aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-11-23 10:15:23 +0000
committerGitHub <noreply@github.com>2025-11-23 10:15:23 +0000
commit48ab8a194974e026104bb2566cf8abd693ba51c1 (patch)
tree012ee677cbaf9d0f323a890a752df497d88536f1 /apps
parented6a3bfac52437c0b86767d7a17dc1ae48d8ccb2 (diff)
downloadkarakeep-48ab8a194974e026104bb2566cf8abd693ba51c1.tar.zst
feat(mobile): Add smart list creation in mobile app (#2153)
* feat: Add smart list creation and display in mobile app This commit adds support for creating and displaying smart lists in the mobile application: - Enhanced list creation screen to support both manual and smart list types - Added type selector with manual/smart toggle buttons - Implemented conditional search query input for smart lists - Added query validation to ensure smart lists have valid queries - Improved error handling to display validation errors from the backend - Added visual indicators (sparkle icon) for smart lists in the lists tab - Implemented smart list query display in list detail view with sparkle badge - Enhanced UI with contextual help text for smart list queries The implementation follows the web app pattern while adapting the UI for mobile best practices. * fixes --------- Co-authored-by: Claude <noreply@anthropic.com>
Diffstat (limited to 'apps')
-rw-r--r--apps/mobile/app/dashboard/(tabs)/lists.tsx2
-rw-r--r--apps/mobile/app/dashboard/lists/new.tsx71
2 files changed, 69 insertions, 4 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx
index a2301c36..e40be1a5 100644
--- a/apps/mobile/app/dashboard/(tabs)/lists.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx
@@ -161,7 +161,7 @@ export default function Lists() {
)}
<Link asChild key={l.item.id} href={l.item.href} className="flex-1">
- <Pressable className="flex flex-row justify-between">
+ <Pressable className="flex flex-row items-center justify-between">
<Text>
{l.item.logo} {l.item.name}
</Text>
diff --git a/apps/mobile/app/dashboard/lists/new.tsx b/apps/mobile/app/dashboard/lists/new.tsx
index 55315e70..af51ed15 100644
--- a/apps/mobile/app/dashboard/lists/new.tsx
+++ b/apps/mobile/app/dashboard/lists/new.tsx
@@ -9,35 +9,81 @@ import { useToast } from "@/components/ui/Toast";
import { useCreateBookmarkList } from "@karakeep/shared-react/hooks/lists";
+type ListType = "manual" | "smart";
+
const NewListPage = () => {
const dismiss = () => {
router.back();
};
const { toast } = useToast();
const [text, setText] = useState("");
+ const [listType, setListType] = useState<ListType>("manual");
+ const [query, setQuery] = useState("");
const { mutate, isPending } = useCreateBookmarkList({
onSuccess: () => {
dismiss();
},
- onError: () => {
+ onError: (error) => {
+ // Extract error message from the error object
+ let errorMessage = "Something went wrong";
+ if (error.data?.zodError) {
+ errorMessage = Object.values(error.data.zodError.fieldErrors)
+ .flat()
+ .join("\n");
+ } else if (error.message) {
+ errorMessage = error.message;
+ }
toast({
- message: "Something went wrong",
+ message: errorMessage,
variant: "destructive",
});
},
});
const onSubmit = () => {
+ // Validate smart list has a query
+ if (listType === "smart" && !query.trim()) {
+ toast({
+ message: "Smart lists must have a search query",
+ variant: "destructive",
+ });
+ return;
+ }
+
mutate({
name: text,
icon: "🚀",
+ type: listType,
+ query: listType === "smart" ? query : undefined,
});
};
return (
<CustomSafeAreaView>
- <View className="gap-2 px-4">
+ <View className="gap-3 px-4">
+ {/* List Type Selector */}
+ <View className="gap-2">
+ <Text className="text-sm text-muted-foreground">List Type</Text>
+ <View className="flex flex-row gap-2">
+ <Button
+ variant={listType === "manual" ? "primary" : "secondary"}
+ onPress={() => setListType("manual")}
+ className="flex-1"
+ >
+ <Text>Manual</Text>
+ </Button>
+ <Button
+ variant={listType === "smart" ? "primary" : "secondary"}
+ onPress={() => setListType("smart")}
+ className="flex-1"
+ >
+ <Text>Smart</Text>
+ </Button>
+ </View>
+ </View>
+
+ {/* List Name */}
<View className="flex flex-row items-center gap-1">
<Text className="shrink p-2">🚀</Text>
<Input
@@ -48,6 +94,25 @@ const NewListPage = () => {
autoCapitalize={"none"}
/>
</View>
+
+ {/* Smart List Query Input */}
+ {listType === "smart" && (
+ <View className="gap-2">
+ <Text className="text-sm text-muted-foreground">Search Query</Text>
+ <Input
+ className="bg-card"
+ onChangeText={setQuery}
+ value={query}
+ placeholder="e.g., #important OR list:work"
+ autoCapitalize={"none"}
+ />
+ <Text className="text-xs italic text-muted-foreground">
+ Smart lists automatically show bookmarks matching your search
+ query
+ </Text>
+ </View>
+ )}
+
<Button disabled={isPending} onPress={onSubmit}>
<Text>Save</Text>
</Button>