From 22f4020ccd5e5be02233993db28ac6ec1bba7091 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 1 Jul 2023 18:04:00 +0800 Subject: [PATCH] fix: comment box Signed-off-by: Innei --- src/components/layout/footer/FooterInfo.tsx | 5 +++ src/components/layout/footer/GatewayCount.tsx | 1 + src/components/ui/dlalog/DialogOverlay.tsx | 5 ++- src/components/ui/form/FormInput.tsx | 8 ++-- src/components/ui/input/Input.tsx | 17 +++++--- .../CommentBox/CommentBoxLegacyForm.tsx | 1 + .../widgets/subscribe/SubscribeModal.tsx | 14 ++++--- .../widgets/subscribe/SubscribeTextButton.tsx | 23 +++++++++++ src/components/widgets/subscribe/hooks.tsx | 9 +++-- src/lib/dom.ts | 6 +++ src/providers/root/modal-stack-provider.tsx | 40 ++++++++++++++++--- 11 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 src/components/widgets/subscribe/SubscribeTextButton.tsx create mode 100644 src/lib/dom.ts diff --git a/src/components/layout/footer/FooterInfo.tsx b/src/components/layout/footer/FooterInfo.tsx index d06741a23b..26a243396e 100644 --- a/src/components/layout/footer/FooterInfo.tsx +++ b/src/components/layout/footer/FooterInfo.tsx @@ -1,5 +1,6 @@ import Link from 'next/link' +import { SubscribeTextButton } from '~/components/widgets/subscribe/SubscribeTextButton' import { kvKeys, redis } from '~/lib/redis.server' import { isDev } from '~/utils/env' import { clsxm } from '~/utils/helper' @@ -121,6 +122,10 @@ const FooterBottom = async () => { 站点地图 + + + + Stay hungry. Stay foolish. diff --git a/src/components/layout/footer/GatewayCount.tsx b/src/components/layout/footer/GatewayCount.tsx index ea34e5649b..9f08213a4e 100644 --- a/src/components/layout/footer/GatewayCount.tsx +++ b/src/components/layout/footer/GatewayCount.tsx @@ -9,6 +9,7 @@ export const GatewayCount = () => { as="span" TriggerComponent={GatewayCountTrigger} type="tooltip" + wrapperClassName="cursor-help" >

diff --git a/src/components/ui/dlalog/DialogOverlay.tsx b/src/components/ui/dlalog/DialogOverlay.tsx index 3a9fa01cf3..3a5c598ac8 100644 --- a/src/components/ui/dlalog/DialogOverlay.tsx +++ b/src/components/ui/dlalog/DialogOverlay.tsx @@ -1,11 +1,12 @@ import * as Dialog from '@radix-ui/react-dialog' import { m } from 'framer-motion' -export const DialogOverlay = () => { +export const DialogOverlay = ({ onClick }: { onClick?: () => void }) => { return ( - , HTMLInputElement> -> = ({ className, ...props }) => { +export const Input = forwardRef< + HTMLInputElement, + Omit< + DetailedHTMLProps, HTMLInputElement>, + 'ref' + > +>(({ className, ...props }, ref) => { return ( ) -} +}) +Input.displayName = 'Input' diff --git a/src/components/widgets/comment/CommentBox/CommentBoxLegacyForm.tsx b/src/components/widgets/comment/CommentBox/CommentBoxLegacyForm.tsx index 02ac313955..f73b11acbf 100644 --- a/src/components/widgets/comment/CommentBox/CommentBoxLegacyForm.tsx +++ b/src/components/widgets/comment/CommentBox/CommentBoxLegacyForm.tsx @@ -35,6 +35,7 @@ const FormInput = (props: { fieldKey: FormKey; required?: boolean }) => { onChange={(e) => setValue(e.target.value)} required={required} placeholder={placeholderMap[key] + (required ? ' *' : '')} + className="border-0 bg-gray-200/50 dark:bg-zinc-800/50" /> ) } diff --git a/src/components/widgets/subscribe/SubscribeModal.tsx b/src/components/widgets/subscribe/SubscribeModal.tsx index 74e18db998..bb20cae33a 100644 --- a/src/components/widgets/subscribe/SubscribeModal.tsx +++ b/src/components/widgets/subscribe/SubscribeModal.tsx @@ -1,10 +1,11 @@ -import { useEffect, useReducer } from 'react' +import React, { useEffect, useReducer } from 'react' import type { SubscribeTypeToBitMap } from '@mx-space/api-client' import type { FC } from 'react' import { StyledButton } from '~/components/ui/button' import { Input } from '~/components/ui/input/Input' import { useStateToRef } from '~/hooks/common/use-state-ref' +import { preventDefault } from '~/lib/dom' import { toast } from '~/lib/toast' import { useAggregationSelector } from '~/providers/root/aggregation-data-provider' import { apiClient } from '~/utils/request' @@ -82,7 +83,8 @@ export const SubscribeModal: FC = ({ const query = useSubscribeStatusQuery() - const handleSubList = async () => { + const handleSubList: React.EventHandler = async (e) => { + preventDefault(e) const { email, types } = state await apiClient.subscribe.subscribe( email, @@ -97,7 +99,7 @@ export const SubscribeModal: FC = ({ const title = useAggregationSelector((data) => data.seo.title) return ( -

+

欢迎订阅「{title} 」,我会定期推送最新的内容到你的邮箱。 @@ -111,16 +113,16 @@ export const SubscribeModal: FC = ({ dispatch({ type: 'set', data: { email: e.target.value } }) }} /> -

+
{Object.keys(state.types) .filter((type) => query.data?.allowTypes.includes(type as any)) .map((name) => (
{ dispatch({ diff --git a/src/components/widgets/subscribe/SubscribeTextButton.tsx b/src/components/widgets/subscribe/SubscribeTextButton.tsx new file mode 100644 index 0000000000..b9c903a292 --- /dev/null +++ b/src/components/widgets/subscribe/SubscribeTextButton.tsx @@ -0,0 +1,23 @@ +'use client' + +import type { FC, PropsWithChildren } from 'react' + +import { useIsEnableSubscribe, usePresentSubscribeModal } from './hooks' + +export const SubscribeTextButton: FC = ({ children }) => { + const canSubscribe = useIsEnableSubscribe() + const { present } = usePresentSubscribeModal() + + if (!canSubscribe) { + return null + } + + return ( + <> + + + + {children} + + ) +} diff --git a/src/components/widgets/subscribe/hooks.tsx b/src/components/widgets/subscribe/hooks.tsx index 05c407a068..015bff5b47 100644 --- a/src/components/widgets/subscribe/hooks.tsx +++ b/src/components/widgets/subscribe/hooks.tsx @@ -6,21 +6,24 @@ import { apiClient } from '~/utils/request' import { SubscribeModal } from './SubscribeModal' -const SWR_CHECK_SUBSCRIBE_KEY = ['subscribe-status'] +const QUERY_CHECK_SUBSCRIBE_KEY = ['subscribe-status'] export const useSubscribeStatusQuery = () => { - return useQuery(SWR_CHECK_SUBSCRIBE_KEY, apiClient.subscribe.check, { + return useQuery(QUERY_CHECK_SUBSCRIBE_KEY, apiClient.subscribe.check, { cacheTime: 60_000 * 10, }) } export const useIsEnableSubscribe = () => useQuery({ - queryKey: SWR_CHECK_SUBSCRIBE_KEY, + queryKey: QUERY_CHECK_SUBSCRIBE_KEY, queryFn: apiClient.subscribe.check, select: (data: { enable: boolean }) => data?.enable, cacheTime: 60_000 * 10, staleTime: 60_000 * 10, + meta: { + persist: false, + }, }) export const usePresentSubscribeModal = ( diff --git a/src/lib/dom.ts b/src/lib/dom.ts new file mode 100644 index 0000000000..458919b7e2 --- /dev/null +++ b/src/lib/dom.ts @@ -0,0 +1,6 @@ +import type { ReactEventHandler } from 'react' + +export const stopPropagation: ReactEventHandler = (e) => + e.stopPropagation() + +export const preventDefault: ReactEventHandler = (e) => e.preventDefault() diff --git a/src/providers/root/modal-stack-provider.tsx b/src/providers/root/modal-stack-provider.tsx index 870817e7d2..91fa4a16fa 100644 --- a/src/providers/root/modal-stack-provider.tsx +++ b/src/providers/root/modal-stack-provider.tsx @@ -1,6 +1,14 @@ import * as Dialog from '@radix-ui/react-dialog' -import { createElement, memo, useCallback, useId, useMemo, useRef } from 'react' -import { AnimatePresence, m } from 'framer-motion' +import { + createElement, + memo, + useCallback, + useEffect, + useId, + useMemo, + useRef, +} from 'react' +import { AnimatePresence, m, useAnimationControls } from 'framer-motion' import { atom, useAtomValue, useSetAtom } from 'jotai' import type { Target, Transition } from 'framer-motion' import type { FC, PropsWithChildren } from 'react' @@ -10,6 +18,7 @@ import { Divider } from '~/components/ui/divider' import { DialogOverlay } from '~/components/ui/dlalog/DialogOverlay' import { microReboundPreset } from '~/constants/spring' import { useIsClient } from '~/hooks/common/use-is-client' +import { stopPropagation } from '~/lib/dom' import { jotaiStore } from '~/lib/store' import { clsxm } from '~/utils/helper' @@ -118,26 +127,47 @@ export const Modal: Component<{ }, [close], ) + const animateController = useAnimationControls() + useEffect(() => { + animateController.start(enterStyle) + }, []) return ( -
+
{ + animateController + .start({ + scale: 1.05, + transition: { + duration: 0.06, + }, + }) + .then(() => { + animateController.start({ + scale: 1, + }) + }) + }} + > ({ zIndex: 99 + index }), [index])} exit={initialStyle} initial={initialStyle} - animate={enterStyle} + animate={animateController} transition={modalTransition} className={clsxm( 'relative flex flex-col overflow-hidden rounded-lg', - 'bg-slate-50/90 dark:bg-neutral-900/90', + 'bg-slate-50/10 dark:bg-neutral-900/80', 'p-2 shadow-2xl shadow-stone-300 backdrop-blur-sm dark:shadow-stone-800', 'max-h-[70vh] min-w-[300px] max-w-[90vw] lg:max-h-[calc(100vh-20rem)] lg:max-w-[50vw]', 'border border-slate-200 dark:border-neutral-800', item.modalClassName, )} + onClick={stopPropagation} > {item.title}