UNPKG

@launchmenu/applet-notes

Version:
287 lines 22.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NotesSource = void 0; const core_1 = require("@launchmenu/core"); const model_react_1 = require("model-react"); const Note_1 = require("./Note"); const NoteCategory_1 = require("./NoteCategory"); const uuid_1 = require("uuid"); const path_1 = __importDefault(require("path")); class NotesSource { /** * Creates a new notes data source based on the specified file path * @param metadataFilePath The path to the metadata file of the notes * @param defaults The retrievers of the defaults of the notes **/ constructor(metadataFilePath, defaults) { // The notes themselves /** The notes data retriever that synchronizes with the note data on disk */ this.notes = new model_react_1.DataCacher((h, prevNotes = []) => { const notesData = this.file.fields.notes.get(h); // Deleted any removed notes prevNotes.forEach(note => { const stillExists = notesData.find(({ ID }) => note.ID == ID); if (!stillExists) note.destroy(); }); // Add any new notes (or obtain the corresponding existing note) return notesData.map(noteData => { // Check if a note instance already exists for this data const prevNote = prevNotes.find(note => note.ID == noteData.ID); if (prevNote) return prevNote; // If it doesn't exist, create it with some data retriever and updater functions const dataSource = new model_react_1.DataCacher(h => { var _a; return (_a = this.file.fields.notes.get(h).find(({ ID }) => ID == noteData.ID)) !== null && _a !== void 0 ? _a : { ...noteData, name: "Deleted", }; }); return new Note_1.Note(noteData.ID, h => dataSource.get(h), (ID, data) => this.updateNote(ID, data), this); }); }); // The note categories data /** The categories data retriever that synchronizes with the note data on disk */ this.categories = new model_react_1.DataCacher((h, prevCategories = []) => { const categoriesData = this.file.fields.categories.get(h); return categoriesData.map(categoryData => { // Check if a note instance already exists for this data const prevCategory = prevCategories.find(note => note.ID == categoryData.ID); if (prevCategory) return prevCategory; // If it doesn't exist, create it with some data retriever and updater functions const dataSource = new model_react_1.DataCacher(h => { var _a; return (_a = this.file.fields.categories .get(h) .find(({ ID }) => ID == categoryData.ID)) !== null && _a !== void 0 ? _a : { ...categoryData, name: "Deleted", }; }); return new NoteCategory_1.NoteCategory(categoryData.ID, h => dataSource.get(h), (ID, data) => this.updateCategory(ID, data), this); }); }); this.file = new core_1.FieldsFile({ path: metadataFilePath, fields: { categories: new model_react_1.Field([]), notes: new model_react_1.Field([]) }, }); this.file.load(); this.loader = new core_1.FileAutoReloader(this.file); this.saver = new core_1.FileAutoSaver(this.file); this.notesDir = path_1.default.join(metadataFilePath, "..", "notes"); this.defaults = defaults; } /** * Retrieves the path of this source * @returns The path of notes source */ getPath() { return this.file.getPath(); } /** * Retrieves the notes file that the data is stored in * @returns The metadata file that all notes are stored in */ getFile() { return this.file; } /** * Retrieves the path to the directory notes are stored in * @returns The notes storage directory */ getNotesDir() { return this.notesDir; } /** * Disposes this source fully */ destroy() { this.loader.destroy(); this.saver.destroy(); this.notes.get().forEach(note => note.destroy()); } /** * Updates the metadata of a given note * @param ID The note's ID * @param data The new data for the note (includes ID of the note) */ updateNote(ID, data) { const notes = this.file.fields.notes.get(); const noteIndex = notes.findIndex(({ ID: vID }) => vID == ID); if (noteIndex != -1) { const newNotes = [ ...notes.slice(0, noteIndex), ...(data ? [data] : []), ...notes.slice(noteIndex + 1), ].sort(({ modifiedAt: a }, { modifiedAt: b }) => b - a); this.file.fields.notes.set(newNotes); } } /** * Retrieves all the registered notes * @param hook The hook to subscribe to changes * @returns The notes that are registered */ getAllNotes(hook) { return this.notes.get(hook); } /** * Updates the metadata of a given category * @param ID The ID of the category to update * @param data The new data for the category (includes ID of the note) */ updateCategory(ID, data) { const categories = this.file.fields.categories.get(); const categoryIndex = categories.findIndex(({ ID: vID }) => vID == ID); if (categoryIndex != -1) { const newCategories = [ ...categories.slice(0, categoryIndex), ...(data ? [data] : []), ...categories.slice(categoryIndex + 1), ]; this.file.fields.categories.set(newCategories); } } /** * Retrieves all the note categories * @param hook The hook to subscribe to changes * @returns The note categories */ getAllCategories(hook) { return this.categories.get(hook); } /** * Retrieves the category with a specified ID * @param ID The ID of the category * @param hook The hook to subscribes to changes * @returns The category if it exists */ getCategoryByID(ID, hook) { var _a; return (_a = this.categories.get(hook).find(({ ID: cID }) => cID == ID)) !== null && _a !== void 0 ? _a : null; } // File/category creation /** * Adds a new note to the system * @param name The name of the note, ID will be based on this if specified * @param ID The ID of the note * @returns The created note */ async addNote(name, ID) { // Create the note's ID const baseID = name !== null && name !== void 0 ? name : uuid_1.v4(); if (!ID) ID = baseID; // Create the note return this.createNote({ ID, name: name !== null && name !== void 0 ? name : "Note", modifiedAt: Date.now(), location: path_1.default.join(this.notesDir, `${ID}.txt`), color: "inherit", fontSize: "inherit", showRichContent: "inherit", syntaxMode: "inherit", searchContent: "inherit", }); } /** * Adds a note to the system, for which a file already exists * @param location The location of the note document * @param name The name of the note to import * @returns The imported note */ async importNote(location, name) { // Create the note's ID const fileNameWithExtension = location.substring(path_1.default.dirname(location).length + 1); const fileName = fileNameWithExtension.substring(0, fileNameWithExtension.length - path_1.default.extname(fileNameWithExtension).length); const ID = name !== null && name !== void 0 ? name : fileName; // Create the note return this.createNote({ name: name !== null && name !== void 0 ? name : fileName, modifiedAt: Date.now(), location, ID, color: "inherit", fontSize: "inherit", showRichContent: "inherit", syntaxMode: "inherit", searchContent: "inherit", }); } /** * Creates a new note with the given information * @param noteData The note data * @returns The created note */ async createNote(noteData) { // Make sure the ID is unique const baseID = noteData.ID; let ID = baseID; let suffix = 0; while (this.notes.get().some(({ ID: vID }) => vID == ID)) ID = baseID + ++suffix; noteData = { ...noteData, ID }; // Insert the data this.file.fields.notes.set([...this.file.fields.notes.get(), noteData]); // Retrieve the note let note; await model_react_1.waitFor(h => { note = this.notes.get(h).find(({ ID }) => noteData.ID == ID); return !!note; }); return note; } // Note category creation /** * Adds a new note category to the system * @param name The name of the category, ID will be based on this if specified * @param ID The ID of the note category * @returns The created note category */ async addNoteCategory(name, ID) { // Create the note category's ID const baseID = name !== null && name !== void 0 ? name : uuid_1.v4(); if (!ID) ID = baseID; // Create the note return this.createNoteCategory({ ID, name: name !== null && name !== void 0 ? name : "Note", color: "inherit", fontSize: "inherit", showRichContent: "inherit", syntaxMode: "inherit", searchContent: "inherit", }); } /** * Creates a new note category with the given information * @param noteCategoryData The note category data * @returns The created note category */ async createNoteCategory(noteCategoryData) { // Make sure the ID is unique const baseID = noteCategoryData.ID; let ID = baseID; let suffix = 0; while (this.notes.get().some(({ ID: vID }) => vID == ID)) ID = baseID + ++suffix; noteCategoryData = { ...noteCategoryData, ID }; // Insert the data this.file.fields.categories.set([ ...this.file.fields.categories.get(), noteCategoryData, ]); // Retrieve the note let noteCategory; await model_react_1.waitFor(h => { noteCategory = this.categories .get(h) .find(({ ID }) => noteCategoryData.ID == ID); return !!noteCategory; }); return noteCategory; } } exports.NotesSource = NotesSource; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTm90ZXNTb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0YU1vZGVsL05vdGVzU291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJDQUFxRjtBQUNyRiw2Q0FBa0U7QUFDbEUsaUNBQTRCO0FBQzVCLGlEQUE0QztBQUc1QywrQkFBZ0M7QUFDaEMsZ0RBQXdCO0FBVXhCLE1BQWEsV0FBVztJQVdwQjs7OztRQUlJO0lBQ0osWUFBbUIsZ0JBQXdCLEVBQUUsUUFBc0M7UUErQ25GLHVCQUF1QjtRQUN2Qiw0RUFBNEU7UUFDbEUsVUFBSyxHQUFHLElBQUksd0JBQVUsQ0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEdBQUcsRUFBRSxFQUFFLEVBQUU7WUFDM0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVoRCw0QkFBNEI7WUFDNUIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDckIsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUMsRUFBRSxFQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQzVELElBQUksQ0FBQyxXQUFXO29CQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNyQyxDQUFDLENBQUMsQ0FBQztZQUVILGdFQUFnRTtZQUNoRSxPQUFPLFNBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQzVCLHdEQUF3RDtnQkFDeEQsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoRSxJQUFJLFFBQVE7b0JBQUUsT0FBTyxR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