mirror of
https://github.com/usememos/memos.git
synced 2024-12-21 18:21:43 +03:00
chore: expand/fold memo content button (#84)
* chore: toggle show all content button * chore: update expand text * chore: rename
This commit is contained in:
parent
ceef257348
commit
1999260f9d
@ -1,4 +1,4 @@
|
|||||||
import { memo } from "react";
|
import { memo, useEffect, useRef, useState } from "react";
|
||||||
import { escape } from "lodash-es";
|
import { escape } from "lodash-es";
|
||||||
import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG, UNKNOWN_ID } from "../helpers/consts";
|
import { IMAGE_URL_REG, LINK_REG, MEMO_LINK_REG, TAG_REG, UNKNOWN_ID } from "../helpers/consts";
|
||||||
import { parseMarkedToHtml, parseRawTextToHtml } from "../helpers/marked";
|
import { parseMarkedToHtml, parseRawTextToHtml } from "../helpers/marked";
|
||||||
@ -12,19 +12,44 @@ import showShareMemoImageDialog from "./ShareMemoImageDialog";
|
|||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
import "../less/memo.less";
|
import "../less/memo.less";
|
||||||
|
|
||||||
|
const MAX_MEMO_CONTAINER_HEIGHT = 384;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
memo: Memo;
|
memo: Memo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExpandButtonStatus = -1 | 0 | 1;
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
expandButtonStatus: ExpandButtonStatus;
|
||||||
|
}
|
||||||
|
|
||||||
const Memo: React.FC<Props> = (props: Props) => {
|
const Memo: React.FC<Props> = (props: Props) => {
|
||||||
const { memo: propsMemo } = props;
|
const { memo: propsMemo } = props;
|
||||||
const memo = {
|
const memo = {
|
||||||
...propsMemo,
|
...propsMemo,
|
||||||
createdAtStr: utils.getDateTimeString(propsMemo.createdTs),
|
createdAtStr: utils.getDateTimeString(propsMemo.createdTs),
|
||||||
};
|
};
|
||||||
|
const [state, setState] = useState<State>({
|
||||||
|
expandButtonStatus: -1,
|
||||||
|
});
|
||||||
|
const memoContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false);
|
const [showConfirmDeleteBtn, toggleConfirmDeleteBtn] = useToggle(false);
|
||||||
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!memoContainerRef) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Number(memoContainerRef.current?.clientHeight) > MAX_MEMO_CONTAINER_HEIGHT) {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
expandButtonStatus: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleShowMemoStoryDialog = () => {
|
const handleShowMemoStoryDialog = () => {
|
||||||
showMemoCardDialog(memo);
|
showMemoCardDialog(memo);
|
||||||
};
|
};
|
||||||
@ -96,6 +121,13 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleShowMoreBtnClick = () => {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
expandButtonStatus: Number(Boolean(!state.expandButtonStatus)) as ExpandButtonStatus,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`} onMouseLeave={handleMouseLeaveMemoWrapper}>
|
<div className={`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`} onMouseLeave={handleMouseLeaveMemoWrapper}>
|
||||||
<div className="memo-top-wrapper">
|
<div className="memo-top-wrapper">
|
||||||
@ -139,10 +171,19 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="memo-content-text"
|
ref={memoContainerRef}
|
||||||
|
className={`memo-content-text ${state.expandButtonStatus === 0 ? "!max-h-96 overflow-y-hidden truncate" : ""}`}
|
||||||
onClick={handleMemoContentClick}
|
onClick={handleMemoContentClick}
|
||||||
dangerouslySetInnerHTML={{ __html: formatMemoContent(memo.content) }}
|
dangerouslySetInnerHTML={{ __html: formatMemoContent(memo.content) }}
|
||||||
></div>
|
></div>
|
||||||
|
{state.expandButtonStatus !== -1 && (
|
||||||
|
<div className="expand-btn-container">
|
||||||
|
<span className={`btn ${state.expandButtonStatus === 0 ? "expand-btn" : "fold-btn"}`} onClick={handleShowMoreBtnClick}>
|
||||||
|
{state.expandButtonStatus === 0 ? "Expand" : "Fold"}
|
||||||
|
<img className="icon-img" src="/icons/arrow-right.svg" alt="" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<Only when={imageUrls.length > 0}>
|
<Only when={imageUrls.length > 0}>
|
||||||
<div className="images-wrapper">
|
<div className="images-wrapper">
|
||||||
{imageUrls.map((imgUrl, idx) => (
|
{imageUrls.map((imgUrl, idx) => (
|
||||||
|
@ -28,8 +28,9 @@ const MemoTrashDialog: React.FC<Props> = (props: Props) => {
|
|||||||
locationService.clearQuery();
|
locationService.clearQuery();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDeletedMemoAction = useCallback((memoId: MemoId) => {
|
const handleDeletedMemoAction = useCallback(async (memoId: MemoId) => {
|
||||||
setDeletedMemos((deletedMemos) => deletedMemos.filter((memo) => memo.id !== memoId));
|
setDeletedMemos((deletedMemos) => deletedMemos.filter((memo) => memo.id !== memoId));
|
||||||
|
await memoService.fetchAllMemos();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -86,7 +86,33 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
> .memo-content-text {
|
> .memo-content-text {
|
||||||
@apply w-full h-auto;
|
@apply w-full h-auto transition-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .expand-btn-container {
|
||||||
|
@apply w-full relative flex flex-row justify-start items-center;
|
||||||
|
|
||||||
|
> .btn {
|
||||||
|
@apply flex flex-row justify-start items-center px-2 py-1 my-1 text-xs rounded-lg border bg-gray-100 border-gray-200 opacity-80 shadow hover:opacity-60;
|
||||||
|
|
||||||
|
&.expand-btn {
|
||||||
|
@apply mt-2;
|
||||||
|
|
||||||
|
> .icon-img {
|
||||||
|
@apply rotate-90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fold-btn {
|
||||||
|
> .icon-img {
|
||||||
|
@apply -rotate-90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon-img {
|
||||||
|
@apply w-4 h-auto transition-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .images-wrapper {
|
> .images-wrapper {
|
||||||
|
Loading…
Reference in New Issue
Block a user