@setoelkahfi / svara / commits / 82f50df

Main view restructure

mellobacon committed Nov 25, 2022 at 14:05 UTC 82f50dfdfe52002eada81d37682491af926eb01c
11 files changed +814 -6
src/App.svelte
+2 -3
@@ -1,7 +1,7 @@
1 <script lang="ts">
2 import Header from "./components/Header/Header.svelte";
3 import Sidebar from "./components/Sidebar/Sidebar.svelte";
4 - import MainContainer from "./components/Content/MainContainer.svelte";
4 + import MainContainer from "./components/View/MainView.svelte";
5 import "carbon-components-svelte/css/g100.css";
6 import { Pane, Splitpanes } from 'svelte-splitpanes';
7 import SidebarView from "./components/Sidebar/SidebarView.svelte";
@@ -13,7 +13,7 @@
13 <Sidebar />
14 <Splitpanes theme="editor-pane">
15 {#if $showsidebarview}
16 - <Pane size={25} snapSize={5}>
16 + <Pane size={25} minSize={10}>
17 <SidebarView title={$tool.tabname} content={$tool.content}></SidebarView>
18 </Pane>
19 {/if}
@@ -25,6 +25,5 @@
25 <style>
26 #main {
27 display: flex;
28 - height: calc(100% - 2rem);
28 }
29 </style>
\ No newline at end of file
src/components/Editor/CodeMirrorEditor.svelte new
+106
@@ -0,0 +1,106 @@
1 +<script lang="ts">
2 + import { createEventDispatcher, onMount, tick } from "svelte";
3 + import { basicSetup } from "codemirror";
4 + import { EditorView, keymap } from "@codemirror/view";
5 + import { indentWithTab } from "@codemirror/commands";
6 + import { EditorState, Compartment } from "@codemirror/state";
7 + import { default_theme } from "./scripts/DefaultTheme";
8 + import { line_info } from "./scripts/Editor";
9 +
10 + export let hidden = false;
11 + let editorElement;
12 + let editorView: EditorView;
13 + export let content = "";
14 + export let lang = new Compartment();
15 +
16 + export function setLanguageMode(mode) {
17 + editorView.dispatch({
18 + effects: lang.reconfigure(mode)
19 + })
20 + }
21 + export async function focus() {
22 + await tick();
23 + await tick();
24 + editorView.focus();
25 + getLineInfo();
26 + }
27 + function getLineInfo() {
28 + let linenumber = editorView.state.doc.lineAt(editorView.state.selection.main.head).number;
29 + let colnumber = editorView.state.selection.ranges[0].head - editorView.state.doc.lineAt(editorView.state.selection.main.head).from
30 + line_info.set({line: linenumber.toString(), col: (colnumber + 1).toString()})
31 + }
32 + async function updateDom() {
33 + await tick();
34 + let filecontent = "";
35 + for (let text of editorView.state.doc) {
36 + filecontent += `${text} `;
37 + }
38 + dispatch("input", filecontent);
39 + }
40 + let dispatch = createEventDispatcher();
41 +
42 + onMount(() => {
43 + editorView = new EditorView({
44 + state: EditorState.create({
45 + extensions: [basicSetup, default_theme, keymap.of([indentWithTab]), lang.of([])],
46 + doc: content
47 + }),
48 + parent: editorElement,
49 + });
50 + });
51 +</script>
52 +<div class="editor" class:hidden bind:this={editorElement}
53 +on:input={async (e) => {
54 + await updateDom();
55 + getLineInfo();
56 +}}
57 +on:keydown={async (e) => {
58 + let key = e.code;
59 + switch(key) {
60 + case "Backspace": case "Enter":
61 + await updateDom();
62 + getLineInfo();
63 + break;
64 + case "ArrowRight": case "ArrowLeft": case "ArrowDown": case "ArrowUp":
65 + getLineInfo();
66 + break;
67 + }
68 +}}
69 +on:mousedown = {(e) => {
70 + getLineInfo();
71 +}}
72 + />
73 +
74 +<style>
75 + .editor {
76 + height: 100%;
77 + width: 100%;
78 + }
79 + .hidden {
80 + display: none;
81 + }
82 + :global(.cm-editor:focus),
83 + :global(.cm-focused) {
84 + outline: none !important;
85 + }
86 + :global(.cm-editor),
87 + :global(.cm-wrap) {
88 + height: 100%;
89 + }
90 + :global(.cm-scroller) {
91 + overflow-y: overlay;
92 + overflow-x: overlay !important;
93 + }
94 + :global(.cm-scroller)::-webkit-scrollbar {
95 + width: 20px;
96 + }
97 + :global(.cm-scroller)::-webkit-scrollbar-thumb {
98 + background-color: #4c4c4c38;;
99 + }
100 + :global(.cm-scroller)::-webkit-scrollbar-corner {
101 + background-color: transparent;
102 + }
103 + :global(.cm-content) {
104 + padding: 0 !important;
105 + }
106 +</style>
src/components/Editor/Editor.svelte new
+17
@@ -0,0 +1,17 @@
1 +<script lang="ts">
2 + import { hidden } from "../Tabs/scripts/Tab";
3 +</script>
4 +
5 +<div id="tabview" class:hidden={$hidden}></div>
6 +
7 +<style>
8 + #tabview {
9 + width: 100%;
10 + height: 100%;
11 + background-color: #1C1C1C;
12 + z-index: 1;
13 + }
14 + .hidden {
15 + visibility: hidden;
16 + }
17 +</style>
\ No newline at end of file
src/components/Editor/scripts/DefaultTheme.ts new
+209
@@ -0,0 +1,209 @@
1 +import { EditorView } from "@codemirror/view";
2 +import type { Extension } from "@codemirror/state";
3 +import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
4 +import { tags as t } from "@lezer/highlight";
5 +
6 +const bg = "#1c1c1c",
7 + cl = "#282a2e",
8 + sel = "#373b41",
9 + fg = "#c5c8c6",
10 + com = "#969896",
11 + red = "#cc6666",
12 + orange = "#fff9f5",
13 + green = "#b5bd68",
14 + aqua = "#8abeb7",
15 + blue = "#81a2be",
16 + purple = "#b294bb";
17 +
18 +const defaultTheme = EditorView.theme(
19 + {
20 + "*": {
21 + fontFamily: '"Ubuntu Mono", monospace'
22 + },
23 +
24 + "&": {
25 + color: fg,
26 + backgroundColor: bg
27 + },
28 +
29 + ".cm-content": {
30 + caretColor: orange
31 + },
32 +
33 + "&.cm-focused .cm-cursor": {
34 + borderLeftColor: orange
35 + },
36 +
37 + "&.cm-focused .cm-selectionBackground, .cm-selectionBackground, ::selection": {
38 + backgroundColor: sel
39 + },
40 +
41 + ".cm-panels": {
42 + backgroundColor: bg,
43 + color: fg
44 + },
45 +
46 + ".cm-panels.cm-panels-top": {
47 + borderBottom: "2px solid black"
48 + },
49 +
50 + ".cm-panels.cm-panels-bottom": {
51 + borderTop: "2px solid black"
52 + },
53 +
54 + ".cm-searchMatch": {
55 + backgroundColor: "#72a1ff59",
56 + outline: "1px solid #457dff"
57 + },
58 +
59 + ".cm-searchMatch.cm-searchMatch-selected": {
60 + backgroundColor: "#6199ff2f"
61 + },
62 +
63 + ".cm-activeLine": {
64 + backgroundColor: "transparent",
65 + boxShadow: "inset 0px 0px 0 0.5px #3f3f3f"
66 + },
67 +
68 + ".cm-selectionMatch": {
69 + backgroundColor: "#aafe661a"
70 + },
71 +
72 + ".cm-matchingBracket, .cm-nonmatchingBracket": {
73 + backgroundColor: "#bad0f847",
74 + outline: "1px solid #515a6b"
75 + },
76 +
77 + ".cm-gutters": {
78 + backgroundColor: bg,
79 + color: com,
80 + border: "none"
81 + },
82 +
83 + ".cm-activeLineGutter": {
84 + backgroundColor: bg,
85 + color: "white"
86 + },
87 +
88 + ".cm-foldPlaceholder": {
89 + backgroundColor: "transparent",
90 + border: "none",
91 + color: "#ddd"
92 + },
93 +
94 + ".cm-tooltip": {
95 + border: "1px solid #181a1f",
96 + backgroundColor: bg
97 + },
98 + ".cm-tooltip-autocomplete": {
99 + "& > ul > li[aria-selected]": {
100 + backgroundColor: bg,
101 + color: fg
102 + }
103 + }
104 + },
105 + { dark: true }
106 +);
107 +
108 +const defaultHighlightStyle = HighlightStyle.define([
109 + {
110 + tag: t.keyword,
111 + color: purple
112 + },
113 +
114 + {
115 + tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
116 + color: red
117 + },
118 +
119 + {
120 + tag: [t.function(t.variableName), t.labelName],
121 + color: blue
122 + },
123 +
124 + {
125 + tag: [t.color, t.constant(t.name), t.standard(t.name)],
126 + color: orange
127 + },
128 +
129 + {
130 + tag: [t.definition(t.name), t.separator],
131 + color: fg
132 + },
133 +
134 + {
135 + tag: [
136 + t.typeName,
137 + t.className,
138 + t.number,
139 + t.changed,
140 + t.annotation,
141 + t.modifier,
142 + t.self,
143 + t.namespace
144 + ],
145 + color: orange
146 + },
147 +
148 + {
149 + tag: [
150 + t.operator,
151 + t.operatorKeyword,
152 + t.url,
153 + t.escape,
154 + t.regexp,
155 + t.link,
156 + t.special(t.string)
157 + ],
158 + color: aqua
159 + },
160 +
161 + {
162 + tag: [t.meta, t.comment],
163 + color: com
164 + },
165 +
166 + {
167 + tag: t.strong,
168 + fontWeight: "bold"
169 + },
170 +
171 + {
172 + tag: t.emphasis,
173 + fontStyle: "italic"
174 + },
175 +
176 + {
177 + tag: t.strikethrough,
178 + textDecoration: "line-through"
179 + },
180 +
181 + {
182 + tag: t.link,
183 + color: com,
184 + textDecoration: "underline"
185 + },
186 +
187 + {
188 + tag: t.heading,
189 + fontWeight: "bold",
190 + color: red
191 + },
192 +
193 + {
194 + tag: [t.atom, t.bool, t.special(t.variableName)],
195 + color: orange
196 + },
197 +
198 + {
199 + tag: [t.processingInstruction, t.string, t.inserted],
200 + color: green
201 + },
202 +
203 + {
204 + tag: t.invalid,
205 + color: "#ffffff"
206 + }
207 +]);
208 +
209 +export const default_theme: Extension = [defaultTheme, syntaxHighlighting(defaultHighlightStyle)];
\ No newline at end of file
src/components/Editor/scripts/Editor.ts new
+26
@@ -0,0 +1,26 @@
1 +import langlist from "../../../scripts/languages/languages.json";
2 +import { languages } from "@codemirror/language-data";
3 +import { writable } from 'svelte/store';
4 +
5 +export let line_info = writable({line: "-", col: "-"});
6 +
7 +let keys = Object.keys(langlist);
8 +export function getLang(ext: string) {
9 + for (let key of keys) {
10 + let extensions = langlist[key].extensions;
11 + if (extensions && extensions.includes(`.${ext}`)) {
12 + return `${key}`;
13 + }
14 + }
15 +}
16 +
17 +export async function getLangMode(language: string) {
18 + // TODO: So apparently not every language is supported in CodeMirror. I need to find a way to support that
19 + let mode = languages.find(l => l.name === language);
20 + if (mode) {
21 + return await mode.load();
22 + }
23 + else {
24 + return [];
25 + }
26 +}
\ No newline at end of file
src/components/Tabs/EditorTabs.svelte new
+49
@@ -0,0 +1,49 @@
1 +<script lang="ts">
2 + import { Sortable } from "sortablejs";
3 + import { onMount } from "svelte";
4 + import Tab from "./Tab.svelte";
5 + import { hidden, tabs } from "./scripts/Tab";
6 + let tabcontainer;
7 + onMount(() => {
8 + Sortable.create(tabcontainer, {
9 + draggable: ".tab",
10 + animation: 150,
11 + forceFallback: true,
12 + easing: "cubic-bezier(1, 0, 0, 1)",
13 + sort: true
14 + })
15 + })
16 +</script>
17 +
18 +<div id="editor-tabs" class:hidden={$hidden}>
19 + <div id="tablist" bind:this={tabcontainer}>
20 + {#each $tabs as tab}
21 + <Tab label={tab.label} path={tab.path} active={tab.active} id={tab.id} unsaved={tab.saved} />
22 + {/each}
23 + </div>
24 +</div>
25 +
26 +<style lang="scss">
27 + .hidden {
28 + visibility: hidden;
29 + }
30 + #editor-tabs {
31 + width: -webkit-fill-available;
32 + display: flex;
33 + align-items: center;
34 + justify-content: space-between;
35 + position: absolute;
36 + box-shadow: inset 0px -1px 0 0 #333;
37 + #tablist {
38 + position: absolute;
39 + height: 100%;
40 + display: flex;
41 + &::-webkit-scrollbar {
42 + height: 4px;
43 + }
44 + &::-webkit-scrollbar-thumb {
45 + background-color: #ffffff12;
46 + }
47 + }
48 + }
49 +</style>
src/components/Tabs/Tab.svelte new
+109
@@ -0,0 +1,109 @@
1 +<script lang="ts">
2 + import { closeTab, setActive } from "./scripts/Tab";
3 + import TabMenu from "./TabMenu.svelte";
4 + export let id = 0;
5 + export let label = "Untitled-1";
6 + export let path = "";
7 + export let active = false;
8 + export let unsaved = false;
9 + let tab;
10 +</script>
11 +<div bind:this={tab} title={path} id={`tab-${id}`} class="tab" class:tab-active={active} class:unsaved={unsaved}>
12 + <!-- svelte-ignore a11y-click-events-have-key-events -->
13 + <div class="tab-content" on:click = {
14 + () => {
15 + setActive(id);
16 + }
17 + }>
18 + <span class="tab-label">{label}</span>
19 + {#if unsaved}
20 + <span></span>
21 + {/if}
22 + </div>
23 + <!-- svelte-ignore a11y-click-events-have-key-events -->
24 + <div class="close-tab" on:click={() => {
25 + closeTab(id);
26 + }}>
27 + <span></span>
28 + </div>
29 +</div>
30 +
31 +<TabMenu target={tab} id={id} filename={label} filepath={path} />
32 +
33 +<style lang="scss">
34 + .tab {
35 + background-color: #1c1c1c;
36 + height: 100%;
37 + min-width: min-content;
38 + flex-grow: 0.05;
39 + display: flex;
40 + overflow: hidden;
41 + color: white;
42 + justify-content: space-between;
43 + align-items: center;
44 + cursor: pointer;
45 + padding: 0 10px;
46 + box-shadow: inset 0px -0.5px 0 0 #bdd4ff;
47 + &:not(.active):hover {
48 + background-color: #2b2b2b;
49 + }
50 + }
51 + .tab:not(.tab-active):hover {
52 + background-color: #2b2b2b;
53 + }
54 + .tab-content::-webkit-scrollbar {
55 + height: 4px;
56 + }
57 + .tab-content::-webkit-scrollbar {
58 + background-color: #1b5fdd;
59 + }
60 + .tab-content {
61 + display: flex;
62 + justify-content: center;
63 + align-items: center;
64 + overflow-x: overlay;
65 + overflow-y: hidden;
66 + height: 100%;
67 + padding-left: 2px;
68 + :nth-child(2) {
69 + display: block;
70 + width: 6px;
71 + height: 6px;
72 + background-color: white;
73 + border-radius: 50%;
74 + left: -11px;
75 + top: 0.5px;
76 + position: relative;
77 + }
78 + }
79 + .tab-active {
80 + background-color: rgb(28, 28, 28);
81 + box-shadow: inset 0px -2px 0 0 #1b5fdd !important;
82 + }
83 + .tab-active.unsaved {
84 + box-shadow: inset 0px -2px 0 0 #dd6f1b !important;
85 + }
86 + .unsaved {
87 + box-shadow: inset 0px -0.5px 0 0 #dd6f1b;
88 + }
89 + .tab-label {
90 + text-overflow: ellipsis;
91 + white-space: nowrap;
92 + padding-right: 20px;
93 + }
94 + .close-tab span::before {
95 + content: "\2715";
96 + font-size: 13px;
97 + }
98 + .close-tab span:hover {
99 + color: gray;
100 + }
101 + .close-tab {
102 + width: 2rem;
103 + margin-left: -1rem;
104 + display: flex;
105 + justify-content: center;
106 + position: relative;
107 + left: 10px;
108 + }
109 +</style>
\ No newline at end of file
src/components/Tabs/TabMenu.svelte new
+57
@@ -0,0 +1,57 @@
1 +<script lang="ts">
2 + import { ContextMenuOption } from "carbon-components-svelte";
3 + import ContextMenu from "../ContextMenu/ContextMenu.svelte";
4 + import CopyFile from "carbon-icons-svelte/lib/CopyFile.svelte";
5 + import Cut from "carbon-icons-svelte/lib/Cut.svelte";
6 + import { clipboard, path, invoke } from "@tauri-apps/api";
7 + import { closeTab, setActive } from "./scripts/Tab";
8 + export let id: number;
9 + export let target;
10 + export let filename: string;
11 + export let filepath: string;
12 +
13 + async function copyToClipboard(input) {
14 + await clipboard.writeText(input);
15 + }
16 +</script>
17 +
18 +<ContextMenu {target}>
19 + <ContextMenuOption indented icon={CopyFile} labelText="Close Tab" on:click={() => {
20 + closeTab(id);
21 + }}>
22 + <span class="contextshortcut" slot="shortcutText">Ctrl + F4</span>
23 + </ContextMenuOption>
24 + <ContextMenuOption indented icon={Cut} labelText="Close Others" on:click={() => {
25 + let tabs = document.getElementsByClassName("tab");
26 + for (const tab of tabs) {
27 + let t = tab.id;
28 + let tabid = parseInt(t.split("-").pop());
29 + if (tabid !== id) {
30 + closeTab(tabid);
31 + }
32 + }
33 + setActive(id);
34 + }} ></ContextMenuOption>
35 + <ContextMenuOption indented labelText="Close Saved Tabs" on:click={() => {}}>
36 + <span class="contextshortcut" slot="shortcutText">Ctrl + X S</span>
37 + </ContextMenuOption>
38 + <ContextMenuOption indented labelText="Close All Tabs" on:click={() => {}}>
39 + <span class="contextshortcut" slot="shortcutText">Ctrl + X A</span>
40 + </ContextMenuOption>
41 + <!--TODO: Make this relative instead of file name. Am lazy-->
42 + <ContextMenuOption on:click={() => copyToClipboard(filename)}>
43 + <span slot="labelText" title={filename}>Copy File Name</span>
44 + </ContextMenuOption>
45 + <ContextMenuOption on:click={() => copyToClipboard(filepath)}>
46 + <span slot="labelText" title={filepath}>Copy Absolute Path</span>
47 + </ContextMenuOption>
48 + <ContextMenuOption labelText="Show in Explorer" on:click={() => {
49 + invoke("open_in_explorer",{ path:filepath})
50 + }}></ContextMenuOption>
51 +</ContextMenu>
52 +
53 +<style>
54 + .contextshortcut {
55 + color: #8c8c8c;
56 + }
57 +</style>
\ No newline at end of file
src/components/Tabs/scripts/Tab.ts new
+196
@@ -0,0 +1,196 @@
1 +import { writable } from 'svelte/store';
2 +import { EditorFile, getFileData } from '../../../scripts/EditorFile'
3 +import CodeMirrorEditor from '../../Editor/CodeMirrorEditor.svelte';
4 +import { writeFile } from '@tauri-apps/api/fs';
5 +import { getLang, getLangMode } from '../../Editor/scripts/Editor';
6 +
7 +let id = 0;
8 +let activeid;
9 +
10 +export let file_language = writable("");
11 +export let linefeed = writable("");
12 +export let tablist: Tab[] = [];
13 +export let tabs = writable([]);
14 +export let hidden = writable(true);
15 +export let isfile = writable(false);
16 +
17 +class Tab {
18 + id: number;
19 + label: string;
20 + active: boolean;
21 + constructor(id: number, label: string = "") {
22 + this.id = id;
23 + this.label = label === "" ? `Untitled-${id}` : label;
24 + }
25 +}
26 +
27 +export class FileTab extends Tab {
28 + path: string;
29 + language: string = "Plain Text";
30 + linefeed: string;
31 + saved: boolean = true;
32 + editor: CodeMirrorEditor | null;
33 + editorcontent: string;
34 + constructor(id: number, file: EditorFile, editor, saved: boolean = true) {
35 + super(id, file.filename);
36 + this.path = file.path;
37 + this.saved = saved;
38 + this.editor = editor;
39 + this.editorcontent = file.content;
40 +
41 + let filepath = file.path.split(".");
42 + let extension = "txt";
43 + if (filepath.length !== 1) {
44 + extension = filepath.at(-1);
45 + }
46 +
47 + this.language = getLang(extension)
48 + this.linefeed = file.linefeed;
49 +
50 + let _ = undefined;
51 + this.editor.$on("input", (e) => {
52 + clearTimeout(_);
53 + _ = setTimeout(() => {
54 + this.editorcontent = e.detail;
55 + if (this.path !== "") {
56 + writeFile(this.path, e.detail);
57 + console.log(`${this.label} saved`);
58 + if (!this.saved) {
59 + this.saved = true;
60 + setActive(this.id);
61 + }
62 + }
63 + else {
64 + this.saved = false;
65 + }
66 + }, 1000)
67 + })
68 + }
69 +
70 + async setLanguage(lang: string) {
71 + let mode = await getLangMode(lang);
72 + this.editor.setLanguageMode(mode);
73 +
74 + file_language.set(lang);
75 + this.language = lang;
76 + }
77 + setFile(file: EditorFile) {
78 + this.label = file.filename === "" ? `Untitled-${this.id}` : file.filename;
79 + this.path = file.path;
80 + let filepath = file.path.split(".");
81 + let extension = "txt";
82 + if (filepath.length !== 1) {
83 + extension = filepath.at(-1);
84 + }
85 + this.language = getLang(extension);
86 +
87 + this.linefeed = file.linefeed;
88 + }
89 + focusTab() {
90 + file_language.set(this.language);
91 + linefeed.set(this.linefeed);
92 + this.editor.focus();
93 + }
94 + updateEditorVisibility(id: number) {
95 + this.editor.$set({ hidden: !(this.id === id) })
96 + }
97 +}
98 +export class SettingsTab extends Tab {
99 + content: string;
100 + constructor(id: number, label: string, content: string) {
101 + super(id, label);
102 + this.content = content;
103 + }
104 +}
105 +
106 +export async function addFileTab(path = "") {
107 + for (let t of tablist) {
108 + if ((t as FileTab).path === path) {
109 + setActive(t.id);
110 + }
111 + }
112 + let file = await getFileData(path);
113 + let editor = new CodeMirrorEditor({ target: document.getElementById("tabview"), props: { content: file.content } });
114 + let tab = new FileTab(id, file, editor, path !== "");
115 + await tab.setLanguage(tab.language);
116 + tablist = [...tablist, tab];
117 +
118 + refreshTabs();
119 +}
120 +
121 +export function addSettingsTab() {
122 + let content = "";
123 + let tab = new SettingsTab(id, "Settings", content);
124 + tablist = [...tablist, tab];
125 +
126 + refreshTabs();
127 +}
128 +
129 +export function setActive(id: number) {
130 + for (let tab of tablist) {
131 + if (tab.id === id) {
132 + activeid = id;
133 + tab.active = true;
134 + if (tab instanceof FileTab) {
135 + let t = tab as FileTab;
136 + isfile.set(true);
137 + t.focusTab();
138 + }
139 + else {
140 + isfile.set(false);
141 + }
142 + }
143 + else {
144 + tab.active = false;
145 + }
146 + }
147 + tabs.set(tablist);
148 + updateEditorVisibility();
149 +}
150 +
151 +export function closeTab(tabid: number) {
152 + if (activeid === tabid) {
153 + for (let i = 0; i <= tablist.length - 1; i++) {
154 + if (tablist[i].id === tabid && tablist[i + 1]) {
155 + setActive(tablist[i + 1].id);
156 + break;
157 + }
158 + else if (tablist[i].id === tabid && tablist[i - 1]) {
159 + setActive(tablist[i - 1].id);
160 + break;
161 + }
162 + }
163 + }
164 +
165 + for (let tab of tablist) {
166 + if (tab.id === tabid) {
167 + (tab as FileTab).editor.$destroy();
168 + break;
169 + }
170 + }
171 + tablist = tablist.filter(t => t.id !== tabid);
172 + tabs.set(tablist);
173 +
174 + updateEditorVisibility();
175 + if (tablist.length === 0) {
176 + hidden.set(true);
177 + isfile.set(false);
178 + id = 0;
179 + }
180 +}
181 +
182 +function refreshTabs() {
183 + if (tablist.length > 0) {
184 + hidden.set(false);
185 + isfile.set(true);
186 + }
187 + tabs.set(tablist);
188 + setActive(id);
189 + id++;
190 +}
191 +
192 +function updateEditorVisibility() {
193 + for (let tab of tablist) {
194 + (tab as FileTab).updateEditorVisibility(activeid);
195 + }
196 +}
src/components/View/MainView.svelte new
+40
@@ -0,0 +1,40 @@
1 +<script lang="ts">
2 + import { Splitpanes, Pane } from "svelte-splitpanes";
3 + import Editor from "../Editor/Editor.svelte";
4 + import Footer, { showpanel, tool } from "../Footer/Footer.svelte";
5 + import EditorTabs from "../Tabs/EditorTabs.svelte";
6 +
7 + let panelsize = 20;
8 + function updatePanelSize(event) {
9 + if ($showpanel) {
10 + panelsize = event.detail[1].size;
11 + }
12 + }
13 +</script>
14 +
15 +<div id="container">
16 + <Splitpanes theme="editor-pane" horizontal on:resized={updatePanelSize}>
17 + <Pane>
18 + <div class="main">
19 + <EditorTabs />
20 + <Editor />
21 + </div>
22 + </Pane>
23 + {#if $showpanel}
24 + <Pane bind:size={panelsize} minSize={4}><div class="panel">{$tool.content}</Pane>
25 + {/if}
26 + </Splitpanes>
27 + <Footer></Footer>
28 +</div>
29 +
30 +<style>
31 + #container {
32 + height: 100%;
33 + overflow: hidden;
34 + }
35 + .main {
36 + background-image: url("/assets/images/Watermark(3).png");
37 + background-repeat: no-repeat;
38 + background-position: center;
39 + }
40 +</style>
\ No newline at end of file
src/scripts/EditorFile.ts
+3 -3
@@ -1,8 +1,8 @@
1 import { readTextFile, writeFile } from "@tauri-apps/api/fs";
2 import { sep } from "@tauri-apps/api/path";
3 import { dialog } from "@tauri-apps/api";
4 -import { setActive, tablist } from "../components/Content/Editor/scripts/Tab";
5 -import type { FileTab } from "../components/Content/Editor/scripts/Tab";
4 +import { setActive, tablist } from "../components/Tabs/scripts/Tab";
5 +import type { FileTab } from "../components/Tabs/scripts/Tab";
6
7 export class EditorFile {
8 filename: string;
@@ -17,7 +17,7 @@ export class EditorFile {
17 }
18 }
19
20 -export async function openFile() {
20 +export async function getFile() {
21 let path = await dialog.open() as string;
22 if (path === undefined) return;
23 return path;