@launchmenu/applet-notes
Version:
An applet to make short notes
287 lines • 22.4 kB
JavaScript
"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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