Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions data/ui/notes.ui
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@
<attribute name="label" translatable="yes">Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Import Notes…</attribute>
<attribute name="action">app.import</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Export All Notes…</attribute>
<attribute name="action">app.export</attribute>
</item>
<item>
<attribute name="label" translatable="yes">About Sticky Notes</attribute>
<attribute name="action">app.about</attribute>
Expand Down
94 changes: 93 additions & 1 deletion src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import Gtk from "gi://Gtk?version=4.0";
import Gdk from "gi://Gdk?version=4.0";

import { StickyNotes } from "./notes.js";
import { Note, settings } from "./util.js";
import { INote, Note, settings } from "./util.js";
import {
delete_note,
load_notes,
Expand Down Expand Up @@ -293,6 +293,14 @@ export class Application extends Adw.Application {
save.connect("activate", () => this.save());
this.add_action(save);

const export_notes = new Gio.SimpleAction({ name: "export" });
export_notes.connect("activate", () => this.export_notes());
this.add_action(export_notes);

const import_notes = new Gio.SimpleAction({ name: "import" });
import_notes.connect("activate", () => this.import_notes());
this.add_action(import_notes);

this.add_action(settings.create_action("color-scheme"));

this.set_accels_for_action("app.quit", ["<Primary>q"]);
Expand Down Expand Up @@ -539,6 +547,90 @@ export class Application extends Adw.Application {
window.present();
}

async export_notes() {
const dialog = new Gtk.FileDialog({
title: _("Export Notes"),
initial_name: "notes.json",
});

try {
const file = await new Promise<Gio.File | null>((resolve, reject) => {
dialog.save(this.active_window, null, (obj, res) => {
try {
resolve(obj!.save_finish(res));
} catch (err) {
reject(err);
}
});
});
Comment thread
paulowender marked this conversation as resolved.
Outdated

if (file) {
const notes = this.notes_array();
const data = {
v: 1,
notes: notes.map((n) => n.toJSON()),
};
const encoder = new TextEncoder();
file.replace_contents(
encoder.encode(JSON.stringify(data, null, 2)),
null,
false,
Gio.FileCreateFlags.NONE,
null,
);
}
} catch (err) {
if (err instanceof GLib.Error && err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED)) {
return;
}
console.error("Failed to export notes:", err);
Comment thread
paulowender marked this conversation as resolved.
}
}

async import_notes() {
const dialog = new Gtk.FileDialog({
title: _("Import Notes"),
});

try {
const file = await new Promise<Gio.File | null>((resolve, reject) => {
dialog.open(this.active_window, null, (obj, res) => {
try {
resolve(obj!.open_finish(res));
} catch (err) {
reject(err);
}
});
});
Comment thread
paulowender marked this conversation as resolved.
Outdated

if (file) {
const [success, contents] = file.load_contents(null);
if (success) {
const decoder = new TextDecoder();
const data = JSON.parse(decoder.decode(contents));
if (data.v === 1 && Array.isArray(data.notes)) {
data.notes.forEach((noteData: INote) => {
// Avoid duplicates by UUID
if (!this.find_note(noteData.uuid)) {
Comment thread
paulowender marked this conversation as resolved.
Outdated
const note = new Note(noteData);
note.connect("notify::modified", () => save_note(note));
note.connect("notify::open", () => save_note(note));
this.notes_list.append(note);
save_note(note);
}
});
this.sort_notes();
}
}
}
} catch (err) {
if (err instanceof GLib.Error && err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED)) {
return;
}
console.error("Failed to import notes:", err);
Comment thread
paulowender marked this conversation as resolved.
}
}

vfunc_startup() {
super.vfunc_startup();

Expand Down