mirror of
https://github.com/usememos/memos.git
synced 2024-09-21 14:55:59 +08:00
chore: add memo resources component
This commit is contained in:
parent
fbce43870f
commit
5fa9aa3c22
|
@ -1,16 +1,16 @@
|
|||
import { memo, useEffect, useRef, useState } from "react";
|
||||
import { indexOf } from "lodash-es";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { indexOf } from "lodash-es";
|
||||
import { memo, useEffect, useRef, useState } from "react";
|
||||
import "dayjs/locale/zh";
|
||||
import useI18n from "../hooks/useI18n";
|
||||
import { UNKNOWN_ID } from "../helpers/consts";
|
||||
import { DONE_BLOCK_REG, formatMemoContent, IMAGE_URL_REG, TODO_BLOCK_REG } from "../helpers/marked";
|
||||
import { DONE_BLOCK_REG, formatMemoContent, TODO_BLOCK_REG } from "../helpers/marked";
|
||||
import { editorStateService, locationService, memoService, userService } from "../services";
|
||||
import Icon from "./Icon";
|
||||
import Only from "./common/OnlyWhen";
|
||||
import toastHelper from "./Toast";
|
||||
import Image from "./Image";
|
||||
import MemoResources from "./MemoResources";
|
||||
import showMemoCardDialog from "./MemoCardDialog";
|
||||
import showShareMemoImageDialog from "./ShareMemoImageDialog";
|
||||
import "../less/memo.less";
|
||||
|
@ -46,7 +46,6 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||
const [createdAtStr, setCreatedAtStr] = useState<string>(getFormatedMemoCreatedAtStr(memo.createdTs, locale));
|
||||
const memoContainerRef = useRef<HTMLDivElement>(null);
|
||||
const memoContentContainerRef = useRef<HTMLDivElement>(null);
|
||||
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
||||
const isVisitorMode = userService.isVisitorMode();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -239,13 +238,7 @@ const Memo: React.FC<Props> = (props: Props) => {
|
|||
</span>
|
||||
</div>
|
||||
)}
|
||||
<Only when={imageUrls.length > 0}>
|
||||
<div className="images-wrapper">
|
||||
{imageUrls.map((imgUrl, idx) => (
|
||||
<Image className="memo-img" key={idx} imgUrl={imgUrl} />
|
||||
))}
|
||||
</div>
|
||||
</Only>
|
||||
<MemoResources memo={memo} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,13 +3,13 @@ import { editorStateService, memoService, userService } from "../services";
|
|||
import { useAppSelector } from "../store";
|
||||
import { UNKNOWN_ID, VISIBILITY_SELECTOR_ITEMS } from "../helpers/consts";
|
||||
import * as utils from "../helpers/utils";
|
||||
import { formatMemoContent, IMAGE_URL_REG, MEMO_LINK_REG, parseHtmlToRawText } from "../helpers/marked";
|
||||
import { formatMemoContent, MEMO_LINK_REG, parseHtmlToRawText } from "../helpers/marked";
|
||||
import Only from "./common/OnlyWhen";
|
||||
import toastHelper from "./Toast";
|
||||
import { generateDialog } from "./Dialog";
|
||||
import Image from "./Image";
|
||||
import Icon from "./Icon";
|
||||
import Selector from "./common/Selector";
|
||||
import MemoResources from "./MemoResources";
|
||||
import showChangeMemoCreatedTsDialog from "./ChangeMemoCreatedTsDialog";
|
||||
import "../less/memo-card-dialog.less";
|
||||
|
||||
|
@ -29,7 +29,6 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
|
|||
});
|
||||
const [linkMemos, setLinkMemos] = useState<LinkedMemo[]>([]);
|
||||
const [linkedMemos, setLinkedMemos] = useState<LinkedMemo[]>([]);
|
||||
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLinkedMemos = async () => {
|
||||
|
@ -167,13 +166,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
|
|||
onClick={handleMemoContentClick}
|
||||
dangerouslySetInnerHTML={{ __html: formatMemoContent(memo.content) }}
|
||||
></div>
|
||||
<Only when={imageUrls.length > 0}>
|
||||
<div className="images-wrapper">
|
||||
{imageUrls.map((imgUrl, idx) => (
|
||||
<Image className="memo-img" key={idx} imgUrl={imgUrl} />
|
||||
))}
|
||||
</div>
|
||||
</Only>
|
||||
<MemoResources memo={memo} />
|
||||
</div>
|
||||
<div className="layer-container"></div>
|
||||
{linkMemos.map((_, idx) => {
|
||||
|
|
28
web/src/components/MemoResources.tsx
Normal file
28
web/src/components/MemoResources.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { IMAGE_URL_REG } from "../helpers/marked";
|
||||
import Only from "./common/OnlyWhen";
|
||||
import Image from "./Image";
|
||||
import "../less/memo-resources.less";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
memo: Memo;
|
||||
}
|
||||
|
||||
const MemoResources: React.FC<Props> = (props: Props) => {
|
||||
const { className, memo } = props;
|
||||
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
||||
|
||||
return (
|
||||
<div className="resource-wrapper">
|
||||
<Only when={imageUrls.length > 0}>
|
||||
<div className={`images-wrapper ${className ?? ""}`}>
|
||||
{imageUrls.map((imgUrl, idx) => (
|
||||
<Image className="memo-img" key={idx} imgUrl={imgUrl} />
|
||||
))}
|
||||
</div>
|
||||
</Only>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MemoResources;
|
|
@ -35,12 +35,12 @@ const Sidebar = () => {
|
|||
<span className="icon">📅</span> {t("sidebar.daily-review")}
|
||||
</button>
|
||||
<Only when={!userService.isVisitorMode()}>
|
||||
<button className="btn action-btn" onClick={handleSettingBtnClick}>
|
||||
<span className="icon">⚙️</span> {t("sidebar.setting")}
|
||||
</button>
|
||||
<button className="btn action-btn" onClick={() => handleExploreBtnClick()}>
|
||||
<span className="icon">🏂</span> {t("common.explore")}
|
||||
</button>
|
||||
<button className="btn action-btn" onClick={handleSettingBtnClick}>
|
||||
<span className="icon">⚙️</span> {t("sidebar.setting")}
|
||||
</button>
|
||||
</Only>
|
||||
</div>
|
||||
<Only when={!userService.isVisitorMode()}>
|
||||
|
|
|
@ -61,23 +61,6 @@
|
|||
> .memo-content-text {
|
||||
@apply w-full text-base;
|
||||
}
|
||||
|
||||
> .images-wrapper {
|
||||
.flex(row, flex-start, flex-start);
|
||||
@apply w-full mt-2 overflow-x-auto overflow-y-hidden;
|
||||
padding-bottom: 2px;
|
||||
.pretty-scroll-bar(0, 2px);
|
||||
|
||||
> .memo-img {
|
||||
@apply mr-2 w-auto h-32 shrink-0 grow-0 overflow-y-hidden hover:border-gray-400 last:mr-0;
|
||||
.hide-scroll-bar();
|
||||
|
||||
> img {
|
||||
@apply w-auto rounded-lg;
|
||||
max-height: 128px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .normal-text {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
}
|
||||
|
||||
> .tag-list {
|
||||
@apply hidden flex-col justify-start items-start absolute top-6 left-0 mt-1 p-1 z-1 rounded w-32 max-h-52 overflow-auto bg-black;
|
||||
@apply hidden flex-col justify-start items-start absolute top-6 left-0 mt-1 p-1 z-1 rounded w-32 max-h-52 overflow-auto font-mono bg-black;
|
||||
|
||||
> .item-container {
|
||||
@apply w-full text-white cursor-pointer rounded text-sm leading-6 px-2 hover:bg-gray-700;
|
||||
|
|
19
web/src/less/memo-resources.less
Normal file
19
web/src/less/memo-resources.less
Normal file
|
@ -0,0 +1,19 @@
|
|||
@import "./mixin.less";
|
||||
|
||||
.resource-wrapper {
|
||||
@apply w-full flex flex-col justify-start items-start;
|
||||
|
||||
> .images-wrapper {
|
||||
@apply flex flex-row justify-start items-start mt-2 w-full overflow-x-auto overflow-y-hidden pb-1;
|
||||
.pretty-scroll-bar(0, 2px);
|
||||
|
||||
> .memo-img {
|
||||
@apply mr-2 last:mr-0 w-auto h-auto shrink-0 grow-0 overflow-y-hidden;
|
||||
.hide-scroll-bar();
|
||||
|
||||
> img {
|
||||
@apply w-auto max-h-40 rounded-lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -140,18 +140,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .images-wrapper {
|
||||
@apply flex flex-row justify-start items-start mt-2 w-full overflow-x-auto overflow-y-hidden pb-1;
|
||||
.pretty-scroll-bar(0, 2px);
|
||||
|
||||
> .memo-img {
|
||||
@apply mr-2 last:mr-0 w-auto h-auto shrink-0 grow-0 overflow-y-hidden;
|
||||
.hide-scroll-bar();
|
||||
|
||||
> img {
|
||||
@apply w-auto max-h-40 rounded-lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { useAppSelector } from "../store";
|
|||
import useI18n from "../hooks/useI18n";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import MemoContent from "../components/MemoContent";
|
||||
import MemoResources from "../components/MemoResources";
|
||||
import "../less/explore.less";
|
||||
|
||||
interface State {
|
||||
|
@ -72,6 +73,7 @@ const Explore = () => {
|
|||
</a>
|
||||
</div>
|
||||
<MemoContent className="memo-content" content={memo.content} onMemoContentClick={() => undefined} />
|
||||
<MemoResources memo={memo} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
Loading…
Reference in a new issue