master
ts 151 lines 4.79 KB
Raw
1 import { writable } from "svelte/store";
2 import Editor from "../Editor.svelte";
3 import { dialog, invoke } from "@tauri-apps/api";
4 import { saveFile } from "../File";
5 import { warn } from "tauri-plugin-log-api";
6 import { appSettings } from "../../config/config";
7
8 export class Tab {
9 id = 0;
10 activeid = this.id;
11 tablist = [];
12 Tab; // Tab class
13 activeTab = null;
14 hidden = writable(true);
15 isfile = writable(false);
16 tabs = writable([]);
17 constructor (Tab) {
18 this.Tab = Tab;
19 }
20
21 setActive(id: number) {
22 for (let tab of this.tablist) {
23 if (tab.id === id) {
24 this.activeid = id;
25 tab.active = true;
26 if (tab.isfile) {
27 this.isfile.set(true);
28 tab.content.focus();
29 }
30 else {
31 this.isfile.set(false);
32 }
33 this.activeTab = tab;
34 }
35 else {
36 tab.active = false;
37 }
38 }
39 this.tabs.set(this.tablist);
40 this.updateView();
41 }
42 updateTabs() {
43 if (this.tablist.length > 0) {
44 this.hidden.set(false);
45 }
46
47 this.tabs.set(this.tablist);
48 this.setActive(this.id);
49 this.id++;
50 }
51 tabOpen(path: string) {
52 for (const tab of this.tablist) {
53 if (tab.path === path) {
54 this.setActive(tab.id);
55 return true;
56 }
57 }
58 return false;
59 }
60 addTab(path: string = "", label: string = "", content = null) {
61 // dont add tabs that are already open
62 if (this.tabOpen(path)) {
63 return;
64 }
65
66 let tab = new this.Tab(this.id, label, content, path);
67 this.tablist = [...this.tablist, tab];
68
69 this.updateTabs();
70 }
71 async addEditorTab(path: string, label: string = "") {
72 if (this.tabOpen(path)) {
73 return;
74 }
75 let fileData = {text: "", encoding: "UTF-8", extension: "", bom: false, spaces: await appSettings.get("editor.tabSize")};
76 try {
77 fileData = await invoke("read_file", {path: path});
78 if (fileData.spaces === 0) {
79 fileData.spaces = await appSettings.get("editor.tabSize")
80 }
81 } catch (error) {
82 warn(`Can't read file content in ${path}. Setting to empty string. Error: ${error}`, {file: "Tab.ts", line: 79});
83 }
84 let content = new Editor({target: document.getElementById("tabview"), props: {content: fileData.text}});
85 let tab = new this.Tab(this.id, label, content, path);
86 tab.isfile = true;
87 tab.saved = true;
88
89 content.updateFileInfo({
90 "filename": tab.label,
91 "path": tab.path,
92 "fileType": fileData.extension,
93 "language": await content.getLang(fileData.extension),
94 "encoding": fileData.encoding,
95 "hasBom": fileData.bom,
96 "spaces": fileData.spaces,
97 "readonly": false,
98 });
99 this.tablist = [...this.tablist, tab];
100
101 this.updateView();
102
103 this.updateTabs();
104 }
105 async closeTab(tabid: number) {
106 if (this.activeid === tabid) {
107 for (let i = 0; i <= this.tablist.length - 1; i++) {
108 if (this.tablist[i].id === tabid && !this.tablist[i].saved) {
109 if (await dialog.ask(`Do you want to save ${this.tablist[i].label} before closing?`, {type: "warning"})) {
110 await saveFile();
111 }
112 }
113 // set right tab active
114 if (this.tablist[i].id === tabid && this.tablist[i + 1]) {
115 this.setActive(this.tablist[i + 1].id);
116 break;
117 }
118 // set left tab active
119 else if (this.tablist[i].id === tabid && this.tablist[i - 1]) {
120 this.setActive(this.tablist[i - 1].id);
121 break;
122 }
123 }
124 }
125
126 this.tablist.find(t => t.id === tabid).content.$destroy();
127 this.tablist = this.tablist.filter(t => t.id !== tabid);
128 this.tabs.set(this.tablist);
129
130 if (this.tablist.length === 0) {
131 this.hidden.set(true);
132 this.isfile.set(false);
133 this.id = 0;
134 }
135 }
136 async closeAllTabs() {
137 await this.closeTab(this.activeid);
138 const temp = [...this.tablist].reverse(); // js just loves to be inconsistent with its array functions innit
139 for (const tab of temp) {
140 await this.closeTab(tab.id);
141 }
142 }
143 updateView() {
144 for (let tab of this.tablist) {
145 tab.updateView(this.activeid);
146 }
147 }
148 refreshTabList() {
149 this.tabs.set(this.tablist);
150 }
151 }