aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-10-12 22:41:56 +0100
committerGitHub <noreply@github.com>2025-10-12 22:41:56 +0100
commit2defc2475fc36635c45a449a44669048871864f6 (patch)
treebf093e6a55f22ec062d8cf3eb41763f72f55f821 /apps
parentc14b69346a67d4c426d7ddb32ef32812c449e67c (diff)
downloadkarakeep-2defc2475fc36635c45a449a44669048871864f6.tar.zst
feat: Add source field to track bookmark creation sources (#2037)
* feat: Add source field to track bookmark creation sources Add a new 'source' field to the bookmarks table to track where bookmarks were created from. Possible values: api, web, cli, mobile, singlefile, rss. Changes: - Add source field to bookmarks table schema - Update Zod schemas to include source field - Update tRPC createBookmark procedure to store source - Update all callsites to pass appropriate source value: - api: Default to "api" if not provided - singlefile: Set to "singlefile" - rss: Set to "rss" in feedWorker - cli: Set to "cli" - mobile: Set to "mobile" in all mobile app bookmark creation - browser-extension: Set to "web" - web: Set to "web" in all web app bookmark creation - Create migration file for database schema change Fixes #2036 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Mohamed Bassem <MohamedBassem@users.noreply.github.com> * feat: Add extension source type for browser extension - Add 'extension' to bookmark source enum - Update browser extension to use 'extension' instead of 'web' Co-authored-by: Mohamed Bassem <MohamedBassem@users.noreply.github.com> * fix CI * fix CI * fix the migration file * add import source * make source nullish --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Mohamed Bassem <MohamedBassem@users.noreply.github.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/browser-extension/src/SavePage.tsx6
-rw-r--r--apps/cli/src/commands/bookmarks.ts21
-rw-r--r--apps/mobile/app/dashboard/bookmarks/new.tsx8
-rw-r--r--apps/mobile/app/sharing.tsx18
-rw-r--r--apps/mobile/lib/upload.ts7
-rw-r--r--apps/web/components/dashboard/UploadDropzone.tsx8
-rw-r--r--apps/web/lib/hooks/useBookmarkImport.ts1
-rw-r--r--apps/workers/workers/feedWorker.ts1
8 files changed, 59 insertions, 11 deletions
diff --git a/apps/browser-extension/src/SavePage.tsx b/apps/browser-extension/src/SavePage.tsx
index 4c495928..d3d9458a 100644
--- a/apps/browser-extension/src/SavePage.tsx
+++ b/apps/browser-extension/src/SavePage.tsx
@@ -49,6 +49,7 @@ export default function SavePage() {
type: BookmarkTypes.LINK,
url: currentTab.url,
title: currentTab.title,
+ source: "extension",
};
} else {
setError("Couldn't find the URL of the current tab");
@@ -56,7 +57,10 @@ export default function SavePage() {
}
}
- createBookmark(newBookmarkRequest);
+ createBookmark({
+ ...newBookmarkRequest,
+ source: newBookmarkRequest.source || "extension",
+ });
}
runSave();
}, [createBookmark]);
diff --git a/apps/cli/src/commands/bookmarks.ts b/apps/cli/src/commands/bookmarks.ts
index 308b57b0..021e344f 100644
--- a/apps/cli/src/commands/bookmarks.ts
+++ b/apps/cli/src/commands/bookmarks.ts
@@ -85,7 +85,12 @@ bookmarkCmd
const promises = [
...opts.link.map((url) =>
api.bookmarks.createBookmark
- .mutate({ type: BookmarkTypes.LINK, url, title: opts.title })
+ .mutate({
+ type: BookmarkTypes.LINK,
+ url,
+ title: opts.title,
+ source: "cli",
+ })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
@@ -93,7 +98,12 @@ bookmarkCmd
),
...opts.note.map((text) =>
api.bookmarks.createBookmark
- .mutate({ type: BookmarkTypes.TEXT, text, title: opts.title })
+ .mutate({
+ type: BookmarkTypes.TEXT,
+ text,
+ title: opts.title,
+ source: "cli",
+ })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
@@ -109,7 +119,12 @@ bookmarkCmd
const text = fs.readFileSync(0, "utf-8");
promises.push(
api.bookmarks.createBookmark
- .mutate({ type: BookmarkTypes.TEXT, text, title: opts.title })
+ .mutate({
+ type: BookmarkTypes.TEXT,
+ text,
+ title: opts.title,
+ source: "cli",
+ })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
diff --git a/apps/mobile/app/dashboard/bookmarks/new.tsx b/apps/mobile/app/dashboard/bookmarks/new.tsx
index 51db6d97..25882d7f 100644
--- a/apps/mobile/app/dashboard/bookmarks/new.tsx
+++ b/apps/mobile/app/dashboard/bookmarks/new.tsx
@@ -48,9 +48,13 @@ const NoteEditorPage = () => {
if (url.protocol != "http:" && url.protocol != "https:") {
throw new Error(`Unsupported URL protocol: ${url.protocol}`);
}
- createBookmark({ type: BookmarkTypes.LINK, url: data });
+ createBookmark({ type: BookmarkTypes.LINK, url: data, source: "mobile" });
} catch {
- createBookmark({ type: BookmarkTypes.TEXT, text: data });
+ createBookmark({
+ type: BookmarkTypes.TEXT,
+ text: data,
+ source: "mobile",
+ });
}
};
diff --git a/apps/mobile/app/sharing.tsx b/apps/mobile/app/sharing.tsx
index 1e5df4b8..3e2b6bfb 100644
--- a/apps/mobile/app/sharing.tsx
+++ b/apps/mobile/app/sharing.tsx
@@ -44,14 +44,26 @@ function SaveBookmark({ setMode }: { setMode: (mode: Mode) => void }) {
return;
}
if (!isPending && shareIntent.webUrl) {
- mutate({ type: BookmarkTypes.LINK, url: shareIntent.webUrl });
+ mutate({
+ type: BookmarkTypes.LINK,
+ url: shareIntent.webUrl,
+ source: "mobile",
+ });
} else if (!isPending && shareIntent?.text) {
const val = z.string().url();
if (val.safeParse(shareIntent.text).success) {
// This is a URL, else treated as text
- mutate({ type: BookmarkTypes.LINK, url: shareIntent.text });
+ mutate({
+ type: BookmarkTypes.LINK,
+ url: shareIntent.text,
+ source: "mobile",
+ });
} else {
- mutate({ type: BookmarkTypes.TEXT, text: shareIntent.text });
+ mutate({
+ type: BookmarkTypes.TEXT,
+ text: shareIntent.text,
+ source: "mobile",
+ });
}
} else if (!isPending && shareIntent?.files) {
uploadAsset({
diff --git a/apps/mobile/lib/upload.ts b/apps/mobile/lib/upload.ts
index a9157d68..0eeab380 100644
--- a/apps/mobile/lib/upload.ts
+++ b/apps/mobile/lib/upload.ts
@@ -61,7 +61,12 @@ export function useUploadAsset(
const assetId = resp.assetId;
const assetType =
resp.contentType === "application/pdf" ? "pdf" : "image";
- createBookmark({ type: BookmarkTypes.ASSET, assetId, assetType });
+ createBookmark({
+ type: BookmarkTypes.ASSET,
+ assetId,
+ assetType,
+ source: "mobile",
+ });
},
onError: (e) => {
if (options.onError) {
diff --git a/apps/web/components/dashboard/UploadDropzone.tsx b/apps/web/components/dashboard/UploadDropzone.tsx
index 2bac005e..8d119467 100644
--- a/apps/web/components/dashboard/UploadDropzone.tsx
+++ b/apps/web/components/dashboard/UploadDropzone.tsx
@@ -34,7 +34,12 @@ export function useUploadAsset() {
onSuccess: async (resp) => {
const assetType =
resp.contentType === "application/pdf" ? "pdf" : "image";
- await createBookmark({ ...resp, type: BookmarkTypes.ASSET, assetType });
+ await createBookmark({
+ ...resp,
+ type: BookmarkTypes.ASSET,
+ assetType,
+ source: "web",
+ });
},
onError: (err, req) => {
toast({
@@ -54,6 +59,7 @@ export function useUploadAsset() {
type: BookmarkTypes.TEXT,
text: content,
title: file.name.replace(/\.md$/i, ""), // Remove .md extension from title
+ source: "web",
});
} catch {
toast({
diff --git a/apps/web/lib/hooks/useBookmarkImport.ts b/apps/web/lib/hooks/useBookmarkImport.ts
index a4ebdd9c..d4ffda4e 100644
--- a/apps/web/lib/hooks/useBookmarkImport.ts
+++ b/apps/web/lib/hooks/useBookmarkImport.ts
@@ -75,6 +75,7 @@ export function useBookmarkImport() {
note: bookmark.notes,
archived: bookmark.archived,
importSessionId: sessionId,
+ source: "import",
...(bookmark.content.type === BookmarkTypes.LINK
? {
type: BookmarkTypes.LINK,
diff --git a/apps/workers/workers/feedWorker.ts b/apps/workers/workers/feedWorker.ts
index 19076b50..38b06c47 100644
--- a/apps/workers/workers/feedWorker.ts
+++ b/apps/workers/workers/feedWorker.ts
@@ -209,6 +209,7 @@ async function run(req: DequeuedJob<ZFeedRequestSchema>) {
trpcClient.bookmarks.createBookmark({
type: BookmarkTypes.LINK,
url: item.link!,
+ source: "rss",
}),
),
);