add notes directory and update note handling in NotesService

This commit is contained in:
2026-03-07 02:59:13 +01:00
parent 883eec3e4d
commit 8872bddc55
6 changed files with 76 additions and 78 deletions
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": false
}
@@ -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") {
@@ -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/"
}
@@ -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)
}
}
@@ -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";
@@ -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);
}
}
}
}