From aa8df79ab48c2e2d9f8b10fbdf4d71197f41303e Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Fri, 15 Mar 2024 12:01:11 +0000 Subject: mobile: Revamp bookmark card's action bar --- apps/mobile/components/bookmarks/BookmarkCard.tsx | 145 +++++++++++++--------- apps/mobile/package.json | 4 +- 2 files changed, 92 insertions(+), 57 deletions(-) (limited to 'apps') diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx index 2189b385..07d7f4fe 100644 --- a/apps/mobile/components/bookmarks/BookmarkCard.tsx +++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx @@ -1,12 +1,21 @@ -import { Image, Pressable, ScrollView, Text, View } from "react-native"; +import { + ActivityIndicator, + Image, + Platform, + Pressable, + ScrollView, + Text, + View, +} from "react-native"; import Markdown from "react-native-markdown-display"; +import * as Haptics from "expo-haptics"; import * as WebBrowser from "expo-web-browser"; import { api } from "@/lib/trpc"; -import { Archive, ArchiveRestore, Star, Trash } from "lucide-react-native"; +import { MenuView } from "@react-native-menu/menu"; +import { Ellipsis, Star } from "lucide-react-native"; import type { ZBookmark } from "@hoarder/trpc/types/bookmarks"; -import { ActionButton } from "../ui/ActionButton"; import { Divider } from "../ui/Divider"; import { Skeleton } from "../ui/Skeleton"; import { useToast } from "../ui/Toast"; @@ -36,46 +45,59 @@ function ActionBar({ bookmark }: { bookmark: ZBookmark }) { const { toast } = useToast(); const apiUtils = api.useUtils(); + const onError = () => { + toast({ + message: "Something went wrong", + variant: "destructive", + showProgress: false, + }); + }; + const { mutate: deleteBookmark, isPending: isDeletionPending } = api.bookmarks.deleteBookmark.useMutation({ + onSuccess: () => { + toast({ + message: 'The bookmark has been deleted!', + showProgress: false, + }); + apiUtils.bookmarks.getBookmarks.invalidate(); + }, + onError, + }); + + const { mutate: favouriteBookmark, variables } = + api.bookmarks.updateBookmark.useMutation({ onSuccess: () => { apiUtils.bookmarks.getBookmarks.invalidate(); + apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: bookmark.id }); }, - onError: () => { + onError, + }); + + const { mutate: archiveBookmark, isPending: isArchivePending } = + api.bookmarks.updateBookmark.useMutation({ + onSuccess: (resp) => { toast({ - message: "Something went wrong", - variant: "destructive", + message: `The bookmark has been ${resp.archived ? "archived" : "un-archived"}!`, showProgress: false, }); + apiUtils.bookmarks.getBookmarks.invalidate(); + apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: bookmark.id }); }, + onError, }); - const { - mutate: updateBookmark, - variables, - isPending: isUpdatePending, - } = api.bookmarks.updateBookmark.useMutation({ - onSuccess: () => { - apiUtils.bookmarks.getBookmarks.invalidate(); - apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: bookmark.id }); - }, - onError: () => { - toast({ - message: "Something went wrong", - variant: "destructive", - showProgress: false, - }); - }, - }); return ( + {(isArchivePending || isDeletionPending) && } - updateBookmark({ + onPress={() => { + Haptics.selectionAsync(); + favouriteBookmark({ bookmarkId: bookmark.id, favourited: !bookmark.favourited, - }) - } + }); + }} > {(variables ? variables.favourited : bookmark.favourited) ? ( @@ -83,31 +105,46 @@ function ActionBar({ bookmark }: { bookmark: ZBookmark }) { )} - - updateBookmark({ - bookmarkId: bookmark.id, - archived: !bookmark.archived, - }) - } - > - {bookmark.archived ? ( - - ) : ( - - )} - - - deleteBookmark({ - bookmarkId: bookmark.id, - }) - } + + { + Haptics.selectionAsync(); + if (nativeEvent.event === "delete") { + deleteBookmark({ + bookmarkId: bookmark.id, + }); + } else if (nativeEvent.event === "archive") { + archiveBookmark({ + bookmarkId: bookmark.id, + archived: !bookmark.archived, + }); + } + }} + actions={[ + { + id: "archive", + title: bookmark.archived ? "Un-archive" : "Archive", + image: Platform.select({ + ios: "folder", + android: "ic_menu_folder", + }), + }, + { + id: "delete", + title: "Delete", + attributes: { + destructive: true, + }, + image: Platform.select({ + ios: "trash", + android: "ic_menu_delete", + }), + }, + ]} + shouldOpenOnLongPress={false} > - - + Haptics.selectionAsync()} color="gray" /> + ); } @@ -236,9 +273,5 @@ export default function BookmarkCard({ break; } - return ( - - {comp} - - ); + return {comp}; } diff --git a/apps/mobile/package.json b/apps/mobile/package.json index ead5e796..71dff6cc 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@hoarder/trpc": "0.1.0", + "@react-native-menu/menu": "^0.9.1", "@tanstack/react-query": "^5.24.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", @@ -20,6 +21,7 @@ "expo-config-plugin-ios-share-extension": "^0.0.4", "expo-constants": "~15.4.5", "expo-dev-client": "^3.3.9", + "expo-haptics": "^12.8.1", "expo-image": "^1.10.6", "expo-linking": "~6.2.2", "expo-router": "~3.4.8", @@ -42,11 +44,11 @@ "zustand": "^4.5.1" }, "devDependencies": { + "@babel/core": "^7.20.0", "@hoarder/eslint-config": "workspace:^0.2.0", "@hoarder/prettier-config": "workspace:^0.1.0", "@hoarder/tailwind-config": "workspace:^0.1.0", "@hoarder/tsconfig": "workspace:^0.1.0", - "@babel/core": "^7.20.0", "@types/react": "^18.2.55", "ajv": "latest", "eslint": "^8.57.0", -- cgit v1.2.3-70-g09d2