| 1 | <script lang="ts"> |
| 2 | import { isfile } from "./EditorTabList.svelte"; |
| 3 | import { line_info, language, encoding, spaces } from "./Editor.svelte"; |
| 4 | import { getVersion } from '@tauri-apps/api/app'; |
| 5 | import { onMount } from "svelte"; |
| 6 | import { Terminal as TerminalIcon, Notification as NotificationIcon, TrashCan } from "carbon-icons-svelte"; |
| 7 | import { invoke } from "@tauri-apps/api"; |
| 8 | import Terminal, { clearTerminal, closeTerminal } from "./Terminal.svelte"; |
| 9 | import { workingDir } from "./File"; |
| 10 | import NotificationList from "./Notifications/NotificationList.svelte"; |
| 11 | import { clearNotifications, markAllRead, unreadnotifications } from "./Notifications/notifications"; |
| 12 | |
| 13 | let appVersion = ""; |
| 14 | onMount(async () => { |
| 15 | appVersion = await getVersion(); |
| 16 | }) |
| 17 | |
| 18 | const tools = [ |
| 19 | {name: "Terminal", content: Terminal, icon: TerminalIcon, action: (t) => {spawnTerminal(t)}, options: [ |
| 20 | {name: "Clear Terminal", action: () => {clearTerminal();}}, |
| 21 | {name: "Close Terminal", action: () => { |
| 22 | closeBottomPanel(); |
| 23 | closeTerminal(); |
| 24 | }} |
| 25 | ]}, |
| 26 | {name: "Notifications", content: NotificationList, icon: NotificationIcon, action: (t) => {toggleBottomPanel(t)}, options: [ |
| 27 | {name: "Mark all as Read", action: () => {markAllRead()}}], |
| 28 | buttons: [ |
| 29 | {icon: TrashCan, title: "Clear Notifications", action: () => {clearNotifications()}} |
| 30 | ]} |
| 31 | ] |
| 32 | |
| 33 | async function spawnTerminal(t) { |
| 34 | if ($externalTerminal) { |
| 35 | invoke("open_terminal", {path: $workingDir}); |
| 36 | } |
| 37 | else { |
| 38 | toggleBottomPanel(t); |
| 39 | } |
| 40 | } |
| 41 | </script> |
| 42 | <script lang="ts" context="module"> |
| 43 | import { get, writable } from "svelte/store"; |
| 44 | export let showBottomPanel = writable(false); |
| 45 | export let externalTerminal = writable(false); |
| 46 | let lastTool = writable({tool: null, element: null}); |
| 47 | let activeTools: {tool: any, element: any}[] = []; |
| 48 | let show = false; |
| 49 | |
| 50 | export let editortool = writable({name: "", options: [], buttons: []}); |
| 51 | |
| 52 | export function toggleBottomPanel(tool = null) { |
| 53 | let last = get(lastTool); |
| 54 | if (tool === last.tool) { |
| 55 | show = !show; |
| 56 | showBottomPanel.set(show); |
| 57 | return; |
| 58 | } |
| 59 | if (activeTools.length === 0) { |
| 60 | let element = new tool.content({target: document.getElementById("toolview-container")}); |
| 61 | lastTool.set({tool: tool, element: element}); |
| 62 | activeTools = [...activeTools, {tool: tool, element: element}]; |
| 63 | show = true; |
| 64 | showBottomPanel.set(true); |
| 65 | } |
| 66 | else { |
| 67 | let mountedTool = activeTools.find(f => f.tool === tool); |
| 68 | if (!mountedTool) { |
| 69 | if (last.element) { |
| 70 | last.element.$set({hidden: true}); |
| 71 | } |
| 72 | let element = new tool.content({target: document.getElementById("toolview-container")}); |
| 73 | lastTool.set({tool: tool, element: element}); |
| 74 | activeTools = [...activeTools, {tool: tool, element: element}]; |
| 75 | show = true; |
| 76 | showBottomPanel.set(true); |
| 77 | } |
| 78 | else { |
| 79 | if (last.element) { |
| 80 | last.element.$set({hidden: true}); |
| 81 | mountedTool.element.$set({hidden: false}); |
| 82 | lastTool.set(mountedTool); |
| 83 | showBottomPanel.set(true); |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | if (tool) { |
| 89 | editortool.set({name: tool.name, options: tool.options, buttons: tool.buttons}); |
| 90 | } |
| 91 | } |
| 92 | export function hideBottomPanel() { |
| 93 | show = false; |
| 94 | showBottomPanel.set(false); |
| 95 | } |
| 96 | export function closeBottomPanel() { |
| 97 | show = false; |
| 98 | showBottomPanel.set(false); |
| 99 | let current = activeTools.find(t => t.tool.name === get(editortool).name); |
| 100 | if (current) current.element.$destroy(); |
| 101 | activeTools = activeTools.filter(t => t.tool.name !== get(editortool).name); |
| 102 | editortool.set({name: "", options: [], buttons: []}); |
| 103 | lastTool.set({tool: null, element: null}); |
| 104 | } |
| 105 | export function setTerminalState(value) { |
| 106 | let v = value === true ? true : false; |
| 107 | externalTerminal.set(v); |
| 108 | } |
| 109 | </script> |
| 110 | |
| 111 | <div id="statusbar"> |
| 112 | <div id="title"> |
| 113 | <span>Svara <span id="version">v{appVersion}-alpha</span></span> |
| 114 | <div class="divider"></div> |
| 115 | </div> |
| 116 | <div class="editor-tools"> |
| 117 | {#each tools as tool} |
| 118 | <!-- svelte-ignore a11y-click-events-have-key-events --> |
| 119 | <span class="tool" title={tool.name} on:click={() => {tool.action(tool)}} class:updated={$unreadnotifications}> |
| 120 | <svelte:component this={tool.icon}></svelte:component> |
| 121 | {#if tool.name === "Notifications"} |
| 122 | <span class="notification"></span> |
| 123 | {/if} |
| 124 | </span> |
| 125 | {/each} |
| 126 | </div> |
| 127 | {#if $isfile} |
| 128 | <div class="editor-info"> |
| 129 | <span title="Indentation">Spaces: {$spaces}</span> |
| 130 | <div class="divider"></div> |
| 131 | <span title="Ln: {$line_info.line}, Col: {$line_info.column}">{$line_info.line} : {$line_info.column}</span> |
| 132 | <div class="divider"></div> |
| 133 | <span>{$encoding.value} {$encoding.hasBom === true ? " with BOM" : ""}</span> |
| 134 | <div class="divider"></div> |
| 135 | <span>{$language}</span> |
| 136 | </div> |
| 137 | {/if} |
| 138 | </div> |
| 139 | |
| 140 | <style lang="scss"> |
| 141 | #statusbar { |
| 142 | z-index: 8000; |
| 143 | width: -webkit-fill-available; |
| 144 | display: flex; |
| 145 | align-items: center; |
| 146 | font-size: 0.9rem; |
| 147 | :global(span svg) { |
| 148 | width: 20px; |
| 149 | height: 20px; |
| 150 | } |
| 151 | } |
| 152 | #title { |
| 153 | display: flex; |
| 154 | justify-content: flex-start; |
| 155 | align-items: center; |
| 156 | height: 100%; |
| 157 | span { |
| 158 | height: 100%; |
| 159 | padding: 0 10px; |
| 160 | } |
| 161 | } |
| 162 | .divider { |
| 163 | width: 0.0625rem; |
| 164 | height: 1rem; |
| 165 | } |
| 166 | .editor-tools { |
| 167 | height: 100%; |
| 168 | display: flex; |
| 169 | align-items: center; |
| 170 | justify-content: flex-start; |
| 171 | padding-left: 10px; |
| 172 | .tool { |
| 173 | height: 100%; |
| 174 | padding: 0 5px; |
| 175 | position: relative; |
| 176 | &:hover { |
| 177 | cursor: pointer; |
| 178 | } |
| 179 | &.updated { |
| 180 | .notification { |
| 181 | position: absolute; |
| 182 | width: 8px; |
| 183 | height: 8px; |
| 184 | display: block; |
| 185 | background-color: #4589ff; |
| 186 | border-radius: 50%; |
| 187 | top: 5px; |
| 188 | right: 5px; |
| 189 | border: none; |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | span { |
| 194 | display: flex; |
| 195 | align-items: center; |
| 196 | justify-content: center; |
| 197 | } |
| 198 | } |
| 199 | .editor-info { |
| 200 | display: flex; |
| 201 | justify-content: flex-end; |
| 202 | align-items: center; |
| 203 | flex-grow: 1; |
| 204 | font-size: 13px; |
| 205 | height: 100%; |
| 206 | span { |
| 207 | padding: 0 7px; |
| 208 | height: 100%; |
| 209 | display: flex; |
| 210 | align-items: center; |
| 211 | } |
| 212 | } |
| 213 | #version { |
| 214 | font-size: 0.7rem; |
| 215 | padding: 0 !important; |
| 216 | color: #6d6d6d; |
| 217 | } |
| 218 | </style> |