memos/web/src/components/MemoView/MemoViewContext.tsx
memoclaw ac077ac3d3
refactor(web): improve MemoView and MemoEditor maintainability (#5754)
Co-authored-by: memoclaw <265580040+memoclaw@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-21 07:20:18 +08:00

54 lines
1.9 KiB
TypeScript

import { timestampDate } from "@bufbuild/protobuf/wkt";
import { createContext, useContext } from "react";
import { useLocation } from "react-router-dom";
import type { Memo } from "@/types/proto/api/v1/memo_service_pb";
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb";
import type { User } from "@/types/proto/api/v1/user_service_pb";
import { RELATIVE_TIME_THRESHOLD_MS } from "./constants";
export interface MemoViewContextValue {
memo: Memo;
creator: User | undefined;
currentUser: User | undefined;
parentPage: string;
isArchived: boolean;
readonly: boolean;
showNSFWContent: boolean;
nsfw: boolean;
openEditor: () => void;
toggleNsfwVisibility: () => void;
openPreview: (urls: string | string[], index?: number) => void;
}
export const MemoViewContext = createContext<MemoViewContextValue | null>(null);
export const useMemoViewContext = (): MemoViewContextValue => {
const context = useContext(MemoViewContext);
if (!context) {
throw new Error("useMemoViewContext must be used within MemoViewContext.Provider");
}
return context;
};
export const computeCommentAmount = (memo: Memo): number =>
memo.relations.filter((r) => r.type === MemoRelation_Type.COMMENT && r.relatedMemo?.name === memo.name).length;
export const useMemoViewDerived = () => {
const { memo, isArchived, readonly } = useMemoViewContext();
const location = useLocation();
const isInMemoDetailPage = location.pathname.startsWith(`/${memo.name}`);
const commentAmount = computeCommentAmount(memo);
const displayTime = memo.displayTime ? timestampDate(memo.displayTime) : undefined;
const relativeTimeFormat: "datetime" | "auto" =
displayTime && Date.now() - displayTime.getTime() > RELATIVE_TIME_THRESHOLD_MS ? "datetime" : "auto";
return {
isArchived,
readonly,
isInMemoDetailPage,
commentAmount,
relativeTimeFormat,
};
};