···33import { COLLECTIONS } from "../lib/constants.ts";
44import {
55 applyRevisionFromFirehose,
66+ deleteBookmarkByUri,
67 deleteMembershipByUri,
78 deleteNoteByAtUri,
89 deleteRequestByUri,
910 deleteWikiByAtUri,
1011 getNoteByAtUri,
1112 getWikiByAtUri,
1313+ upsertBookmark,
1214 upsertMembership,
1315 upsertNote,
1416 upsertRequest,
···5254 createdAt: string;
5355}
54565757+interface BookmarkRecord {
5858+ wikiRef: string;
5959+ createdAt: string;
6060+}
6161+5562function isValidRecord(record: unknown): record is Record<string, unknown> {
5663 return typeof record === "object" && record !== null;
5764}
···8087 break;
8188 case COLLECTIONS.memberRequest:
8289 handleMemberRequest(evt, record as unknown as MemberRequestRecord);
9090+ break;
9191+ case COLLECTIONS.bookmark:
9292+ handleBookmark(evt, record as unknown as BookmarkRecord);
8393 break;
8494 }
8595}
···189199 upsertRequest(wiki.slug, evt.did, atUri, record.createdAt);
190200}
191201202202+function handleBookmark(evt: CommitEvt, record: BookmarkRecord): void {
203203+ if (!record.wikiRef || !record.createdAt) return;
204204+205205+ const atUri = evt.uri.toString();
206206+ if (!didOwnsUri(evt.did, atUri)) return;
207207+208208+ const wiki = getWikiByAtUri(record.wikiRef);
209209+ if (!wiki) return;
210210+211211+ upsertBookmark(evt.did, record.wikiRef, atUri, record.createdAt);
212212+}
213213+192214function handleDelete(evt: CommitEvt): void {
193215 const atUri = evt.uri.toString();
194216 if (!didOwnsUri(evt.did, atUri)) return;
···205227 break;
206228 case COLLECTIONS.memberRequest:
207229 deleteRequestByUri(atUri);
230230+ break;
231231+ case COLLECTIONS.bookmark:
232232+ deleteBookmarkByUri(atUri);
208233 break;
209234 }
210235}
+3-1
src/lib/i18n/en.ts
···104104 bookmarks: "Bookmarks",
105105 noOwnedWikis: "You haven't created any wikis yet.",
106106 noCollaboratingWikis: "You're not collaborating on any wikis yet.",
107107- bookmarksComingSoon: "Bookmarks are coming soon.",
107107+ noBookmarks: "No bookmarks yet.",
108108+ bookmark: "Bookmark",
109109+ removeBookmark: "Remove bookmark",
108110 },
109111 error: {
110112 titleRequired: "Title is required.",
+3-1
src/lib/i18n/fr.ts
···105105 bookmarks: "Signets",
106106 noOwnedWikis: "Vous n'avez pas encore cree de wiki.",
107107 noCollaboratingWikis: "Vous ne collaborez sur aucun wiki pour le moment.",
108108- bookmarksComingSoon: "Les signets arrivent bientot.",
108108+ noBookmarks: "Aucun signet pour le moment.",
109109+ bookmark: "Ajouter aux signets",
110110+ removeBookmark: "Retirer des signets",
109111 },
110112 error: {
111113 titleRequired: "Le titre est requis.",
···8787 `);
88888989 db.run(`
9090+ CREATE TABLE IF NOT EXISTS bookmarks (
9191+ id INTEGER PRIMARY KEY AUTOINCREMENT,
9292+ did TEXT NOT NULL,
9393+ wiki_at_uri TEXT NOT NULL,
9494+ at_uri TEXT NOT NULL UNIQUE,
9595+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
9696+ UNIQUE (did, wiki_at_uri)
9797+ )
9898+ `);
9999+100100+ db.run(`
90101 CREATE TABLE IF NOT EXISTS backlinks (
91102 source_note_uri TEXT NOT NULL,
92103 target_note_slug TEXT NOT NULL,
···147158 db.run(
148159 "CREATE INDEX IF NOT EXISTS idx_blobs_revision ON blobs(revision_at_uri)",
149160 );
161161+ db.run("CREATE INDEX IF NOT EXISTS idx_bookmarks_did ON bookmarks(did)");
150162}