From 33f407797213c56dd2f13e98228a5305efdf90fd Mon Sep 17 00:00:00 2001 From: xuatz Date: Mon, 3 Nov 2025 04:32:18 +0900 Subject: feat: display notes on bookmark card (#2083) * feat: display notes on bookmark card * apply styling * include mobile impl * apply pr comments * add display options menu into PR * put it under app setting * cleanup * address pr comments * change the default for show notes to false * make the in-card note font lighter --------- Co-authored-by: Mohamed Bassem --- apps/mobile/app/dashboard/(tabs)/settings.tsx | 14 +++- apps/mobile/components/bookmarks/BookmarkCard.tsx | 10 ++- apps/mobile/components/bookmarks/NotePreview.tsx | 83 +++++++++++++++++++++++ apps/mobile/lib/settings.ts | 2 + 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 apps/mobile/components/bookmarks/NotePreview.tsx (limited to 'apps/mobile') diff --git a/apps/mobile/app/dashboard/(tabs)/settings.tsx b/apps/mobile/app/dashboard/(tabs)/settings.tsx index 6d76308d..76216e00 100644 --- a/apps/mobile/app/dashboard/(tabs)/settings.tsx +++ b/apps/mobile/app/dashboard/(tabs)/settings.tsx @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import { ActivityIndicator, Pressable, View } from "react-native"; +import { ActivityIndicator, Pressable, Switch, View } from "react-native"; import { Slider } from "react-native-awesome-slider"; import { useSharedValue } from "react-native-reanimated"; import { Link } from "expo-router"; @@ -87,6 +87,18 @@ export default function Dashboard() { + + Show note preview in bookmark + + setSettings({ + ...settings, + showNotes: value, + }) + } + /> + Upload Settings diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx index 62e74e97..98d8d3e2 100644 --- a/apps/mobile/components/bookmarks/BookmarkCard.tsx +++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx @@ -1,4 +1,3 @@ -import React from "react"; import { ActivityIndicator, Alert, @@ -37,6 +36,7 @@ import { Skeleton } from "../ui/Skeleton"; import { useToast } from "../ui/Toast"; import BookmarkAssetImage from "./BookmarkAssetImage"; import BookmarkTextMarkdown from "./BookmarkTextMarkdown"; +import { NotePreview } from "./NotePreview"; import TagPill from "./TagPill"; function ActionBar({ bookmark }: { bookmark: ZBookmark }) { @@ -285,6 +285,7 @@ function LinkCard({ throw new Error("Wrong content type rendered"); } + const note = settings.showNotes ? bookmark.note?.trim() : undefined; const url = bookmark.content.url; const parsedUrl = new URL(url); @@ -329,6 +330,7 @@ function LinkCard({ > {bookmark.title ?? bookmark.content.title ?? parsedUrl.host} + {note && } @@ -347,9 +349,11 @@ function TextCard({ bookmark: ZBookmark; onOpenBookmark: () => void; }) { + const { settings } = useAppSettings(); if (bookmark.content.type !== BookmarkTypes.TEXT) { throw new Error("Wrong content type rendered"); } + const note = settings.showNotes ? bookmark.note?.trim() : undefined; const content = bookmark.content.text; return ( @@ -365,6 +369,7 @@ function TextCard({ + {note && } @@ -382,9 +387,11 @@ function AssetCard({ bookmark: ZBookmark; onOpenBookmark: () => void; }) { + const { settings } = useAppSettings(); if (bookmark.content.type !== BookmarkTypes.ASSET) { throw new Error("Wrong content type rendered"); } + const note = settings.showNotes ? bookmark.note?.trim() : undefined; const title = bookmark.title ?? bookmark.content.fileName; const assetImage = @@ -405,6 +412,7 @@ function AssetCard({ {title} )} + {note && } diff --git a/apps/mobile/components/bookmarks/NotePreview.tsx b/apps/mobile/components/bookmarks/NotePreview.tsx new file mode 100644 index 00000000..d529d56e --- /dev/null +++ b/apps/mobile/components/bookmarks/NotePreview.tsx @@ -0,0 +1,83 @@ +import { useState } from "react"; +import { Modal, Pressable, ScrollView, View } from "react-native"; +import { router } from "expo-router"; +import { ExternalLink, NotepadText, X } from "lucide-react-native"; +import { useColorScheme } from "nativewind"; + +import { Button } from "../ui/Button"; +import { Text } from "../ui/Text"; + +interface NotePreviewProps { + note: string; + bookmarkId: string; +} + +export function NotePreview({ note, bookmarkId }: NotePreviewProps) { + const [isModalVisible, setIsModalVisible] = useState(false); + const { colorScheme } = useColorScheme(); + const iconColor = colorScheme === "dark" ? "#9ca3af" : "#6b7280"; + const modalIconColor = colorScheme === "dark" ? "#d1d5db" : "#374151"; + + if (!note?.trim()) { + return null; + } + + return ( + <> + setIsModalVisible(true)}> + + + + {note} + + + + + setIsModalVisible(false)} + > + + + {/* Header */} + + Note + setIsModalVisible(false)} + className="p-2" + > + + + + + {/* Note Content */} + + + {note} + + + + {/* Action Button */} + + + + + + + + ); +} diff --git a/apps/mobile/lib/settings.ts b/apps/mobile/lib/settings.ts index 51fa661f..4399e04a 100644 --- a/apps/mobile/lib/settings.ts +++ b/apps/mobile/lib/settings.ts @@ -14,6 +14,7 @@ const zSettingsSchema = z.object({ .enum(["reader", "browser"]) .optional() .default("reader"), + showNotes: z.boolean().optional().default(false), }); export type Settings = z.infer; @@ -32,6 +33,7 @@ const useSettings = create((set, get) => ({ imageQuality: 0.2, theme: "system", defaultBookmarkView: "reader", + showNotes: false, }, }, setSettings: async (settings) => { -- cgit v1.2.3-70-g09d2