From 8a5a109cdf14b6503b6bd07aa667788924a12fe6 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sun, 23 Nov 2025 12:22:34 +0000
Subject: feat(mobile): Add highlights page to mobile app (#2156)

* feat: Add highlights page to mobile app

This commit adds a new highlights page to the mobile app where users can
view all their highlights with the following features:

- HighlightCard component: Displays individual highlights with colored borders,
  text, optional notes, timestamps, and a link to the source bookmark
- HighlightList component: Renders a scrollable list of highlights with
  pull-to-refresh and infinite scroll pagination
- UpdatingHighlightList component: Handles data fetching using tRPC infinite
  queries with automatic cache invalidation
- New /dashboard/highlights route with large header title
- Added navigation link in Settings tab under "App Settings"

All components follow the existing mobile app patterns and integrate with
the existing highlights API.

* make it a tab

---------

Co-authored-by: Claude <noreply@anthropic.com>
---
 .../mobile/components/highlights/HighlightList.tsx | 65 ++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 apps/mobile/components/highlights/HighlightList.tsx

(limited to 'apps/mobile/components/highlights/HighlightList.tsx')

diff --git a/apps/mobile/components/highlights/HighlightList.tsx b/apps/mobile/components/highlights/HighlightList.tsx
new file mode 100644
index 00000000..865add2a
--- /dev/null
+++ b/apps/mobile/components/highlights/HighlightList.tsx
@@ -0,0 +1,65 @@
+import { useRef } from "react";
+import { ActivityIndicator, Keyboard, View } from "react-native";
+import Animated, { LinearTransition } from "react-native-reanimated";
+import { Text } from "@/components/ui/Text";
+import { useScrollToTop } from "@react-navigation/native";
+
+import type { ZHighlight } from "@karakeep/shared/types/highlights";
+
+import HighlightCard from "./HighlightCard";
+
+export default function HighlightList({
+  highlights,
+  header,
+  onRefresh,
+  fetchNextPage,
+  isFetchingNextPage,
+  isRefreshing,
+}: {
+  highlights: ZHighlight[];
+  onRefresh: () => void;
+  isRefreshing: boolean;
+  fetchNextPage?: () => void;
+  header?: React.ReactElement;
+  isFetchingNextPage?: boolean;
+}) {
+  const flatListRef = useRef(null);
+  useScrollToTop(flatListRef);
+
+  return (
+    <Animated.FlatList
+      ref={flatListRef}
+      itemLayoutAnimation={LinearTransition}
+      ListHeaderComponent={header}
+      contentContainerStyle={{
+        gap: 15,
+        marginHorizontal: 15,
+        marginBottom: 15,
+      }}
+      renderItem={(h) => <HighlightCard highlight={h.item} />}
+      ListEmptyComponent={
+        <View className="items-center justify-center pt-4">
+          <Text variant="title3">No Highlights</Text>
+          <Text className="mt-2 text-center text-muted-foreground">
+            Highlights you create will appear here
+          </Text>
+        </View>
+      }
+      data={highlights}
+      refreshing={isRefreshing}
+      onRefresh={onRefresh}
+      onScrollBeginDrag={Keyboard.dismiss}
+      keyExtractor={(h) => h.id}
+      onEndReached={fetchNextPage}
+      ListFooterComponent={
+        isFetchingNextPage ? (
+          <View className="items-center">
+            <ActivityIndicator />
+          </View>
+        ) : (
+          <View />
+        )
+      }
+    />
+  );
+}
-- 
cgit v1.2.3-70-g09d2

