aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/mobile/components/bookmarks/BookmarkCard.tsx49
-rw-r--r--packages/mobile/package.json1
-rw-r--r--pnpm-lock.yaml72
3 files changed, 107 insertions, 15 deletions
diff --git a/packages/mobile/components/bookmarks/BookmarkCard.tsx b/packages/mobile/components/bookmarks/BookmarkCard.tsx
index 17e675df..57e601f7 100644
--- a/packages/mobile/components/bookmarks/BookmarkCard.tsx
+++ b/packages/mobile/components/bookmarks/BookmarkCard.tsx
@@ -2,6 +2,7 @@ import { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { ZBookmarkTags } from "@hoarder/trpc/types/tags";
import { Star, Archive, Trash } from "lucide-react-native";
import { View, Text, Image, ScrollView, Pressable } from "react-native";
+import Markdown from "react-native-markdown-display";
import { api } from "@/lib/trpc";
@@ -65,7 +66,10 @@ function TagList({ tags }: { tags: ZBookmarkTags[] }) {
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View className="flex flex-row gap-2">
{tags.map((t) => (
- <View className="rounded-full border border-gray-200 px-2.5 py-0.5 text-xs font-semibold">
+ <View
+ key={t.id}
+ className="rounded-full border border-gray-200 px-2.5 py-0.5 text-xs font-semibold"
+ >
<Text>{t.name}</Text>
</View>
))}
@@ -82,25 +86,41 @@ function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
const parsedUrl = new URL(bookmark.content.url);
return (
- <View className="flex gap-2 rounded bg-white p-4">
+ <View className="flex gap-2">
<Image
source={{ uri: bookmark.content.imageUrl || "" }}
className="h-56 min-h-56 w-full"
/>
- <Text className="line-clamp-2 text-xl font-bold">
- {bookmark.content.title || parsedUrl.host}
- </Text>
- <TagList tags={bookmark.tags} />
- <View className="mt-2 flex flex-row justify-between">
- <Text className="my-auto line-clamp-1">{parsedUrl.host}</Text>
- <ActionBar bookmark={bookmark} />
+ <View className="flex gap-2">
+ <Text className="line-clamp-2 text-xl font-bold">
+ {bookmark.content.title || parsedUrl.host}
+ </Text>
+ <TagList tags={bookmark.tags} />
+ <View className="mt-2 flex flex-row justify-between">
+ <Text className="my-auto line-clamp-1">{parsedUrl.host}</Text>
+ <ActionBar bookmark={bookmark} />
+ </View>
</View>
</View>
);
}
function TextCard({ bookmark }: { bookmark: ZBookmark }) {
- return <View />;
+ if (bookmark.content.type !== "text") {
+ throw new Error("Wrong content type rendered");
+ }
+ return (
+ <View className="flex max-h-96 gap-2">
+ <View className="max-h-56 overflow-hidden pb-2">
+ <Markdown>{bookmark.content.text}</Markdown>
+ </View>
+ <TagList tags={bookmark.tags} />
+ <View className="flex flex-row justify-between">
+ <View />
+ <ActionBar bookmark={bookmark} />
+ </View>
+ </View>
+ );
}
export default function BookmarkCard({
@@ -115,10 +135,15 @@ export default function BookmarkCard({
{ initialData },
);
+ let comp;
switch (bookmark.content.type) {
case "link":
- return <LinkCard bookmark={bookmark} />;
+ comp = <LinkCard bookmark={bookmark} />;
+ break;
case "text":
- return <TextCard bookmark={bookmark} />;
+ comp = <TextCard bookmark={bookmark} />;
+ break;
}
+
+ return <View className="rounded bg-white p-4">{comp}</View>;
}
diff --git a/packages/mobile/package.json b/packages/mobile/package.json
index bbc0127c..613bb3c3 100644
--- a/packages/mobile/package.json
+++ b/packages/mobile/package.json
@@ -26,6 +26,7 @@
"nativewind": "^4.0.1",
"react": "18.2.0",
"react-native": "0.73.4",
+ "react-native-markdown-display": "^7.0.2",
"react-native-reanimated": "^3.8.0",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2b2ae33a..b11597fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -232,9 +232,6 @@ importers:
lucide-react-native:
specifier: ^0.354.0
version: 0.354.0(react-native-svg@15.1.0)(react-native@0.73.4)(react@18.2.0)
- metro-cache:
- specifier: ^0.80.6
- version: 0.80.6
nativewind:
specifier: ^4.0.1
version: 4.0.36(@babel/core@7.23.9)(react-native-reanimated@3.8.0)(react-native-safe-area-context@4.8.2)(react-native-svg@15.1.0)(react-native@0.73.4)(react@18.2.0)(tailwindcss@3.3.2)
@@ -244,6 +241,9 @@ importers:
react-native:
specifier: 0.73.4
version: 0.73.4(@babel/core@7.23.9)(@babel/preset-env@7.24.0)(react@18.2.0)
+ react-native-markdown-display:
+ specifier: ^7.0.2
+ version: 7.0.2(react-native@0.73.4)(react@18.2.0)
react-native-reanimated:
specifier: ^3.8.0
version: 3.8.0(@babel/core@7.23.9)(react-native@0.73.4)(react@18.2.0)
@@ -7097,6 +7097,10 @@ packages:
engines: {node: '>=14.16'}
dev: true
+ /camelize@1.0.1:
+ resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
+ dev: false
+
/caniuse-lite@1.0.30001589:
resolution: {integrity: sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==}
@@ -7674,6 +7678,11 @@ packages:
engines: {node: '>=8'}
dev: false
+ /css-color-keywords@1.0.0:
+ resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==}
+ engines: {node: '>=4'}
+ dev: false
+
/css-select@5.1.0:
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
dependencies:
@@ -7683,6 +7692,14 @@ packages:
domutils: 3.1.0
nth-check: 2.1.1
+ /css-to-react-native@3.2.0:
+ resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==}
+ dependencies:
+ camelize: 1.0.1
+ css-color-keywords: 1.0.0
+ postcss-value-parser: 4.2.0
+ dev: false
+
/css-tree@1.1.3:
resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
engines: {node: '>=8.0.0'}
@@ -8306,6 +8323,10 @@ packages:
graceful-fs: 4.2.11
tapable: 2.2.1
+ /entities@2.0.3:
+ resolution: {integrity: sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==}
+ dev: false
+
/entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -11433,6 +11454,12 @@ packages:
/lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ /linkify-it@2.2.0:
+ resolution: {integrity: sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==}
+ dependencies:
+ uc.micro: 1.0.6
+ dev: false
+
/loader-runner@4.3.0:
resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
engines: {node: '>=6.11.5'}
@@ -11694,6 +11721,17 @@ packages:
tmpl: 1.0.5
dev: false
+ /markdown-it@10.0.0:
+ resolution: {integrity: sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==}
+ hasBin: true
+ dependencies:
+ argparse: 1.0.10
+ entities: 2.0.3
+ linkify-it: 2.2.0
+ mdurl: 1.0.1
+ uc.micro: 1.0.6
+ dev: false
+
/marky@1.2.5:
resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==}
dev: false
@@ -11835,6 +11873,10 @@ packages:
resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
dev: false
+ /mdurl@1.0.1:
+ resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
+ dev: false
+
/meilisearch@0.37.0:
resolution: {integrity: sha512-LdbK6JmRghCawrmWKJSEQF0OiE82md+YqJGE/U2JcCD8ROwlhTx0KM6NX4rQt0u0VpV0QZVG9umYiu3CSSIJAQ==}
dependencies:
@@ -14246,6 +14288,26 @@ packages:
- supports-color
dev: false
+ /react-native-fit-image@1.5.5:
+ resolution: {integrity: sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg==}
+ dependencies:
+ prop-types: 15.8.1
+ dev: false
+
+ /react-native-markdown-display@7.0.2(react-native@0.73.4)(react@18.2.0):
+ resolution: {integrity: sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ==}
+ peerDependencies:
+ react: '>=16.2.0'
+ react-native: '>=0.50.4'
+ dependencies:
+ css-to-react-native: 3.2.0
+ markdown-it: 10.0.0
+ prop-types: 15.8.1
+ react: 18.2.0
+ react-native: 0.73.4(@babel/core@7.23.9)(@babel/preset-env@7.24.0)(react@18.2.0)
+ react-native-fit-image: 1.5.5
+ dev: false
+
/react-native-reanimated@3.8.0(@babel/core@7.23.9)(react-native@0.73.4)(react@18.2.0):
resolution: {integrity: sha512-xoG4+nf+lSmzv37mjTUIT0gYNEIr2Mb8WXgmqR8deCJk8CC6lXT0HRpshTPVAF00LvdzrD2W/rCpiBdHN5FW2w==}
peerDependencies:
@@ -16123,6 +16185,10 @@ packages:
resolution: {integrity: sha512-pGtPAQmLwh+R9w81WVHzui1FfedpQWQpiaIIfPCwhtsBez4q6DYbJFfyXPVHPUTNFnedAvNEnkoFiLuhXIR94w==}
dev: true
+ /uc.micro@1.0.6:
+ resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
+ dev: false
+
/ufo@1.4.0:
resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==}
dev: true