136 lines
4.4 KiB
TypeScript
136 lines
4.4 KiB
TypeScript
import { useQueryClient } from "@tanstack/react-query";
|
|
import copy from "copy-to-clipboard";
|
|
import { useCallback } from "react";
|
|
import toast from "react-hot-toast";
|
|
import { useLocation } from "react-router-dom";
|
|
import { useInstance } from "@/contexts/InstanceContext";
|
|
import { useDeleteMemo, useUpdateMemo } from "@/hooks/useMemoQueries";
|
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
|
import { userKeys } from "@/hooks/useUserQueries";
|
|
import { State } from "@/types/proto/api/v1/common_pb";
|
|
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
|
|
import { useTranslate } from "@/utils/i18n";
|
|
import { removeCompletedTasks } from "@/utils/markdown-manipulation";
|
|
|
|
interface UseMemoActionHandlersOptions {
|
|
memo: Memo;
|
|
onEdit?: () => void;
|
|
setDeleteDialogOpen: (open: boolean) => void;
|
|
setRemoveTasksDialogOpen: (open: boolean) => void;
|
|
}
|
|
|
|
export const useMemoActionHandlers = ({ memo, onEdit, setDeleteDialogOpen, setRemoveTasksDialogOpen }: UseMemoActionHandlersOptions) => {
|
|
const t = useTranslate();
|
|
const location = useLocation();
|
|
const navigateTo = useNavigateTo();
|
|
const queryClient = useQueryClient();
|
|
const { profile } = useInstance();
|
|
const { mutateAsync: updateMemo } = useUpdateMemo();
|
|
const { mutateAsync: deleteMemo } = useDeleteMemo();
|
|
const isInMemoDetailPage = location.pathname.startsWith(`/${memo.name}`);
|
|
|
|
const memoUpdatedCallback = useCallback(() => {
|
|
// Invalidate user stats to trigger refetch
|
|
queryClient.invalidateQueries({ queryKey: userKeys.stats() });
|
|
}, [queryClient]);
|
|
|
|
const handleTogglePinMemoBtnClick = useCallback(async () => {
|
|
try {
|
|
await updateMemo({
|
|
update: {
|
|
name: memo.name,
|
|
pinned: !memo.pinned,
|
|
},
|
|
updateMask: ["pinned"],
|
|
});
|
|
} catch {
|
|
// do nothing
|
|
}
|
|
}, [memo.name, memo.pinned, updateMemo]);
|
|
|
|
const handleEditMemoClick = useCallback(() => {
|
|
onEdit?.();
|
|
}, [onEdit]);
|
|
|
|
const handleToggleMemoStatusClick = useCallback(async () => {
|
|
const state = memo.state === State.ARCHIVED ? State.NORMAL : State.ARCHIVED;
|
|
const message = memo.state === State.ARCHIVED ? t("message.restored-successfully") : t("message.archived-successfully");
|
|
|
|
try {
|
|
await updateMemo({
|
|
update: {
|
|
name: memo.name,
|
|
state,
|
|
},
|
|
updateMask: ["state"],
|
|
});
|
|
toast.success(message);
|
|
} catch (error: unknown) {
|
|
const err = error as { details?: string };
|
|
toast.error(err.details || "An error occurred");
|
|
console.error(error);
|
|
return;
|
|
}
|
|
|
|
if (isInMemoDetailPage) {
|
|
navigateTo(memo.state === State.ARCHIVED ? "/" : "/archived");
|
|
}
|
|
memoUpdatedCallback();
|
|
}, [memo.name, memo.state, t, isInMemoDetailPage, navigateTo, memoUpdatedCallback, updateMemo]);
|
|
|
|
const handleCopyLink = useCallback(() => {
|
|
let host = profile.instanceUrl;
|
|
if (host === "") {
|
|
host = window.location.origin;
|
|
}
|
|
copy(`${host}/${memo.name}`);
|
|
toast.success(t("message.succeed-copy-link"));
|
|
}, [memo.name, t, profile.instanceUrl]);
|
|
|
|
const handleCopyContent = useCallback(() => {
|
|
copy(memo.content);
|
|
toast.success(t("message.succeed-copy-content"));
|
|
}, [memo.content, t]);
|
|
|
|
const handleDeleteMemoClick = useCallback(() => {
|
|
setDeleteDialogOpen(true);
|
|
}, [setDeleteDialogOpen]);
|
|
|
|
const confirmDeleteMemo = useCallback(async () => {
|
|
await deleteMemo(memo.name);
|
|
toast.success(t("message.deleted-successfully"));
|
|
if (isInMemoDetailPage) {
|
|
navigateTo("/");
|
|
}
|
|
memoUpdatedCallback();
|
|
}, [memo.name, t, isInMemoDetailPage, navigateTo, memoUpdatedCallback, deleteMemo]);
|
|
|
|
const handleRemoveCompletedTaskListItemsClick = useCallback(() => {
|
|
setRemoveTasksDialogOpen(true);
|
|
}, [setRemoveTasksDialogOpen]);
|
|
|
|
const confirmRemoveCompletedTaskListItems = useCallback(async () => {
|
|
const newContent = removeCompletedTasks(memo.content);
|
|
await updateMemo({
|
|
update: {
|
|
name: memo.name,
|
|
content: newContent,
|
|
},
|
|
updateMask: ["content"],
|
|
});
|
|
toast.success(t("message.remove-completed-task-list-items-successfully"));
|
|
memoUpdatedCallback();
|
|
}, [memo.name, memo.content, t, memoUpdatedCallback, updateMemo]);
|
|
|
|
return {
|
|
handleTogglePinMemoBtnClick,
|
|
handleEditMemoClick,
|
|
handleToggleMemoStatusClick,
|
|
handleCopyLink,
|
|
handleCopyContent,
|
|
handleDeleteMemoClick,
|
|
confirmDeleteMemo,
|
|
handleRemoveCompletedTaskListItemsClick,
|
|
confirmRemoveCompletedTaskListItems,
|
|
};
|
|
};
|