diff --git a/packages/core/src/collections/notes.ts b/packages/core/src/collections/notes.ts index fbc4c75eb..4649626a1 100644 --- a/packages/core/src/collections/notes.ts +++ b/packages/core/src/collections/notes.ts @@ -154,12 +154,18 @@ export class Notes implements ICollection { return id; } - async note(idOrNote: string) { - const note = await this.collection.get(idOrNote); + async note(id: string) { + const note = await this.collection.get(id); if (!note || isTrashItem(note) || isDeleted(note)) return; return note; } + async trashed(id: string) { + const note = await this.collection.get(id); + if (note && (!isTrashItem(note) || isDeleted(note))) return; + return note; + } + // note(idOrNote: string | Note) { // if (!idOrNote) return; // const note = diff --git a/packages/core/src/collections/trash.ts b/packages/core/src/collections/trash.ts index 94e8815c4..90c053270 100644 --- a/packages/core/src/collections/trash.ts +++ b/packages/core/src/collections/trash.ts @@ -22,7 +22,8 @@ import Database from "../api"; import { deleteItems } from "../utils/array"; import { GroupOptions, TrashItem } from "../types"; import { VirtualizedGrouping } from "../utils/virtualized-grouping"; -import { groupArray } from "../utils/grouping"; +import { getSortSelectors, groupArray } from "../utils/grouping"; +import { sql } from "kysely"; export default class Trash { collections = ["notes", "notebooks"] as const; @@ -39,23 +40,20 @@ export default class Trash { await this.cleanup(); const result = await this.db .sql() - .selectNoFrom((eb) => [ - eb - .selectFrom("notes") - .where("type", "==", "trash") - .select("id") - .as("noteId"), + .selectFrom("notes") + .where("type", "==", "trash") + .select(["id", sql`'note'`.as("itemType")]) + .unionAll((eb) => eb .selectFrom("notebooks") .where("type", "==", "trash") - .select("id") - .as("notebookId") - ]) + .select(["id", sql`'notebook'`.as("itemType")]) + ) .execute(); - for (const { noteId, notebookId } of result) { - if (noteId) this.cache.notes.push(noteId); - else if (notebookId) this.cache.notebooks.push(notebookId); + for (const { id, itemType } of result) { + if (itemType === "note") this.cache.notes.push(id); + else if (itemType === "notebook") this.cache.notebooks.push(id); } } @@ -192,49 +190,69 @@ export default class Trash { // } async all() { - const trashedNotes = await this.db + return [ + ...(await this.trashedNotes(this.cache.notes)), + ...(await this.trashedNotebooks(this.cache.notebooks)) + ] as TrashItem[]; + } + + private async trashedNotes(ids: string[]) { + return (await this.db .sql() .selectFrom("notes") .where("type", "==", "trash") - .where("id", "in", this.cache.notes) + .where("id", "in", ids) .selectAll() - .execute(); + .execute()) as TrashItem[]; + } - const trashedNotebooks = await this.db + private async trashedNotebooks(ids: string[]) { + return (await this.db .sql() .selectFrom("notebooks") .where("type", "==", "trash") - .where("id", "in", this.cache.notebooks) + .where("id", "in", ids) .selectAll() - .execute(); - - return [...trashedNotes, ...trashedNotebooks] as TrashItem[]; + .execute()) as TrashItem[]; } async grouped(options: GroupOptions) { - // const items = await this.all(); - // const ids = groupArray(items, options); - // const records: Record = {}; - // for (const item of items) records[item.id] = item; - // const ids = [...this.cache.notebooks,...this.cache.notes] - + const ids = [...this.cache.notes, ...this.cache.notebooks]; + const selector = getSortSelectors(options)[options.sortDirection]; return new VirtualizedGrouping( - this.cache.notebooks.length + this.cache.notes.length, + ids.length, this.db.options.batchSize, - () => Promise.resolve([...this.cache.notebooks, ...this.cache.notes]), + () => Promise.resolve(ids), async (start, end) => { - // const notesRange = end < this.cache.notes.length ? [start, end] : [start, this.cache.notes.length - 1]; - // const notebooksRange = start >= this.cache.notes.length ?[start, end] : [ - // 0, end - // ] - // TODO: - return { ids: [], items: [] }; - // return { - // ids: ids.slice(start,end), - // } - // const items: Record = {}; - // for (const id of ids) items[id] = records[id]; - // return items; + const notesRange = + end < this.cache.notes.length + ? [start, end] + : [start, this.cache.notes.length]; + const notebooksRange = + start >= this.cache.notes.length + ? [start, end] + : [0, Math.min(this.cache.notebooks.length, end)]; + + const items = [ + ...(await this.trashedNotes( + this.cache.notes.slice(notesRange[0], notesRange[1]) + )), + ...(await this.trashedNotebooks( + this.cache.notebooks.slice(notebooksRange[0], notebooksRange[1]) + )) + ]; + items.sort(selector); + + return { + ids: ids.slice(start, end), + items + }; + }, + (items) => groupArray(items, options), + async () => { + const items = await this.all(); + items.sort(selector); + return Array.from(groupArray(items, options).values()); } ); } diff --git a/packages/core/src/utils/grouping.ts b/packages/core/src/utils/grouping.ts index b0709211b..4c4356772 100644 --- a/packages/core/src/utils/grouping.ts +++ b/packages/core/src/utils/grouping.ts @@ -42,12 +42,33 @@ export const getSortValue = ( item.dateDeleted ) return item.dateDeleted; - else if (options.sortBy === "dateEdited" && "dateEdited" in item) + else if ( + options.sortBy === "dateEdited" && + "dateEdited" in item && + item.dateEdited + ) return item.dateEdited; - return item.dateCreated; + return item.dateCreated || 0; }; +export function getSortSelectors( + options: GroupOptions +) { + if (options.sortBy === "title") + return { + asc: (a: T, b: T) => + getTitle(a).localeCompare(getTitle(b), undefined, { numeric: true }), + desc: (a: T, b: T) => + getTitle(b).localeCompare(getTitle(a), undefined, { numeric: true }) + }; + + return { + asc: (a: T, b: T) => getSortValue(options, a) - getSortValue(options, b), + desc: (a: T, b: T) => getSortValue(options, b) - getSortValue(options, a) + }; +} + const MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24; const MILLISECONDS_IN_WEEK = MILLISECONDS_IN_DAY * 7;