From 8872bddc55c667c42e5a5c4eb48f912cb1e50d9b Mon Sep 17 00:00:00 2001 From: Uyanide Date: Sat, 7 Mar 2026 02:59:13 +0100 Subject: [PATCH] add notes directory and update note handling in NotesService --- .../.config/quickshell/.vscode/settings.json | 3 + .../.config/quickshell/Constants/Colors.qml | 1 + .../.config/quickshell/Constants/Paths.qml | 1 + .../Modules/Sidebar/Modules/NoteCard.qml | 8 +- .../.config/quickshell/Services/Init.qml | 2 +- .../quickshell/Services/NotesService.qml | 139 +++++++++--------- 6 files changed, 76 insertions(+), 78 deletions(-) create mode 100644 config/quickshell/.config/quickshell/.vscode/settings.json diff --git a/config/quickshell/.config/quickshell/.vscode/settings.json b/config/quickshell/.config/quickshell/.vscode/settings.json new file mode 100644 index 0000000..7c2feb7 --- /dev/null +++ b/config/quickshell/.config/quickshell/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": false +} diff --git a/config/quickshell/.config/quickshell/Constants/Colors.qml b/config/quickshell/.config/quickshell/Constants/Colors.qml index e43cfe3..4b9be9f 100644 --- a/config/quickshell/.config/quickshell/Constants/Colors.qml +++ b/config/quickshell/.config/quickshell/Constants/Colors.qml @@ -36,6 +36,7 @@ Singleton { property color distro: "#74c7ec" property color transparent: "#00000000" readonly property var cavaList: [mLavender, mBlue, mSky, mCyan, mGreen, mYellow, mOrange, mRed] + readonly property var noteList: [mLavender, mBlue, mSky, mCyan, mGreen, mYellow, mOrange, mRed, mPurple, mPink] function reloadColors(newColors) { if (typeof newColors === "string") { diff --git a/config/quickshell/.config/quickshell/Constants/Paths.qml b/config/quickshell/.config/quickshell/Constants/Paths.qml index 35cd1e3..b04f52b 100644 --- a/config/quickshell/.config/quickshell/Constants/Paths.qml +++ b/config/quickshell/.config/quickshell/Constants/Paths.qml @@ -7,5 +7,6 @@ Singleton { readonly property string cacheDir: Quickshell.shellDir + "/Assets/Cache/" readonly property string configDir: Quickshell.shellDir + "/Assets/Config/" + readonly property string notesDir: Quickshell.env("HOME") + "/Documents/qs-notes/" readonly property string recordingDir: Quickshell.env("HOME") + "/Videos/recordings/" } diff --git a/config/quickshell/.config/quickshell/Modules/Sidebar/Modules/NoteCard.qml b/config/quickshell/.config/quickshell/Modules/Sidebar/Modules/NoteCard.qml index 630966f..9ae86ad 100644 --- a/config/quickshell/.config/quickshell/Modules/Sidebar/Modules/NoteCard.qml +++ b/config/quickshell/.config/quickshell/Modules/Sidebar/Modules/NoteCard.qml @@ -87,7 +87,7 @@ Rectangle { model: NotesService.notesModel delegate: UBox { - property color accentColor: Colors.cavaList[model.colorIdx % Colors.cavaList.length] + property color accentColor: Colors.noteList[model.colorIdx % Colors.noteList.length] width: notesColumn.width implicitHeight: noteLayout.implicitHeight + Style.marginM * 2 @@ -104,13 +104,13 @@ Rectangle { MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton - onClicked: NotesService.openNote(model.noteId) + onClicked: NotesService.openNote(model.notePath) } FileView { id: fileView - path: NotesService.notesDir + "/" + model.noteId + ".txt" + path: model.notePath watchChanges: true onFileChanged: reload() } @@ -140,7 +140,7 @@ Rectangle { iconName: "trash" baseSize: Style.baseWidgetSize * 0.8 colorFg: Colors.mError - onClicked: NotesService.deleteNote(model.noteId) + onClicked: NotesService.deleteNote(model.notePath) } } diff --git a/config/quickshell/.config/quickshell/Services/Init.qml b/config/quickshell/.config/quickshell/Services/Init.qml index cd9d248..bb6f647 100644 --- a/config/quickshell/.config/quickshell/Services/Init.qml +++ b/config/quickshell/.config/quickshell/Services/Init.qml @@ -12,7 +12,7 @@ Singleton { Component.onCompleted: { let mkdirs = ""; - for (const dir of [Paths.cacheDir, Paths.configDir, Paths.recordingDir]) { + for (const dir of [Paths.cacheDir, Paths.configDir, Paths.recordingDir, Paths.notesDir]) { mkdirs += `mkdir -p "${dir}" && `; } mkdirs += "true"; diff --git a/config/quickshell/.config/quickshell/Services/NotesService.qml b/config/quickshell/.config/quickshell/Services/NotesService.qml index 3c52353..decb40a 100644 --- a/config/quickshell/.config/quickshell/Services/NotesService.qml +++ b/config/quickshell/.config/quickshell/Services/NotesService.qml @@ -8,119 +8,112 @@ pragma Singleton Singleton { id: root - property string notesDir: Paths.cacheDir + "/notes" - property var notes: [] property ListModel notesModel - function loadNotes() { - listProcess.running = true; - } - function createNote() { - var id = new Date().getTime().toString(); - var filePath = notesDir + "/" + id + ".txt"; - // Random color index from 0 to 7 - var colorIdx = Math.floor(Math.random() * 8); - createProcess.command = ["sh", "-c", "mkdir -p " + notesDir + " && echo 'New Note' > " + filePath + " && echo " + colorIdx + " > " + filePath + ".color"]; + if (createProcess.running) { + Logger.w("Notes", "Create process is already running, skipping new note creation."); + return ; + } + const fileName = generateFileName(); + const path = Paths.notesDir + "/" + fileName; + createProcess.currentNote = { + "notePath": path, + "colorIdx": strToColor(fileName) + }; + createProcess.command = ["touch", path]; createProcess.running = true; } - function deleteNote(id) { - var filePath = notesDir + "/" + id + ".txt"; - var colorPath = notesDir + "/" + id + ".txt.color"; - deleteProcess.command = ["rm", "-f", filePath, colorPath]; + function deleteNote(path) { + if (deleteProcess.running) { + Logger.w("Notes", "Delete process is already running, skipping note deletion."); + return ; + } + deleteProcess.currentPath = path; + deleteProcess.command = ["rm", "-f", path]; deleteProcess.running = true; } - function openNote(id) { - var filePath = notesDir + "/" + id + ".txt"; - openProcess.command = ["gnome-text-editor", filePath]; - openProcess.running = true; + function openNote(path) { + Quickshell.execDetached(["wezterm", "start", "--", "sh", "-c", `exec nvim "${path}"`]); } - Component.onCompleted: { - loadNotes(); + function strToColor(str) { + let hash = 5381; + for (let i = 0; i < str.length; i++) { + hash = ((hash << 5) + hash) + str.charCodeAt(i); + } + return hash >>> 0; } - Process { - id: openProcess + function generateFileName() { + const timestamp = Time.timestamp; + const randomPart = Math.floor(Math.random() * 1e+06); + return `note_${timestamp}_${randomPart}.txt`; } Process { id: createProcess - onExited: root.loadNotes() + property var currentNote + + onExited: (ret) => { + if (ret !== 0 || !currentNote) { + Logger.e("Notes", `Failed to create note file: ${ret}`); + return ; + } + notesModel.append(currentNote); + const toOpen = currentNote.notePath; + currentNote = null; + root.openNote(toOpen); + } } Process { id: deleteProcess - onExited: root.loadNotes() + property string currentPath + + onExited: (ret) => { + if (ret !== 0) { + Logger.e("Notes", `Failed to delete note file: ${ret}`); + return ; + } + for (let i = 0; i < notesModel.count; i++) { + if (notesModel.get(i).notePath === currentPath) { + notesModel.remove(i); + break; + } + } + currentPath = ""; + } } Process { - id: listProcess + id: initProcess - command: ["sh", "-c", "mkdir -p " + notesDir + " && ls -1 " + notesDir + " | grep '\\.txt$' || true"] + running: true + command: ["sh", "-c", "ls -p -tr " + Paths.notesDir] stdout: StdioCollector { id: listCollector onStreamFinished: { - var files = listCollector.text.split('\n'); + const files = listCollector.text.split('\n'); notesModel.clear(); for (var i = 0; i < files.length; i++) { - if (files[i] === "") + const fileName = files[i].trim(); + if (!fileName || !fileName.endsWith(".txt")) continue; - var id = files[i].replace(".txt", ""); - var contentFile = notesDir + "/" + files[i]; - var colorFile = notesDir + "/" + files[i] + ".color"; - // create an intermediate reader process - readProcessComponent.createObject(root, { - "noteId": id, - "contentFile": contentFile, - "colorFile": colorFile - }).run(); - } - } - } - - } - - Component { - id: readProcessComponent - - Process { - id: p - - property string noteId - property string contentFile - property string colorFile - - function run() { - running = true; - } - - command: ["sh", "-c", "cat " + colorFile + " 2>/dev/null || echo 0; head -n 5 " + contentFile] - - stdout: StdioCollector { - id: readCollector - - onStreamFinished: { - var lines = readCollector.text.split('\n'); - var colorIdx = parseInt(lines[0] || "0"); - lines.shift(); - var contentLines = lines.join('\n').trim(); notesModel.append({ - "noteId": p.noteId, - "title": contentLines, - "colorIdx": colorIdx + "notePath": Paths.notesDir + "/" + fileName, + "colorIdx": strToColor(fileName) }); - p.destroy(); + Logger.d("Notes", "Loaded note: " + fileName); } } - } }