Skip to content

Commit

Permalink
refactor: added the bookmark type to the database (#256)
Browse files Browse the repository at this point in the history
* refactoring asset types
Extracted out functions to silently delete assets and to update them after crawling
Generalized the mapping of assets to bookmark fields to make extending them easier

* Added the bookmark type to the database
Introduced an enum to have better type safety
cleaned up the code and based some code on the type directly

* add BookmarkType.UNKNWON

* lint and remove unused function

---------

Co-authored-by: MohamedBassem <[email protected]>
  • Loading branch information
kamtschatka and MohamedBassem authored Jul 1, 2024
1 parent ccbff18 commit e648646
Show file tree
Hide file tree
Showing 27 changed files with 1,266 additions and 120 deletions.
3 changes: 2 additions & 1 deletion apps/browser-extension/src/SavePage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { Navigate } from "react-router-dom";

import { BookmarkTypes } from "../../../packages/shared/types/bookmarks";
import Spinner from "./Spinner";
import { api } from "./utils/trpc";

Expand Down Expand Up @@ -32,7 +33,7 @@ export default function SavePage() {
}

createBookmark({
type: "link",
type: BookmarkTypes.LINK,
url: currentUrl,
});
}
Expand Down
13 changes: 8 additions & 5 deletions apps/cli/src/commands/bookmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { getAPIClient } from "@/lib/trpc";
import { Command } from "@commander-js/extra-typings";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { MAX_NUM_BOOKMARKS_PER_PAGE } from "@hoarder/shared/types/bookmarks";
import {
BookmarkTypes,
MAX_NUM_BOOKMARKS_PER_PAGE,
} from "@hoarder/shared/types/bookmarks";

export const bookmarkCmd = new Command()
.name("bookmarks")
Expand All @@ -26,7 +29,7 @@ function normalizeBookmark(bookmark: ZBookmark) {
tags: bookmark.tags.map((t) => t.name),
};

if (ret.content.type == "link" && ret.content.htmlContent) {
if (ret.content.type == BookmarkTypes.LINK && ret.content.htmlContent) {
if (ret.content.htmlContent.length > 10) {
ret.content.htmlContent =
ret.content.htmlContent.substring(0, 10) + "... <CROPPED>";
Expand Down Expand Up @@ -63,15 +66,15 @@ bookmarkCmd
const promises = [
...opts.link.map((url) =>
api.bookmarks.createBookmark
.mutate({ type: "link", url })
.mutate({ type: BookmarkTypes.LINK, url })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
.catch(printError(`Failed to add a link bookmark for url "${url}"`)),
),
...opts.note.map((text) =>
api.bookmarks.createBookmark
.mutate({ type: "text", text })
.mutate({ type: BookmarkTypes.TEXT, text })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
Expand All @@ -87,7 +90,7 @@ bookmarkCmd
const text = fs.readFileSync(0, "utf-8");
promises.push(
api.bookmarks.createBookmark
.mutate({ type: "text", text })
.mutate({ type: BookmarkTypes.TEXT, text })
.then((bookmark: ZBookmark) => {
results.push(normalizeBookmark(bookmark));
})
Expand Down
4 changes: 3 additions & 1 deletion apps/mobile/app/dashboard/add-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Input } from "@/components/ui/Input";
import { useToast } from "@/components/ui/Toast";
import { api } from "@/lib/trpc";

import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

export default function AddNote() {
const [text, setText] = useState("");
const [error, setError] = useState<string | undefined>();
Expand Down Expand Up @@ -54,7 +56,7 @@ export default function AddNote() {
autoFocus
/>
<Button
onPress={() => mutate({ type: "link", url: text })}
onPress={() => mutate({ type: BookmarkTypes.LINK, url: text })}
label="Add Link"
/>
</View>
Expand Down
7 changes: 6 additions & 1 deletion apps/mobile/app/dashboard/add-note.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { api } from "@/lib/trpc";

import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

export default function AddNote() {
const [text, setText] = useState("");
const [error, setError] = useState<string | undefined>();
Expand Down Expand Up @@ -45,7 +47,10 @@ export default function AddNote() {
placeholder="What's on your mind?"
autoFocus
/>
<Button onPress={() => mutate({ type: "text", text })} label="Add Note" />
<Button
onPress={() => mutate({ type: BookmarkTypes.TEXT, text })}
label="Add Note"
/>
</View>
);
}
6 changes: 3 additions & 3 deletions apps/mobile/app/sharing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { api } from "@/lib/trpc";
import { useUploadAsset } from "@/lib/upload";
import { z } from "zod";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";

type Mode =
| { type: "idle" }
Expand Down Expand Up @@ -45,9 +45,9 @@ function SaveBookmark({ setMode }: { setMode: (mode: Mode) => void }) {
const val = z.string().url();
if (val.safeParse(shareIntent.text).success) {
// This is a URL, else treated as text
mutate({ type: "link", url: shareIntent.text });
mutate({ type: BookmarkTypes.LINK, url: shareIntent.text });
} else {
mutate({ type: "text", text: shareIntent.text });
mutate({ type: BookmarkTypes.TEXT, text: shareIntent.text });
}
} else if (!isPending && shareIntent?.files) {
uploadAsset({
Expand Down
13 changes: 7 additions & 6 deletions apps/mobile/components/bookmarks/BookmarkCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
isBookmarkStillLoading,
isBookmarkStillTagging,
} from "@hoarder/shared-react/utils/bookmarkUtils";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

import { TailwindResolver } from "../TailwindResolver";
import { Divider } from "../ui/Divider";
Expand Down Expand Up @@ -161,7 +162,7 @@ function TagList({ bookmark }: { bookmark: ZBookmark }) {

function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
const { settings } = useAppSettings();
if (bookmark.content.type !== "link") {
if (bookmark.content.type !== BookmarkTypes.LINK) {
throw new Error("Wrong content type rendered");
}

Expand Down Expand Up @@ -223,7 +224,7 @@ function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
}

function TextCard({ bookmark }: { bookmark: ZBookmark }) {
if (bookmark.content.type !== "text") {
if (bookmark.content.type !== BookmarkTypes.TEXT) {
throw new Error("Wrong content type rendered");
}
const content = bookmark.content.text;
Expand Down Expand Up @@ -262,7 +263,7 @@ function TextCard({ bookmark }: { bookmark: ZBookmark }) {

function AssetCard({ bookmark }: { bookmark: ZBookmark }) {
const { settings } = useAppSettings();
if (bookmark.content.type !== "asset") {
if (bookmark.content.type !== BookmarkTypes.ASSET) {
throw new Error("Wrong content type rendered");
}
const title = bookmark.title ?? bookmark.content.fileName;
Expand Down Expand Up @@ -322,13 +323,13 @@ export default function BookmarkCard({

let comp;
switch (bookmark.content.type) {
case "link":
case BookmarkTypes.LINK:
comp = <LinkCard bookmark={bookmark} />;
break;
case "text":
case BookmarkTypes.TEXT:
comp = <TextCard bookmark={bookmark} />;
break;
case "asset":
case BookmarkTypes.ASSET:
comp = <AssetCard bookmark={bookmark} />;
break;
}
Expand Down
3 changes: 2 additions & 1 deletion apps/mobile/components/bookmarks/UpdatingBookmarkList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Text } from "react-native";
import { api } from "@/lib/trpc";

import type { ZGetBookmarksRequest } from "@hoarder/shared/types/bookmarks";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

import FullPageSpinner from "../ui/FullPageSpinner";
import BookmarkList from "./BookmarkList";
Expand Down Expand Up @@ -46,7 +47,7 @@ export default function UpdatingBookmarkList({
<BookmarkList
bookmarks={data.pages
.flatMap((p) => p.bookmarks)
.filter((b) => b.content.type != "unknown")}
.filter((b) => b.content.type != BookmarkTypes.UNKNWON)}
header={header}
onRefresh={onRefresh}
fetchNextPage={fetchNextPage}
Expand Down
4 changes: 2 additions & 2 deletions apps/mobile/lib/upload.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMutation } from "@tanstack/react-query";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";
import {
zUploadErrorSchema,
zUploadResponseSchema,
Expand Down Expand Up @@ -59,7 +59,7 @@ export function useUploadAsset(
const assetId = resp.assetId;
const assetType =
resp.contentType === "application/pdf" ? "pdf" : "image";
createBookmark({ type: "asset", assetId, assetType });
createBookmark({ type: BookmarkTypes.ASSET, assetId, assetType });
},
onError: (e) => {
if (options.onError) {
Expand Down
5 changes: 3 additions & 2 deletions apps/web/components/dashboard/UploadDropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { TRPCClientError } from "@trpc/client";
import DropZone from "react-dropzone";

import { useCreateBookmarkWithPostHook } from "@hoarder/shared-react/hooks/bookmarks";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";
import {
zUploadErrorSchema,
zUploadResponseSchema,
Expand Down Expand Up @@ -50,7 +51,7 @@ export function useUploadAsset() {
onSuccess: async (resp) => {
const assetType =
resp.contentType === "application/pdf" ? "pdf" : "image";
return createBookmark({ ...resp, type: "asset", assetType });
return createBookmark({ ...resp, type: BookmarkTypes.ASSET, assetType });
},
onError: (error, req) => {
const err = zUploadErrorSchema.parse(JSON.parse(error.message));
Expand All @@ -68,7 +69,7 @@ export function useUploadAsset() {
onSuccess: async (resp) => {
return Promise.all(
resp.map((url) =>
createBookmark({ type: "link", url: url.toString() }),
createBookmark({ type: BookmarkTypes.LINK, url: url.toString() }),
),
);
},
Expand Down
8 changes: 4 additions & 4 deletions apps/web/components/dashboard/bookmarks/BookmarkCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { api } from "@/lib/trpc";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { isBookmarkStillLoading } from "@hoarder/shared-react/utils/bookmarkUtils";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";

import AssetCard from "./AssetCard";
import LinkCard from "./LinkCard";
Expand Down Expand Up @@ -34,21 +34,21 @@ export default function BookmarkCard({
);

switch (bookmark.content.type) {
case "link":
case BookmarkTypes.LINK:
return (
<LinkCard
className={className}
bookmark={{ ...bookmark, content: bookmark.content }}
/>
);
case "text":
case BookmarkTypes.TEXT:
return (
<TextCard
className={className}
bookmark={{ ...bookmark, content: bookmark.content }}
/>
);
case "asset":
case BookmarkTypes.ASSET:
return (
<AssetCard
className={className}
Expand Down
7 changes: 4 additions & 3 deletions apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from "@hoarder/shared-react/hooks//bookmarks";
import { useRemoveBookmarkFromList } from "@hoarder/shared-react/hooks//lists";
import { useBookmarkGridContext } from "@hoarder/shared-react/hooks/bookmark-grid-context";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
import { ArchivedActionIcon, FavouritedActionIcon } from "./icons";
Expand Down Expand Up @@ -115,7 +116,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-fit">
{bookmark.content.type === "text" && (
{bookmark.content.type === BookmarkTypes.TEXT && (
<DropdownMenuItem onClick={() => setTextEditorOpen(true)}>
<Pencil className="mr-2 size-4" />
<span>Edit</span>
Expand Down Expand Up @@ -151,7 +152,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
/>
<span>{bookmark.archived ? "Un-archive" : "Archive"}</span>
</DropdownMenuItem>
{bookmark.content.type === "link" && (
{bookmark.content.type === BookmarkTypes.LINK && (
<DropdownMenuItem
onClick={() => {
navigator.clipboard.writeText(
Expand Down Expand Up @@ -191,7 +192,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
</DropdownMenuItem>
)}

{bookmark.content.type === "link" && (
{bookmark.content.type === BookmarkTypes.LINK && (
<DropdownMenuItem
disabled={demoMode}
onClick={() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Textarea } from "@/components/ui/textarea";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";

export function BookmarkedTextEditor({
bookmark,
Expand All @@ -27,7 +27,9 @@ export function BookmarkedTextEditor({
}) {
const isNewBookmark = bookmark === undefined;
const [noteText, setNoteText] = useState(
bookmark && bookmark.content.type == "text" ? bookmark.content.text : "",
bookmark && bookmark.content.type == BookmarkTypes.TEXT
? bookmark.content.text
: "",
);

const invalidateOneBookmarksCache =
Expand Down
12 changes: 8 additions & 4 deletions apps/web/components/dashboard/bookmarks/EditorCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { useForm } from "react-hook-form";
import { z } from "zod";

import { useCreateBookmarkWithPostHook } from "@hoarder/shared-react/hooks/bookmarks";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

import { useUploadAsset } from "../UploadDropzone";

Expand Down Expand Up @@ -99,7 +100,7 @@ export default function EditorCard({ className }: { className?: string }) {

if (urls.length === 1) {
// Only 1 url in the textfield --> simply import it
mutate({ type: "link", url: text });
mutate({ type: BookmarkTypes.LINK, url: text });
return;
}
// multiple urls found --> ask the user if it should be imported as multiple URLs or as a text bookmark
Expand Down Expand Up @@ -128,7 +129,7 @@ export default function EditorCard({ className }: { className?: string }) {
tryToImportUrls(text);
} catch (e) {
// Not a URL
mutate({ type: "text", text });
mutate({ type: BookmarkTypes.TEXT, text });
}
};

Expand Down Expand Up @@ -240,7 +241,10 @@ export default function EditorCard({ className }: { className?: string }) {
variant="secondary"
loading={isPending}
onClick={() => {
mutate({ type: "text", text: multiUrlImportState.text });
mutate({
type: BookmarkTypes.TEXT,
text: multiUrlImportState.text,
});
setMultiUrlImportState(null);
}}
>
Expand All @@ -254,7 +258,7 @@ export default function EditorCard({ className }: { className?: string }) {
loading={isPending}
onClick={() => {
multiUrlImportState.urls.forEach((url) =>
mutate({ type: "link", url: url.toString() }),
mutate({ type: BookmarkTypes.LINK, url: url.toString() }),
);
setMultiUrlImportState(null);
}}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/components/dashboard/preview/AssetContentSection.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Image from "next/image";
import Link from "next/link";

import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";

export function AssetContentSection({ bookmark }: { bookmark: ZBookmark }) {
if (bookmark.content.type != "asset") {
if (bookmark.content.type != BookmarkTypes.ASSET) {
throw new Error("Invalid content type");
}

Expand Down
Loading

0 comments on commit e648646

Please sign in to comment.