From 5d5c437089139255bcbe74807ecb3ab7c6c409ab Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 6 Apr 2023 19:59:01 +0800 Subject: [PATCH] fix: component and state separated, fixed #240 --- src/components/dashboard/PagesManager.tsx | 306 ++++++++++++---------- src/hooks/useGetState.ts | 8 + 2 files changed, 178 insertions(+), 136 deletions(-) create mode 100644 src/hooks/useGetState.ts diff --git a/src/components/dashboard/PagesManager.tsx b/src/components/dashboard/PagesManager.tsx index baf94f3b..981e739b 100644 --- a/src/components/dashboard/PagesManager.tsx +++ b/src/components/dashboard/PagesManager.tsx @@ -1,4 +1,4 @@ -import { Fragment, useEffect, useMemo, useState } from "react" +import { FC, Fragment, useEffect, useMemo, useState } from "react" import { getPageVisibility } from "~/lib/page-helpers" import { useDate } from "~/hooks/useDate" import { TabItem, Tabs } from "../ui/Tabs" @@ -25,6 +25,7 @@ import { Tooltip } from "../ui/Tooltip" import { APP_NAME } from "~/lib/env" import { Trans, useTranslation } from "next-i18next" import { readFiles } from "~/lib/read-files" +import { useGetState } from "~/hooks/useGetState" export const PagesManager: React.FC<{ isPost: boolean @@ -40,38 +41,9 @@ export const PagesManager: React.FC<{ [router.query.visibility], ) - const deletePage = useDeletePage() - const createOrUpdatePage = useCreateOrUpdatePage() - const [convertToastId, setConvertToastId] = useState("") - const [deleteToastId, setDeleteToastId] = useState("") const { t } = useTranslation(["dashboard", "site"]) const date = useDate() - useEffect(() => { - if (deletePage.isSuccess) { - toast.success(t("Deleted!"), { - id: deleteToastId, - }) - } - }, [deletePage.isSuccess, deleteToastId, t]) - - useEffect(() => { - if (createOrUpdatePage.isSuccess) { - toast.success(t("Converted!"), { - id: convertToastId, - }) - } else if (createOrUpdatePage.isError) { - toast.error(t("Failed to convert."), { - id: convertToastId, - }) - } - }, [ - createOrUpdatePage.isSuccess, - createOrUpdatePage.isError, - convertToastId, - t, - ]) - const pages = useGetPagesBySite({ type: isPost ? "post" : "page", site: subdomain!, @@ -125,91 +97,6 @@ export const PagesManager: React.FC<{ } const queryClient = useQueryClient() - const getPageMenuItems = (page: Note) => { - const isCrossbell = !page.applications?.includes("xlog") - return [ - { - text: "Edit", - icon: , - onClick() { - router.push(getPageEditLink(page)) - }, - }, - { - text: - "Convert to " + - (isCrossbell - ? `${APP_NAME} ${isPost ? "Post" : "Page"}` - : isPost - ? "Page" - : "Post"), - icon: , - onClick() { - const toastId = toast.loading("Converting...") - if (isCrossbell) { - setConvertToastId(toastId) - createOrUpdatePage.mutate({ - published: true, - pageId: page.id, - siteId: subdomain, - tags: page.tags - ?.filter((tag) => tag !== "post" && tag !== "page") - ?.join(", "), - isPost: isPost, - applications: page.applications, - }) - } else { - if (!page.metadata) { - const data = getStorage(`draft-${subdomain}-${page.id}`) - data.isPost = !isPost - setStorage(`draft-${subdomain}-${page.id}`, data) - queryClient.invalidateQueries(["getPagesBySite", subdomain]) - queryClient.invalidateQueries(["getPage", page.id]) - toast.success("Converted!", { - id: toastId, - }) - } else { - setConvertToastId(toastId) - createOrUpdatePage.mutate({ - published: true, - pageId: page.id, - siteId: subdomain, - tags: page.tags - ?.filter((tag) => tag !== "post" && tag !== "page") - ?.join(", "), - isPost: !isPost, - applications: page.applications, - }) - } - } - }, - }, - { - text: "Delete", - icon: , - onClick() { - if (!page.metadata) { - const toastId = toast.loading("Deleting...") - delStorage(`draft-${subdomain}-${page.id}`) - Promise.all([ - queryClient.refetchQueries(["getPagesBySite", subdomain]), - queryClient.refetchQueries(["getPage", page.id]), - ]).then(() => { - toast.success("Deleted!", { - id: toastId, - }) - }) - } else { - setDeleteToastId(toast.loading("Deleting...")) - deletePage.mutate({ - site: subdomain, - id: page.id, - }) - } - }, - }, - ] - } const importFile = () => { const input = document.createElement("input") @@ -380,27 +267,8 @@ export const PagesManager: React.FC<{ - - {getPageMenuItems(page).map((item) => { - return ( - - - - ) - })} - + + )} @@ -435,3 +303,169 @@ export const PagesManager: React.FC<{ ) } + +const usePageEditLink = (page: { id: string }, isPost: boolean) => { + const router = useRouter() + const subdomain = router.query.subdomain as string + + return `/dashboard/${subdomain}/editor?id=${page.id}&type=${ + isPost ? "post" : "page" + }` +} + +const usePageMenuItems = ({ + page, + isPost, +}: { + page: Note + isPost: boolean +}) => { + const isCrossbell = !page.applications?.includes("xlog") + const router = useRouter() + const createOrUpdatePage = useCreateOrUpdatePage() + + const editLink = usePageEditLink(page, isPost) + const subdomain = router.query.subdomain as string + const queryClient = useQueryClient() + const deletePage = useDeletePage() + + const [convertToastId, setConvertToastId] = useState("") + const [deleteToastId, setDeleteToastId] = useState("") + + const getDeleteToastId = useGetState(deleteToastId) + const getCurrentToastId = useGetState(convertToastId) + const { t } = useTranslation(["dashboard", "site"]) + + useEffect(() => { + if (deletePage.isSuccess) { + toast.success(t("Deleted!"), { + id: getDeleteToastId(), + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [deletePage.isSuccess]) + + useEffect(() => { + if (createOrUpdatePage.isSuccess) { + toast.success(t("Converted!"), { + id: getCurrentToastId(), + }) + } else if (createOrUpdatePage.isError) { + toast.error(t("Failed to convert."), { + id: getCurrentToastId(), + }) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [createOrUpdatePage.isSuccess, createOrUpdatePage.isError]) + + return [ + { + text: "Edit", + icon: , + onClick() { + router.push(editLink) + }, + }, + { + text: + "Convert to " + + (isCrossbell + ? `${APP_NAME} ${isPost ? "Post" : "Page"}` + : isPost + ? "Page" + : "Post"), + icon: , + onClick() { + const toastId = toast.loading("Converting...") + if (isCrossbell) { + setConvertToastId(toastId) + createOrUpdatePage.mutate({ + published: true, + pageId: page.id, + siteId: subdomain, + tags: page.tags + ?.filter((tag) => tag !== "post" && tag !== "page") + ?.join(", "), + isPost: isPost, + applications: page.applications, + }) + } else { + if (!page.metadata) { + const data = getStorage(`draft-${subdomain}-${page.id}`) + data.isPost = !isPost + setStorage(`draft-${subdomain}-${page.id}`, data) + queryClient.invalidateQueries(["getPagesBySite", subdomain]) + queryClient.invalidateQueries(["getPage", page.id]) + toast.success("Converted!", { + id: toastId, + }) + } else { + setConvertToastId(toastId) + createOrUpdatePage.mutate({ + published: true, + pageId: page.id, + siteId: subdomain, + tags: page.tags + ?.filter((tag) => tag !== "post" && tag !== "page") + ?.join(", "), + isPost: !isPost, + applications: page.applications, + }) + } + } + }, + }, + { + text: "Delete", + icon: , + onClick() { + if (!page.metadata) { + const toastId = toast.loading("Deleting...") + delStorage(`draft-${subdomain}-${page.id}`) + Promise.all([ + queryClient.refetchQueries(["getPagesBySite", subdomain]), + queryClient.refetchQueries(["getPage", page.id]), + ]).then(() => { + toast.success("Deleted!", { + id: toastId, + }) + }) + } else { + setDeleteToastId(toast.loading("Deleting...")) + deletePage.mutate({ + site: subdomain, + id: page.id, + }) + } + }, + }, + ] +} + +const MenuItems: FC<{ + isPost: boolean + page: Note +}> = ({ isPost, page }) => { + const { t } = useTranslation(["dashboard", "site"]) + return ( + + {usePageMenuItems({ page, isPost }).map((item) => { + return ( + + + + ) + })} + + ) +} diff --git a/src/hooks/useGetState.ts b/src/hooks/useGetState.ts new file mode 100644 index 00000000..c9bd43a0 --- /dev/null +++ b/src/hooks/useGetState.ts @@ -0,0 +1,8 @@ +import { useEffect, useRef } from "react" + +export const useGetState = (state: any) => { + const ref = useRef(state) + + useEffect(() => void (ref.current = state), [state]) + return () => ref.current +}