aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/mobile/app/dashboard/bookmarks/[slug].tsx82
-rw-r--r--apps/mobile/components/bookmarks/BookmarkAssetImage.tsx23
-rw-r--r--apps/mobile/components/bookmarks/BookmarkCard.tsx71
-rw-r--r--apps/mobile/components/bookmarks/BookmarkTextMarkdown.tsx21
4 files changed, 160 insertions, 37 deletions
diff --git a/apps/mobile/app/dashboard/bookmarks/[slug].tsx b/apps/mobile/app/dashboard/bookmarks/[slug].tsx
new file mode 100644
index 00000000..c7b0cead
--- /dev/null
+++ b/apps/mobile/app/dashboard/bookmarks/[slug].tsx
@@ -0,0 +1,82 @@
+import { View } from "react-native";
+import { Stack, useLocalSearchParams } from "expo-router";
+import BookmarkAssetImage from "@/components/bookmarks/BookmarkAssetImage";
+import BookmarkTextMarkdown from "@/components/bookmarks/BookmarkTextMarkdown";
+import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView";
+import FullPageSpinner from "@/components/ui/FullPageSpinner";
+import PageTitle from "@/components/ui/PageTitle";
+import { api } from "@/lib/trpc";
+
+import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";
+
+function BookmarkTextView({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type !== BookmarkTypes.TEXT) {
+ throw new Error("Wrong content type rendered");
+ }
+ const content = bookmark.content.text;
+
+ return (
+ <View className="flex gap-2">
+ <BookmarkTextMarkdown text={content} />
+ </View>
+ );
+}
+
+function BookmarkAssetView({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type !== BookmarkTypes.ASSET) {
+ throw new Error("Wrong content type rendered");
+ }
+ return (
+ <View className="flex gap-2">
+ <BookmarkAssetImage
+ assetId={bookmark.content.assetId}
+ className="h-56 min-h-56 w-full object-cover"
+ />
+ </View>
+ );
+}
+
+export default function BookmarkView() {
+ const { slug } = useLocalSearchParams();
+ if (typeof slug !== "string") {
+ throw new Error("Unexpected param type");
+ }
+
+ const { data: bookmark } = api.bookmarks.getBookmark.useQuery({
+ bookmarkId: slug,
+ });
+
+ let comp;
+ let title = null;
+ if (bookmark) {
+ switch (bookmark.content.type) {
+ case BookmarkTypes.LINK:
+ comp = null;
+ break;
+ case BookmarkTypes.TEXT:
+ title = bookmark.title;
+ comp = <BookmarkTextView bookmark={bookmark} />;
+ break;
+ case BookmarkTypes.ASSET:
+ title = bookmark.title ?? bookmark.content.fileName;
+ comp = <BookmarkAssetView bookmark={bookmark} />;
+ break;
+ }
+ } else {
+ comp = <FullPageSpinner />;
+ }
+
+ return (
+ <CustomSafeAreaView>
+ <Stack.Screen
+ options={{
+ headerTitle: "",
+ headerBackTitle: "Back",
+ headerTransparent: true,
+ }}
+ />
+ <PageTitle title={title ?? "Untitled"} />
+ <View className="px-4 py-2">{comp}</View>
+ </CustomSafeAreaView>
+ );
+}
diff --git a/apps/mobile/components/bookmarks/BookmarkAssetImage.tsx b/apps/mobile/components/bookmarks/BookmarkAssetImage.tsx
new file mode 100644
index 00000000..95f963f4
--- /dev/null
+++ b/apps/mobile/components/bookmarks/BookmarkAssetImage.tsx
@@ -0,0 +1,23 @@
+import { Image } from "react-native";
+import useAppSettings from "@/lib/settings";
+
+export default function BookmarkAssetImage({
+ assetId,
+ className,
+}: {
+ assetId: string;
+ className: string;
+}) {
+ const { settings } = useAppSettings();
+ return (
+ <Image
+ source={{
+ uri: `${settings.address}/api/assets/${assetId}`,
+ headers: {
+ Authorization: `Bearer ${settings.apiKey}`,
+ },
+ }}
+ className={className}
+ />
+ );
+}
diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx
index 3be1f9a0..860e5486 100644
--- a/apps/mobile/components/bookmarks/BookmarkCard.tsx
+++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx
@@ -8,9 +8,8 @@ import {
Text,
View,
} from "react-native";
-import Markdown from "react-native-markdown-display";
import * as Haptics from "expo-haptics";
-import { Link } from "expo-router";
+import { Link, router } from "expo-router";
import * as WebBrowser from "expo-web-browser";
import useAppSettings from "@/lib/settings";
import { api } from "@/lib/trpc";
@@ -30,10 +29,11 @@ import {
} from "@hoarder/shared-react/utils/bookmarkUtils";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";
-import { TailwindResolver } from "../TailwindResolver";
import { Divider } from "../ui/Divider";
import { Skeleton } from "../ui/Skeleton";
import { useToast } from "../ui/Toast";
+import BookmarkAssetImage from "./BookmarkAssetImage";
+import BookmarkTextMarkdown from "./BookmarkTextMarkdown";
import ListPickerModal from "./ListPickerModal";
function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
@@ -250,26 +250,21 @@ function TextCard({ bookmark }: { bookmark: ZBookmark }) {
const content = bookmark.content.text;
return (
<View className="flex max-h-96 gap-2 p-2">
- {bookmark.title && (
- <Text className="line-clamp-2 text-xl font-bold text-foreground">
- {bookmark.title}
- </Text>
- )}
+ <Pressable
+ onPress={() => router.push(`/dashboard/bookmarks/${bookmark.id}`)}
+ >
+ {bookmark.title && (
+ <Text className="line-clamp-2 text-xl font-bold text-foreground">
+ {bookmark.title}
+ </Text>
+ )}
+ </Pressable>
<View className="max-h-56 overflow-hidden p-2 text-foreground">
- <TailwindResolver
- className="text-foreground"
- comp={(styles) => (
- <Markdown
- style={{
- text: {
- color: styles?.color?.toString(),
- },
- }}
- >
- {content}
- </Markdown>
- )}
- />
+ <Pressable
+ onPress={() => router.push(`/dashboard/bookmarks/${bookmark.id}`)}
+ >
+ <BookmarkTextMarkdown text={content} />
+ </Pressable>
</View>
<TagList bookmark={bookmark} />
<Divider orientation="vertical" className="mt-2 h-0.5 w-full" />
@@ -282,7 +277,6 @@ function TextCard({ bookmark }: { bookmark: ZBookmark }) {
}
function AssetCard({ bookmark }: { bookmark: ZBookmark }) {
- const { settings } = useAppSettings();
if (bookmark.content.type !== BookmarkTypes.ASSET) {
throw new Error("Wrong content type rendered");
}
@@ -290,21 +284,24 @@ function AssetCard({ bookmark }: { bookmark: ZBookmark }) {
return (
<View className="flex gap-2">
- <Image
- source={{
- uri: `${settings.address}/api/assets/${bookmark.content.assetId}`,
- headers: {
- Authorization: `Bearer ${settings.apiKey}`,
- },
- }}
- className="h-56 min-h-56 w-full object-cover"
- />
+ <Pressable
+ onPress={() => router.push(`/dashboard/bookmarks/${bookmark.id}`)}
+ >
+ <BookmarkAssetImage
+ assetId={bookmark.content.assetId}
+ className="h-56 min-h-56 w-full object-cover"
+ />
+ </Pressable>
<View className="flex gap-2 p-2">
- {title && (
- <Text className="line-clamp-2 text-xl font-bold text-foreground">
- {title}
- </Text>
- )}
+ <Pressable
+ onPress={() => router.push(`/dashboard/bookmarks/${bookmark.id}`)}
+ >
+ {title && (
+ <Text className="line-clamp-2 text-xl font-bold text-foreground">
+ {title}
+ </Text>
+ )}
+ </Pressable>
<TagList bookmark={bookmark} />
<Divider orientation="vertical" className="mt-2 h-0.5 w-full" />
<View className="mt-2 flex flex-row justify-between px-2 pb-2">
diff --git a/apps/mobile/components/bookmarks/BookmarkTextMarkdown.tsx b/apps/mobile/components/bookmarks/BookmarkTextMarkdown.tsx
new file mode 100644
index 00000000..80ea007c
--- /dev/null
+++ b/apps/mobile/components/bookmarks/BookmarkTextMarkdown.tsx
@@ -0,0 +1,21 @@
+import Markdown from "react-native-markdown-display";
+import { TailwindResolver } from "@/components/TailwindResolver";
+
+export default function BookmarkTextMarkdown({ text }: { text: string }) {
+ return (
+ <TailwindResolver
+ className="text-foreground"
+ comp={(styles) => (
+ <Markdown
+ style={{
+ text: {
+ color: styles?.color?.toString(),
+ },
+ }}
+ >
+ {text}
+ </Markdown>
+ )}
+ />
+ );
+}