diff options
| author | MohamedBassem <me@mbassem.com> | 2024-08-26 18:00:00 +0300 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-08-26 18:00:42 +0300 |
| commit | 140554021e83ca375845584f8d7e5e476434f1c0 (patch) | |
| tree | 2dfd49ebd1718e2508b50a4c6828c5d8dce72a23 | |
| parent | 410b0e78962566d9eb97710e834bf0a477b8cef2 (diff) | |
| download | karakeep-140554021e83ca375845584f8d7e5e476434f1c0.tar.zst | |
feature(mobile): Add ability to create basic lists from the app
| -rw-r--r-- | apps/mobile/app.json | 4 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/lists.tsx | 32 | ||||
| -rw-r--r-- | apps/mobile/components/lists/NewListModal.tsx | 80 |
3 files changed, 111 insertions, 5 deletions
diff --git a/apps/mobile/app.json b/apps/mobile/app.json index b205b80d..baf2ca6e 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -30,7 +30,7 @@ "NSAllowsLocalNetworking": true } }, - "buildNumber": "7" + "buildNumber": "8" }, "android": { "adaptiveIcon": { @@ -48,7 +48,7 @@ } }, "package": "app.hoarder.hoardermobile", - "versionCode": 7 + "versionCode": 8 }, "plugins": [ "expo-router", diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx index 9e4b0929..c7e3a874 100644 --- a/apps/mobile/app/dashboard/(tabs)/lists.tsx +++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx @@ -1,15 +1,32 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { FlatList, Pressable, Text, View } from "react-native"; +import * as Haptics from "expo-haptics"; import { Link } from "expo-router"; +import NewListModal from "@/components/lists/NewListModal"; import { TailwindResolver } from "@/components/TailwindResolver"; import CustomSafeAreaView from "@/components/ui/CustomSafeAreaView"; import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; -import { ChevronRight } from "lucide-react-native"; +import { BottomSheetModal } from "@gorhom/bottom-sheet"; +import { ChevronRight, Plus } from "lucide-react-native"; import { useBookmarkLists } from "@hoarder/shared-react/hooks/lists"; import { ZBookmarkListTreeNode } from "@hoarder/shared/utils/listUtils"; +function HeaderRight({ openNewListModal }: { openNewListModal: () => void }) { + return ( + <Pressable + className="my-auto px-4" + onPress={() => { + Haptics.selectionAsync(); + openNewListModal(); + }} + > + <Plus color="rgb(0, 122, 255)" /> + </Pressable> + ); +} + interface ListLink { id: string; logo: string; @@ -53,6 +70,7 @@ export default function Lists() { {}, ); const apiUtils = api.useUtils(); + const newListModal = useRef<BottomSheetModal>(null); useEffect(() => { setRefreshing(isPending); @@ -94,9 +112,17 @@ export default function Lists() { return ( <CustomSafeAreaView> + <NewListModal ref={newListModal} snapPoints={["90%"]} /> <FlatList className="h-full" - ListHeaderComponent={<PageTitle title="Lists" />} + ListHeaderComponent={ + <View className="flex flex-row justify-between"> + <PageTitle title="Lists" /> + <HeaderRight + openNewListModal={() => newListModal.current?.present()} + /> + </View> + } contentContainerStyle={{ gap: 5, }} diff --git a/apps/mobile/components/lists/NewListModal.tsx b/apps/mobile/components/lists/NewListModal.tsx new file mode 100644 index 00000000..d31ac362 --- /dev/null +++ b/apps/mobile/components/lists/NewListModal.tsx @@ -0,0 +1,80 @@ +import React, { useState } from "react"; +import { Text, View } from "react-native"; +import { + BottomSheetBackdrop, + BottomSheetModal, + BottomSheetModalProps, + BottomSheetView, + useBottomSheetModal, +} from "@gorhom/bottom-sheet"; + +import { useCreateBookmarkList } from "@hoarder/shared-react/hooks/lists"; + +import { Button } from "../ui/Button"; +import { Input } from "../ui/Input"; +import PageTitle from "../ui/PageTitle"; +import { useToast } from "../ui/Toast"; + +const NewListModal = React.forwardRef< + BottomSheetModal, + Omit<BottomSheetModalProps, "children" | "backdropComponent" | "onDismiss"> +>(({ ...props }, ref) => { + const { dismiss } = useBottomSheetModal(); + const { toast } = useToast(); + const [text, setText] = useState(""); + + const { mutate, isPending } = useCreateBookmarkList({ + onSuccess: () => { + dismiss(); + }, + onError: () => { + toast({ + message: "Something went wrong", + variant: "destructive", + }); + }, + }); + + const onSubmit = () => { + mutate({ + name: text, + icon: "🚀", + }); + }; + + return ( + <View> + <BottomSheetModal + ref={ref} + onDismiss={() => setText("")} + backdropComponent={(props) => ( + <BottomSheetBackdrop + appearsOnIndex={0} + disappearsOnIndex={-1} + {...props} + /> + )} + {...props} + > + <PageTitle title="New List" /> + <BottomSheetView className="gap-2 px-4"> + <BottomSheetView className="flex flex-row items-center gap-1"> + <Text className="shrink p-2">🚀</Text> + <Input + className="flex-1" + onChangeText={setText} + placeholder="List Name" + autoFocus + autoCapitalize={"none"} + /> + </BottomSheetView> + <Button disabled={isPending} onPress={onSubmit} label="Save" /> + </BottomSheetView> + </BottomSheetModal> + </View> + ); +}); + +NewListModal.displayName = "NewListModal"; + +export default NewListModal; |
