add file saving and dirty tracking
This commit is contained in:
parent
49cbd4ac35
commit
ec40c759d3
|
|
@ -63,9 +63,16 @@ export class Editor {
|
|||
...searchKeymap,
|
||||
{ key: "Mod-z", run: () => undo(file.target) },
|
||||
{ key: "Mod-shift-z", run: () => redo(file.target) },
|
||||
{
|
||||
key: "Ctrl-s",
|
||||
run: () => {
|
||||
file.saveFile();
|
||||
return true;
|
||||
},
|
||||
},
|
||||
]);
|
||||
this.view = new EditorView({
|
||||
doc: file.rootState.doc,
|
||||
doc: file.rootState.val.doc,
|
||||
dispatch: (trs) => this.dispatch(trs),
|
||||
extensions: [
|
||||
oneDark,
|
||||
|
|
@ -92,7 +99,7 @@ export class Editor {
|
|||
});
|
||||
const language = LanguageDescription.matchFilename(
|
||||
languages,
|
||||
file.filePath,
|
||||
file.filePath.val,
|
||||
)
|
||||
?.load()
|
||||
.then((Lang) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@ const EditorWrapper = (editor: any, del: any, k: any) =>
|
|||
{ class: "flex flex-col" },
|
||||
v.div(
|
||||
{ class: "flex" },
|
||||
v.span({ class: "mx-1 flex-1" }, "Editor " + k),
|
||||
v.span(
|
||||
{ class: "mx-1 flex-1" },
|
||||
() =>
|
||||
editor.val.file.filePath.val +
|
||||
(editor.val.file.isDirty() ? "*" : ""),
|
||||
),
|
||||
u.InlineButton(del, "Close", "❌"),
|
||||
),
|
||||
v.div({ class: "flex-auto h-4" }, editor.val.dom),
|
||||
|
|
|
|||
|
|
@ -7,21 +7,25 @@ import {
|
|||
} from "@codemirror/state";
|
||||
import { history } from "@codemirror/commands";
|
||||
import { Editor } from "./editor";
|
||||
import { State } from "vanjs-core";
|
||||
import van from "vanjs-core";
|
||||
|
||||
const openFiles: { [path: string]: OpenFile } = {};
|
||||
|
||||
export class OpenFile {
|
||||
filePath: string;
|
||||
filePath: State<string>;
|
||||
editors: Editor[];
|
||||
rootState: EditorState;
|
||||
lastSaved?: Text;
|
||||
rootState: State<EditorState>;
|
||||
lastSaved?: State<Text>;
|
||||
|
||||
constructor(cfg: EditorStateConfig) {
|
||||
this.filePath = null;
|
||||
this.filePath = van.state(null);
|
||||
this.editors = [];
|
||||
this.rootState = EditorState.create(cfg).update({
|
||||
this.rootState = van.state(
|
||||
EditorState.create(cfg).update({
|
||||
effects: [StateEffect.appendConfig.of([history()])],
|
||||
}).state;
|
||||
}).state,
|
||||
);
|
||||
}
|
||||
|
||||
static async openFile(filePath?: string): Promise<OpenFile> {
|
||||
|
|
@ -30,24 +34,24 @@ export class OpenFile {
|
|||
}
|
||||
const { content, path } = await window.electronAPI.readFile(filePath);
|
||||
const file = new OpenFile({ doc: content });
|
||||
file.lastSaved = file.rootState.doc;
|
||||
file.lastSaved = van.state(file.rootState.val.doc);
|
||||
file.setPath(path);
|
||||
return file;
|
||||
}
|
||||
|
||||
private setPath(path: string) {
|
||||
delete openFiles[this.filePath];
|
||||
this.filePath = path;
|
||||
delete openFiles[this.filePath?.val];
|
||||
this.filePath.val = path;
|
||||
openFiles[path] = this;
|
||||
}
|
||||
|
||||
async saveFile() {
|
||||
if (this.filePath) {
|
||||
await window.electronAPI.saveFile(
|
||||
this.rootState.doc.toString(),
|
||||
this.filePath,
|
||||
this.rootState.val.doc.toString(),
|
||||
this.filePath.val,
|
||||
);
|
||||
this.lastSaved = this.rootState.doc;
|
||||
this.lastSaved.val = this.rootState.val.doc;
|
||||
} else {
|
||||
await this.saveAs();
|
||||
}
|
||||
|
|
@ -55,11 +59,11 @@ export class OpenFile {
|
|||
|
||||
async saveAs(filePath?: string) {
|
||||
const { path } = await window.electronAPI.saveFile(
|
||||
this.rootState.doc.toString(),
|
||||
this.rootState.val.doc.toString(),
|
||||
filePath,
|
||||
);
|
||||
this.setPath(path);
|
||||
this.lastSaved = this.rootState.doc;
|
||||
this.lastSaved.val = this.rootState.val.doc;
|
||||
}
|
||||
|
||||
// Function to create and return a new EditorView for this file
|
||||
|
|
@ -70,7 +74,7 @@ export class OpenFile {
|
|||
}
|
||||
|
||||
dispatch(trs: TransactionSpec, origin?: Editor) {
|
||||
this.rootState = this.rootState.update(trs).state;
|
||||
this.rootState.val = this.rootState.val.update(trs).state;
|
||||
if (origin) {
|
||||
const es = this.editors.filter((e) => e !== origin);
|
||||
es.forEach((e) => e.dispatch(e.view.state.update(trs), true));
|
||||
|
|
@ -84,12 +88,12 @@ export class OpenFile {
|
|||
get target() {
|
||||
console.log("Getting target");
|
||||
return {
|
||||
state: this.rootState,
|
||||
state: this.rootState.val,
|
||||
dispatch: (tr: TransactionSpec) => this.dispatch(tr),
|
||||
};
|
||||
}
|
||||
|
||||
isDirty(): boolean {
|
||||
return this.lastSaved !== this.rootState.doc;
|
||||
return !this.lastSaved.val.eq(this.rootState.val.doc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue