Commit 29412f46 authored by Steven's avatar Steven

refactor: simplify NSFW implementation by inlining logic

- Remove unused showNsfwContent prop (was only used in MemoDetail to pre-reveal NSFW, which defeats the purpose)
- Inline useNsfwContent hook logic directly into MemoView.tsx (only 3 lines, no reusability benefit)
- Delete web/src/components/MemoView/hooks/useNsfwContent.ts
- NSFW content now consistently starts hidden across all pages
- Maintains same user experience: click to reveal, no toggle back

This removes unnecessary indirection and prop threading while preserving functionality.
parent 6db58fae
...@@ -8,7 +8,7 @@ import MemoEditor from "../MemoEditor"; ...@@ -8,7 +8,7 @@ import MemoEditor from "../MemoEditor";
import PreviewImageDialog from "../PreviewImageDialog"; import PreviewImageDialog from "../PreviewImageDialog";
import { MemoBody, MemoHeader } from "./components"; import { MemoBody, MemoHeader } from "./components";
import { MEMO_CARD_BASE_CLASSES } from "./constants"; import { MEMO_CARD_BASE_CLASSES } from "./constants";
import { useImagePreview, useMemoActions, useMemoHandlers, useNsfwContent } from "./hooks"; import { useImagePreview, useMemoActions, useMemoHandlers } from "./hooks";
import { MemoViewContext } from "./MemoViewContext"; import { MemoViewContext } from "./MemoViewContext";
import type { MemoViewProps } from "./types"; import type { MemoViewProps } from "./types";
...@@ -23,7 +23,11 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => { ...@@ -23,7 +23,11 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => {
const readonly = memoData.creator !== currentUser?.name && !isSuperUser(currentUser); const readonly = memoData.creator !== currentUser?.name && !isSuperUser(currentUser);
const parentPage = parentPageProp || "/"; const parentPage = parentPageProp || "/";
const { nsfw, showNSFWContent, toggleNsfwVisibility } = useNsfwContent(memoData, props.showNsfwContent); // NSFW content management: always blur content tagged with NSFW (case-insensitive)
const [showNSFWContent, setShowNSFWContent] = useState(false);
const nsfw = memoData.tags?.some((tag) => tag.toUpperCase() === "NSFW") ?? false;
const toggleNsfwVisibility = () => setShowNSFWContent((prev) => !prev);
const { previewState, openPreview, setPreviewOpen } = useImagePreview(); const { previewState, openPreview, setPreviewOpen } = useImagePreview();
const { unpinMemo } = useMemoActions(memoData, isArchived); const { unpinMemo } = useMemoActions(memoData, isArchived);
...@@ -76,7 +80,6 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => { ...@@ -76,7 +80,6 @@ const MemoView: React.FC<MemoViewProps> = (props: MemoViewProps) => {
onEdit={openEditor} onEdit={openEditor}
onGotoDetail={handleGotoMemoDetailPage} onGotoDetail={handleGotoMemoDetailPage}
onUnpin={unpinMemo} onUnpin={unpinMemo}
onToggleNsfwVisibility={toggleNsfwVisibility}
/> />
<MemoBody <MemoBody
......
import { timestampDate } from "@bufbuild/protobuf/wkt"; import { timestampDate } from "@bufbuild/protobuf/wkt";
import { BookmarkIcon, EyeOffIcon, MessageCircleMoreIcon } from "lucide-react"; import { BookmarkIcon, MessageCircleMoreIcon } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
...@@ -16,19 +16,11 @@ import VisibilityIcon from "../../VisibilityIcon"; ...@@ -16,19 +16,11 @@ import VisibilityIcon from "../../VisibilityIcon";
import { useMemoViewContext, useMemoViewDerived } from "../MemoViewContext"; import { useMemoViewContext, useMemoViewDerived } from "../MemoViewContext";
import type { MemoHeaderProps } from "../types"; import type { MemoHeaderProps } from "../types";
const MemoHeader: React.FC<MemoHeaderProps> = ({ const MemoHeader: React.FC<MemoHeaderProps> = ({ showCreator, showVisibility, showPinned, onEdit, onGotoDetail, onUnpin }) => {
showCreator,
showVisibility,
showPinned,
onEdit,
onGotoDetail,
onUnpin,
onToggleNsfwVisibility,
}) => {
const t = useTranslate(); const t = useTranslate();
const [reactionSelectorOpen, setReactionSelectorOpen] = useState(false); const [reactionSelectorOpen, setReactionSelectorOpen] = useState(false);
const { memo, creator, currentUser, parentPage, isArchived, readonly, showNSFWContent, nsfw } = useMemoViewContext(); const { memo, creator, currentUser, parentPage, isArchived, readonly } = useMemoViewContext();
const { isInMemoDetailPage, commentAmount, relativeTimeFormat } = useMemoViewDerived(); const { isInMemoDetailPage, commentAmount, relativeTimeFormat } = useMemoViewDerived();
const displayTime = isArchived ? ( const displayTime = isArchived ? (
...@@ -100,12 +92,6 @@ const MemoHeader: React.FC<MemoHeaderProps> = ({ ...@@ -100,12 +92,6 @@ const MemoHeader: React.FC<MemoHeaderProps> = ({
</TooltipProvider> </TooltipProvider>
)} )}
{nsfw && showNSFWContent && onToggleNsfwVisibility && (
<span className="cursor-pointer">
<EyeOffIcon className="w-4 h-auto text-primary" onClick={onToggleNsfwVisibility} />
</span>
)}
<MemoActionMenu memo={memo} readonly={readonly} onEdit={onEdit} /> <MemoActionMenu memo={memo} readonly={readonly} onEdit={onEdit} />
</div> </div>
</div> </div>
......
export { useImagePreview } from "./useImagePreview"; export { useImagePreview } from "./useImagePreview";
export { useMemoActions } from "./useMemoActions"; export { useMemoActions } from "./useMemoActions";
export { useMemoHandlers } from "./useMemoHandlers"; export { useMemoHandlers } from "./useMemoHandlers";
export { useNsfwContent } from "./useNsfwContent";
import { useState } from "react";
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
export interface UseNsfwContentReturn {
nsfw: boolean;
showNSFWContent: boolean;
toggleNsfwVisibility: () => void;
}
export const useNsfwContent = (memo: Memo, initialShowNsfw?: boolean): UseNsfwContentReturn => {
const [showNSFWContent, setShowNSFWContent] = useState(initialShowNsfw ?? false);
// Always blur content tagged with NSFW
const nsfw = memo.tags?.includes("NSFW") ?? false;
return {
nsfw,
showNSFWContent,
toggleNsfwVisibility: () => setShowNSFWContent((prev) => !prev),
};
};
...@@ -6,7 +6,6 @@ export interface MemoViewProps { ...@@ -6,7 +6,6 @@ export interface MemoViewProps {
showCreator?: boolean; showCreator?: boolean;
showVisibility?: boolean; showVisibility?: boolean;
showPinned?: boolean; showPinned?: boolean;
showNsfwContent?: boolean;
className?: string; className?: string;
parentPage?: string; parentPage?: string;
} }
...@@ -18,7 +17,6 @@ export interface MemoHeaderProps { ...@@ -18,7 +17,6 @@ export interface MemoHeaderProps {
onEdit: () => void; onEdit: () => void;
onGotoDetail: () => void; onGotoDetail: () => void;
onUnpin: () => void; onUnpin: () => void;
onToggleNsfwVisibility?: () => void;
} }
export interface MemoBodyProps { export interface MemoBodyProps {
......
...@@ -93,7 +93,6 @@ const MemoDetail = () => { ...@@ -93,7 +93,6 @@ const MemoDetail = () => {
showCreator showCreator
showVisibility showVisibility
showPinned showPinned
showNsfwContent
/> />
<div className="pt-8 pb-16 w-full"> <div className="pt-8 pb-16 w-full">
<h2 id="comments" className="sr-only"> <h2 id="comments" className="sr-only">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment