mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
@ -1,5 +1,4 @@
|
||||
import { Divider } from "@mui/joy";
|
||||
import { isEqual, uniqWith } from "lodash-es";
|
||||
import { memo, useEffect, useRef, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -7,7 +6,7 @@ import { Link } from "react-router-dom";
|
||||
import { UNKNOWN_ID } from "@/helpers/consts";
|
||||
import { getRelativeTimeString } from "@/helpers/datetime";
|
||||
import { useFilterStore, useMemoStore, useUserStore } from "@/store/module";
|
||||
import { useMemoCacheStore, useUserV1Store } from "@/store/v1";
|
||||
import { useUserV1Store } from "@/store/v1";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
|
||||
import { showCommonDialog } from "./Dialog/CommonDialog";
|
||||
@ -23,24 +22,20 @@ import "@/less/memo.less";
|
||||
|
||||
interface Props {
|
||||
memo: Memo;
|
||||
showCreator?: boolean;
|
||||
showVisibility?: boolean;
|
||||
showRelatedMemos?: boolean;
|
||||
lazyRendering?: boolean;
|
||||
}
|
||||
|
||||
const Memo: React.FC<Props> = (props: Props) => {
|
||||
const { memo, showCreator, showRelatedMemos, lazyRendering } = props;
|
||||
const { memo, lazyRendering } = props;
|
||||
const { i18n } = useTranslation();
|
||||
const t = useTranslate();
|
||||
const filterStore = useFilterStore();
|
||||
const userStore = useUserStore();
|
||||
const memoStore = useMemoStore();
|
||||
const memoCacheStore = useMemoCacheStore();
|
||||
const userV1Store = useUserV1Store();
|
||||
const [shouldRender, setShouldRender] = useState<boolean>(lazyRendering ? false : true);
|
||||
const [createdTimeStr, setCreatedTimeStr] = useState<string>(getRelativeTimeString(memo.displayTs));
|
||||
const [relatedMemoList, setRelatedMemoList] = useState<Memo[]>([]);
|
||||
const [displayTime, setDisplayTime] = useState<string>(getRelativeTimeString(memo.displayTs));
|
||||
const memoContainerRef = useRef<HTMLDivElement>(null);
|
||||
const readonly = userStore.isVisitorMode() || userStore.getCurrentUsername() !== memo.creatorUsername;
|
||||
const creator = userV1Store.getUserByUsername(memo.creatorUsername);
|
||||
@ -50,27 +45,12 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||
userV1Store.getOrFetchUserByUsername(memo.creatorUsername);
|
||||
}, [memo.creatorUsername]);
|
||||
|
||||
// Prepare related memos.
|
||||
useEffect(() => {
|
||||
Promise.allSettled(memo.relationList.map((memoRelation) => memoCacheStore.getOrFetchMemoById(memoRelation.relatedMemoId))).then(
|
||||
(results) => {
|
||||
const memoList = [];
|
||||
for (const result of results) {
|
||||
if (result.status === "fulfilled") {
|
||||
memoList.push(result.value);
|
||||
}
|
||||
}
|
||||
setRelatedMemoList(uniqWith(memoList, isEqual));
|
||||
}
|
||||
);
|
||||
}, [memo.relationList]);
|
||||
|
||||
// Update display time string.
|
||||
useEffect(() => {
|
||||
let intervalFlag: any = -1;
|
||||
if (Date.now() - memo.displayTs < 1000 * 60 * 60 * 24) {
|
||||
intervalFlag = setInterval(() => {
|
||||
setCreatedTimeStr(getRelativeTimeString(memo.displayTs));
|
||||
setDisplayTime(getRelativeTimeString(memo.displayTs));
|
||||
}, 1000 * 1);
|
||||
}
|
||||
|
||||
@ -246,26 +226,25 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||
<>
|
||||
<div className={`memo-wrapper ${"memos-" + memo.id} ${memo.pinned && !readonly ? "pinned" : ""}`} ref={memoContainerRef}>
|
||||
<div className="memo-top-wrapper">
|
||||
<div className="status-text-container">
|
||||
{showCreator && creator && (
|
||||
<p className="w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1">
|
||||
{creator && (
|
||||
<>
|
||||
<Link className="flex flex-row justify-start items-center" to={`/u/${memo.creatorUsername}`}>
|
||||
<UserAvatar className="!w-5 !h-auto mr-1" avatarUrl={creator.avatarUrl} />
|
||||
<span className="text-sm text-gray-600 dark:text-zinc-300">{creator.nickname}</span>
|
||||
<span className="text-sm text-gray-600 max-w-[8em] truncate dark:text-zinc-300">{creator.nickname}</span>
|
||||
</Link>
|
||||
<Icon.Dot className="w-4 h-auto text-gray-400 dark:text-zinc-400" />
|
||||
</>
|
||||
)}
|
||||
<Link className="time-text" to={`/m/${memo.id}`} onClick={handleMemoCreatedTimeClick}>
|
||||
{createdTimeStr}
|
||||
</Link>
|
||||
</div>
|
||||
<span className="text-sm text-gray-400" onClick={handleMemoCreatedTimeClick}>
|
||||
{displayTime}
|
||||
</span>
|
||||
</p>
|
||||
<div className="btns-container space-x-2">
|
||||
{memo.pinned && <Icon.Bookmark className="w-4 h-auto rounded text-green-600" />}
|
||||
{!readonly && (
|
||||
<>
|
||||
<span className="btn more-action-btn">
|
||||
<Icon.MoreHorizontal className="icon-img" />
|
||||
<Icon.MoreVertical className="icon-img" />
|
||||
</span>
|
||||
<div className="more-action-btns-wrapper">
|
||||
<div className="more-action-btns-container min-w-[6em]">
|
||||
@ -306,24 +285,8 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||
onMemoContentDoubleClick={handleMemoContentDoubleClick}
|
||||
/>
|
||||
<MemoResourceListView resourceList={memo.resourceList} />
|
||||
{!showRelatedMemos && <MemoRelationListView relationList={memo.relationList} />}
|
||||
<MemoRelationListView relationList={memo.relationList} />
|
||||
</div>
|
||||
|
||||
{showRelatedMemos && relatedMemoList.length > 0 && (
|
||||
<>
|
||||
<p className="text-sm dark:text-gray-300 my-2 pl-4 opacity-50 flex flex-row items-center">
|
||||
<Icon.Link className="w-4 h-auto mr-1" />
|
||||
<span>Related memos</span>
|
||||
</p>
|
||||
{relatedMemoList.map((relatedMemo) => {
|
||||
return (
|
||||
<div key={relatedMemo.id} className="w-full">
|
||||
<Memo memo={relatedMemo} showCreator />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user