aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/mobile/components/bookmarks/BookmarkCard.tsx19
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx21
-rw-r--r--apps/web/components/dashboard/bookmarks/DeleteBookmarkConfirmationDialog.tsx63
-rw-r--r--apps/web/components/dashboard/preview/ActionBar.tsx37
-rw-r--r--apps/web/lib/i18n/locales/en/translation.json6
-rw-r--r--pnpm-lock.yaml2
6 files changed, 110 insertions, 38 deletions
diff --git a/apps/mobile/components/bookmarks/BookmarkCard.tsx b/apps/mobile/components/bookmarks/BookmarkCard.tsx
index 13d639c9..ce294a6f 100644
--- a/apps/mobile/components/bookmarks/BookmarkCard.tsx
+++ b/apps/mobile/components/bookmarks/BookmarkCard.tsx
@@ -1,5 +1,6 @@
import {
ActivityIndicator,
+ Alert,
Image,
Platform,
Pressable,
@@ -70,6 +71,20 @@ function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
onError,
});
+ const deleteBookmarkAlert = () =>
+ Alert.alert(
+ "Delete bookmark?",
+ "Are you sure you want to delete this bookmark?",
+ [
+ { text: "Cancel", style: "cancel" },
+ {
+ text: "Delete",
+ onPress: () => deleteBookmark({ bookmarkId: bookmark.id }),
+ style: "destructive",
+ },
+ ],
+ );
+
return (
<View className="flex flex-row gap-4">
{(isArchivePending || isDeletionPending) && <ActivityIndicator />}
@@ -93,9 +108,7 @@ function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
onPressAction={({ nativeEvent }) => {
Haptics.selectionAsync();
if (nativeEvent.event === "delete") {
- deleteBookmark({
- bookmarkId: bookmark.id,
- });
+ deleteBookmarkAlert();
} else if (nativeEvent.event === "archive") {
archiveBookmark({
bookmarkId: bookmark.id,
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
index 8dfb96fd..e9e5834b 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
@@ -28,7 +28,6 @@ import type {
ZBookmarkedLink,
} from "@hoarder/shared/types/bookmarks";
import {
- useDeleteBookmark,
useRecrawlBookmark,
useUpdateBookmark,
} from "@hoarder/shared-react/hooks//bookmarks";
@@ -37,6 +36,7 @@ import { useBookmarkGridContext } from "@hoarder/shared-react/hooks/bookmark-gri
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";
import { BookmarkedTextEditor } from "./BookmarkedTextEditor";
+import DeleteBookmarkConfirmationDialog from "./DeleteBookmarkConfirmationDialog";
import { ArchivedActionIcon, FavouritedActionIcon } from "./icons";
import { useManageListsModal } from "./ManageListsModal";
import { useTagModel } from "./TagModal";
@@ -53,6 +53,8 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
const { setOpen: setManageListsModalOpen, content: manageListsModal } =
useManageListsModal(bookmark.id);
+ const [deleteBookmarkDialogOpen, setDeleteBookmarkDialogOpen] =
+ useState(false);
const [isTextEditorOpen, setTextEditorOpen] = useState(false);
const { listId } = useBookmarkGridContext() ?? {};
@@ -63,14 +65,6 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
title: t("common.something_went_wrong"),
});
};
- const deleteBookmarkMutator = useDeleteBookmark({
- onSuccess: () => {
- toast({
- description: t("toasts.bookmarks.deleted"),
- });
- },
- onError,
- });
const updateBookmarkMutator = useUpdateBookmark({
onSuccess: () => {
@@ -112,6 +106,11 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
<>
{tagModal}
{manageListsModal}
+ <DeleteBookmarkConfirmationDialog
+ bookmark={bookmark}
+ open={deleteBookmarkDialogOpen}
+ setOpen={setDeleteBookmarkDialogOpen}
+ />
<BookmarkedTextEditor
bookmark={bookmark}
open={isTextEditorOpen}
@@ -240,9 +239,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
<DropdownMenuItem
disabled={demoMode}
className="text-destructive"
- onClick={() =>
- deleteBookmarkMutator.mutate({ bookmarkId: bookmark.id })
- }
+ onClick={() => setDeleteBookmarkDialogOpen(true)}
>
<Trash2 className="mr-2 size-4" />
<span>{t("actions.delete")}</span>
diff --git a/apps/web/components/dashboard/bookmarks/DeleteBookmarkConfirmationDialog.tsx b/apps/web/components/dashboard/bookmarks/DeleteBookmarkConfirmationDialog.tsx
new file mode 100644
index 00000000..4a69e3d0
--- /dev/null
+++ b/apps/web/components/dashboard/bookmarks/DeleteBookmarkConfirmationDialog.tsx
@@ -0,0 +1,63 @@
+import { usePathname, useRouter } from "next/navigation";
+import { ActionButton } from "@/components/ui/action-button";
+import ActionConfirmingDialog from "@/components/ui/action-confirming-dialog";
+import { toast } from "@/components/ui/use-toast";
+import { useTranslation } from "@/lib/i18n/client";
+
+import { useDeleteBookmark } from "@hoarder/shared-react/hooks//bookmarks";
+import { ZBookmark } from "@hoarder/shared/types/bookmarks";
+
+export default function DeleteBookmarkConfirmationDialog({
+ bookmark,
+ children,
+ open,
+ setOpen,
+}: {
+ bookmark: ZBookmark;
+ children?: React.ReactNode;
+ open: boolean;
+ setOpen: (v: boolean) => void;
+}) {
+ const { t } = useTranslation();
+ const currentPath = usePathname();
+ const router = useRouter();
+
+ const { mutate: deleteBoomark, isPending } = useDeleteBookmark({
+ onSuccess: () => {
+ toast({
+ description: t("toasts.bookmarks.deleted"),
+ });
+ setOpen(false);
+ if (currentPath.includes(bookmark.id)) {
+ router.push("/dashboard/bookmarks");
+ }
+ },
+ onError: () => {
+ toast({
+ variant: "destructive",
+ description: `Something went wrong`,
+ });
+ },
+ });
+
+ return (
+ <ActionConfirmingDialog
+ open={open}
+ setOpen={setOpen}
+ title={t("dialogs.bookmarks.delete_confirmation_title")}
+ description={t("dialogs.bookmarks.delete_confirmation_description")}
+ actionButton={() => (
+ <ActionButton
+ type="button"
+ variant="destructive"
+ loading={isPending}
+ onClick={() => deleteBoomark({ bookmarkId: bookmark.id })}
+ >
+ Delete
+ </ActionButton>
+ )}
+ >
+ {children}
+ </ActionConfirmingDialog>
+ );
+}
diff --git a/apps/web/components/dashboard/preview/ActionBar.tsx b/apps/web/components/dashboard/preview/ActionBar.tsx
index 38ad8fa2..86c86d5a 100644
--- a/apps/web/components/dashboard/preview/ActionBar.tsx
+++ b/apps/web/components/dashboard/preview/ActionBar.tsx
@@ -1,5 +1,6 @@
-import { useRouter } from "next/navigation";
+import { useState } from "react";
import { ActionButton } from "@/components/ui/action-button";
+import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
@@ -10,16 +11,16 @@ import { useTranslation } from "@/lib/i18n/client";
import { Trash2 } from "lucide-react";
import type { ZBookmark } from "@hoarder/shared/types/bookmarks";
-import {
- useDeleteBookmark,
- useUpdateBookmark,
-} from "@hoarder/shared-react/hooks/bookmarks";
+import { useUpdateBookmark } from "@hoarder/shared-react/hooks/bookmarks";
+import DeleteBookmarkConfirmationDialog from "../bookmarks/DeleteBookmarkConfirmationDialog";
import { ArchivedActionIcon, FavouritedActionIcon } from "../bookmarks/icons";
export default function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
const { t } = useTranslation();
- const router = useRouter();
+ const [deleteBookmarkDialogOpen, setDeleteBookmarkDialogOpen] =
+ useState(false);
+
const onError = () => {
toast({
variant: "destructive",
@@ -44,16 +45,6 @@ export default function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
},
onError,
});
- const { mutate: deleteBookmark, isPending: pendingDeletion } =
- useDeleteBookmark({
- onSuccess: () => {
- toast({
- description: "The bookmark has been deleted!",
- });
- router.back();
- },
- onError,
- });
return (
<div className="flex items-center justify-center gap-3">
@@ -100,17 +91,19 @@ export default function ActionBar({ bookmark }: { bookmark: ZBookmark }) {
</TooltipContent>
</Tooltip>
<Tooltip delayDuration={0}>
+ <DeleteBookmarkConfirmationDialog
+ bookmark={bookmark}
+ open={deleteBookmarkDialogOpen}
+ setOpen={setDeleteBookmarkDialogOpen}
+ />
<TooltipTrigger asChild>
- <ActionButton
- loading={pendingDeletion}
+ <Button
className="size-14 rounded-full bg-background"
variant="none"
- onClick={() => {
- deleteBookmark({ bookmarkId: bookmark.id });
- }}
+ onClick={() => setDeleteBookmarkDialogOpen(true)}
>
<Trash2 />
- </ActionButton>
+ </Button>
</TooltipTrigger>
<TooltipContent side="bottom">{t("actions.delete")}</TooltipContent>
</Tooltip>
diff --git a/apps/web/lib/i18n/locales/en/translation.json b/apps/web/lib/i18n/locales/en/translation.json
index 92f6e956..cdd31922 100644
--- a/apps/web/lib/i18n/locales/en/translation.json
+++ b/apps/web/lib/i18n/locales/en/translation.json
@@ -243,6 +243,12 @@
}
}
},
+ "dialogs": {
+ "bookmarks": {
+ "delete_confirmation_title": "Delete Bookmark?",
+ "delete_confirmation_description": "Are you sure you want to delete this bookmark?"
+ }
+ },
"toasts": {
"bookmarks": {
"updated": "The bookmark has been updated!",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 29df9366..f9721ffb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -31059,4 +31059,4 @@ snapshots:
use-sync-external-store: 1.2.0(react@18.3.1)
dev: false
- zwitch@2.0.4: {}
+ zwitch@2.0.4: {} \ No newline at end of file