aboutsummaryrefslogtreecommitdiffstats
path: root/apps/mobile/app/dashboard
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-04-19 12:29:19 +0100
committerMohamedBassem <me@mbassem.com>2024-04-19 12:29:19 +0100
commit5ae6694da365c3c22b7dc00a999182e0310f6c38 (patch)
treeb2b69ff38647716e91c2be8473917670373a7d1a /apps/mobile/app/dashboard
parente0999f701cd1834c3d940113cd8dd5247c5fe95f (diff)
downloadkarakeep-5ae6694da365c3c22b7dc00a999182e0310f6c38.tar.zst
feature(mobile): Add support for nested listed on mobile
Diffstat (limited to 'apps/mobile/app/dashboard')
-rw-r--r--apps/mobile/app/dashboard/(tabs)/lists.tsx107
1 files changed, 89 insertions, 18 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx
index 53817bf2..ed085f3d 100644
--- a/apps/mobile/app/dashboard/(tabs)/lists.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx
@@ -4,11 +4,53 @@ import { Link } from "expo-router";
import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView";
import PageTitle from "@/components/ui/PageTitle";
import { api } from "@/lib/trpc";
-import { ChevronRight } from "lucide-react-native";
+import { ChevronRight, Triangle } from "lucide-react-native";
+
+import { useBookmarkLists } from "@hoarder/shared-react/hooks/lists";
+import { ZBookmarkListTreeNode } from "@hoarder/shared/utils/listUtils";
+
+interface ListLink {
+ id: string;
+ logo: string;
+ name: string;
+ href: string;
+ level: number;
+ parent?: string;
+ numChildren: number;
+ collapsed: boolean;
+}
+
+function traverseTree(
+ node: ZBookmarkListTreeNode,
+ links: ListLink[],
+ showChildrenOf: Record<string, boolean>,
+ parent?: string,
+ level = 0,
+) {
+ links.push({
+ id: node.item.id,
+ logo: node.item.icon,
+ name: node.item.name,
+ href: `/dashboard/lists/${node.item.id}`,
+ level,
+ parent,
+ numChildren: node.children?.length ?? 0,
+ collapsed: !showChildrenOf[node.item.id],
+ });
+
+ if (node.children && showChildrenOf[node.item.id]) {
+ node.children.forEach((child) =>
+ traverseTree(child, links, showChildrenOf, node.item.id, level + 1),
+ );
+ }
+}
export default function Lists() {
const [refreshing, setRefreshing] = useState(false);
- const { data: lists, isPending } = api.lists.list.useQuery();
+ const { data: lists, isPending } = useBookmarkLists();
+ const [showChildrenOf, setShowChildrenOf] = useState<Record<string, boolean>>(
+ {},
+ );
const apiUtils = api.useUtils();
useEffect(() => {
@@ -24,46 +66,75 @@ export default function Lists() {
apiUtils.lists.list.invalidate();
};
- const links = [
+ const links: ListLink[] = [
{
id: "fav",
logo: "⭐️",
name: "Favourites",
href: "/dashboard/favourites",
+ level: 0,
+ numChildren: 0,
+ collapsed: false,
},
{
id: "arch",
logo: "🗄️",
name: "Archive",
href: "/dashboard/archive",
+ level: 0,
+ numChildren: 0,
+ collapsed: false,
},
];
- links.push(
- ...lists.lists.map((l) => ({
- id: l.id,
- logo: l.icon,
- name: l.name,
- href: `/dashboard/lists/${l.id}`,
- })),
+ Object.values(lists.root).forEach((list) =>
+ traverseTree(list, links, showChildrenOf),
);
return (
<CustomSafeAreaView>
<FlatList
+ className="h-full"
ListHeaderComponent={<PageTitle title="Lists" />}
contentContainerStyle={{
gap: 5,
}}
renderItem={(l) => (
- <Link asChild key={l.item.id} href={l.item.href}>
- <Pressable className="mx-2 flex flex-row justify-between rounded-xl border border-input bg-white px-4 py-2 dark:bg-accent">
- <Text className="text-lg text-accent-foreground">
- {l.item.logo} {l.item.name}
- </Text>
- <ChevronRight color="rgb(0, 122, 255)" />
- </Pressable>
- </Link>
+ <View
+ className="mx-2 flex flex-row items-center gap-x-2 rounded-xl border border-input bg-white px-4 py-2 dark:bg-accent"
+ style={{ marginLeft: l.item.level * 20 }}
+ >
+ {l.item.numChildren > 0 && (
+ <Pressable
+ onPress={() => {
+ setShowChildrenOf((prev) => ({
+ ...prev,
+ [l.item.id]: !prev[l.item.id],
+ }));
+ }}
+ >
+ <Triangle
+ fill="black"
+ color="black"
+ size={10}
+ style={{
+ transform: [
+ { rotate: l.item.collapsed ? "90deg" : "180deg" },
+ ],
+ }}
+ />
+ </Pressable>
+ )}
+
+ <Link asChild key={l.item.id} href={l.item.href} className="flex-1">
+ <Pressable className="flex flex-row justify-between">
+ <Text className="text-lg text-accent-foreground">
+ {l.item.logo} {l.item.name}
+ </Text>
+ <ChevronRight color="rgb(0, 122, 255)" />
+ </Pressable>
+ </Link>
+ </View>
)}
data={links}
refreshing={refreshing}