Basic file opening support

This commit is contained in:
Quinten Kock 2025-10-28 00:48:55 +01:00
parent 001d215b0e
commit e2a7435157
4 changed files with 41 additions and 8 deletions

View File

@ -8,7 +8,7 @@ import { OpenFile } from "./filestate";
const fixedHeightEditor = EditorView.theme({ const fixedHeightEditor = EditorView.theme({
"&": { "&": {
height: "100%", height: "100%",
minHeight: "0px", minHeight: "1em",
resize: "horizontal", resize: "horizontal",
overflow: "auto", overflow: "auto",
width: "600px", width: "600px",
@ -19,6 +19,13 @@ const fixedHeightEditor = EditorView.theme({
".cm-scroller": { overflow: "auto scroll" }, ".cm-scroller": { overflow: "auto scroll" },
}); });
const testTheme = EditorView.theme({
"&": {
width: "600px",
resize: "horizontal",
},
});
export class Editor { export class Editor {
view: EditorView; view: EditorView;
file: OpenFile; file: OpenFile;
@ -40,7 +47,12 @@ export class Editor {
this.view = new EditorView({ this.view = new EditorView({
doc: file.rootState.doc, doc: file.rootState.doc,
dispatch: (trs) => this.dispatch(trs), dispatch: (trs) => this.dispatch(trs),
extensions: [oneDark, fixedHeightEditor, kmap], extensions: [
oneDark,
fixedHeightEditor,
kmap,
EditorView.lineWrapping,
],
}); });
} }

View File

@ -25,8 +25,9 @@ export function addEditor(file: OpenFile) {
const editor = file.createEditor(); const editor = file.createEditor();
editors[currentTab.val].push(vanX.noreactive(editor)); editors[currentTab.val].push(vanX.noreactive(editor));
} }
export function addTab() {
editors.push([]); export function addTab(file?: OpenFile) {
editors.push(file ? [file] : []);
} }
const TabHeader = (tab: any, del: any, k: any) => const TabHeader = (tab: any, del: any, k: any) =>

View File

@ -3,6 +3,7 @@ import {
EditorStateConfig, EditorStateConfig,
TransactionSpec, TransactionSpec,
StateEffect, StateEffect,
Text,
} from "@codemirror/state"; } from "@codemirror/state";
import { history } from "@codemirror/commands"; import { history } from "@codemirror/commands";
import { Editor } from "./editor"; import { Editor } from "./editor";
@ -13,6 +14,7 @@ export class OpenFile {
filePath: string; filePath: string;
editors: Editor[]; editors: Editor[];
rootState: EditorState; rootState: EditorState;
lastSaved?: Text;
constructor(cfg: EditorStateConfig) { constructor(cfg: EditorStateConfig) {
this.filePath = null; this.filePath = null;
@ -22,9 +24,13 @@ export class OpenFile {
}).state; }).state;
} }
static async openFile(filePath?: string) { static async openFile(filePath?: string): Promise<OpenFile> {
if (filePath && openFiles[filePath]) {
return openFiles[filePath];
}
const { content, path } = await window.electronAPI.readFile(filePath); const { content, path } = await window.electronAPI.readFile(filePath);
const file = new OpenFile({ doc: content }); const file = new OpenFile({ doc: content });
file.lastSaved = file.rootState.doc;
file.setPath(path); file.setPath(path);
return file; return file;
} }
@ -41,6 +47,7 @@ export class OpenFile {
this.rootState.doc.toString(), this.rootState.doc.toString(),
this.filePath, this.filePath,
); );
this.lastSaved = this.rootState.doc;
} else { } else {
await this.saveAs(); await this.saveAs();
} }
@ -52,6 +59,7 @@ export class OpenFile {
filePath, filePath,
); );
this.setPath(path); this.setPath(path);
this.lastSaved = this.rootState.doc;
} }
// Function to create and return a new EditorView for this file // Function to create and return a new EditorView for this file
@ -62,8 +70,6 @@ export class OpenFile {
} }
dispatch(trs: TransactionSpec, origin?: Editor) { dispatch(trs: TransactionSpec, origin?: Editor) {
console.log("Dispatching trs", trs, "to", this.editors, "from", origin);
console.log(this.rootState);
this.rootState = this.rootState.update(trs).state; this.rootState = this.rootState.update(trs).state;
if (origin) { if (origin) {
const es = this.editors.filter((e) => e !== origin); const es = this.editors.filter((e) => e !== origin);
@ -82,4 +88,8 @@ export class OpenFile {
dispatch: (tr: TransactionSpec) => this.dispatch(tr), dispatch: (tr: TransactionSpec) => this.dispatch(tr),
}; };
} }
isDirty(): boolean {
return this.lastSaved !== this.rootState.doc;
}
} }

View File

@ -1,6 +1,8 @@
import van from "vanjs-core"; import van from "vanjs-core";
const v = van.tags; const v = van.tags;
import type { FolderTree } from "../types/global"; import type { FolderTree } from "../types/global";
import { addEditor } from "./editorgrid";
import { OpenFile } from "./filestate";
import * as u from "./utils"; import * as u from "./utils";
@ -38,7 +40,15 @@ export const FolderTreeView = () => {
// TODO: determine if lazy DOM creation is better or not. // TODO: determine if lazy DOM creation is better or not.
// Alternatively, investigate lazy FS traversal in main. // Alternatively, investigate lazy FS traversal in main.
const FsItemView = (tree: FolderTree): HTMLElement => { const FsItemView = (tree: FolderTree): HTMLElement => {
if (tree.type === "file") return v.p(v.span("📄"), tree.name); if (tree.type === "file")
return v.p(
{
onclick: async () =>
addEditor(await OpenFile.openFile(tree.path)),
},
v.span("📄"),
tree.name,
);
const isOpen = van.state(false); const isOpen = van.state(false);
const children = () => const children = () =>
isOpen.val isOpen.val