From a3632571ffb11a4cbbd79b70157334c6cd10b784 Mon Sep 17 00:00:00 2001 From: reya Date: Sun, 12 Nov 2023 08:41:47 +0700 Subject: [PATCH] polish --- package.json | 1 - pnpm-lock.yaml | 13 ------ src/app/notes/article.tsx | 4 +- src/app/notes/text.tsx | 19 ++------ src/shared/notes/file.tsx | 2 +- src/shared/notes/preview/image.tsx | 71 ++++++++++++++++++------------ src/shared/notes/text.tsx | 2 +- src/shared/widgets/thread.tsx | 20 ++++++++- src/utils/hooks/useNostr.ts | 40 ++++++++++++----- 9 files changed, 99 insertions(+), 73 deletions(-) diff --git a/package.json b/package.json index a4cce2e9..0750a3e6 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.48.2", "react-hotkeys-hook": "^4.4.1", - "react-medium-image-zoom": "^5.1.8", "react-router-dom": "^6.18.0", "react-string-replace": "^1.1.1", "reactflow": "^11.10.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93a14fe5..88e86861 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -191,9 +191,6 @@ dependencies: react-hotkeys-hook: specifier: ^4.4.1 version: 4.4.1(react-dom@18.2.0)(react@18.2.0) - react-medium-image-zoom: - specifier: ^5.1.8 - version: 5.1.8(react-dom@18.2.0)(react@18.2.0) react-router-dom: specifier: ^6.18.0 version: 6.18.0(react-dom@18.2.0)(react@18.2.0) @@ -5405,16 +5402,6 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: true - /react-medium-image-zoom@5.1.8(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-2X4oLlEopIWg7qalR1Qpy4gPrU9CTF0DvJ7HNu5u/NwdyQWupEsje2vuMbjBz7+np8MmQ4DKJ6zGr1ofCuzB3g==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /react-remove-scroll-bar@2.3.4(@types/react@18.2.37)(react@18.2.0): resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} engines: {node: '>=10'} diff --git a/src/app/notes/article.tsx b/src/app/notes/article.tsx index dada6bb9..1df8bedf 100644 --- a/src/app/notes/article.tsx +++ b/src/app/notes/article.tsx @@ -87,9 +87,9 @@ export function ArticleNoteScreen() { )}
- +
- +
diff --git a/src/app/notes/text.tsx b/src/app/notes/text.tsx index 8d832a96..85695b6e 100644 --- a/src/app/notes/text.tsx +++ b/src/app/notes/text.tsx @@ -6,14 +6,7 @@ import { useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { ArrowLeftIcon, CheckCircleIcon, ReplyIcon, ShareIcon } from '@shared/icons'; -import { - ArticleNote, - FileNote, - NoteActions, - NoteReplyForm, - TextNote, - UnknownNote, -} from '@shared/notes'; +import { MemoizedTextKind, NoteActions, NoteReplyForm, UnknownNote } from '@shared/notes'; import { ReplyList } from '@shared/notes/replies/list'; import { User } from '@shared/user'; @@ -46,11 +39,7 @@ export function TextNoteScreen() { const renderKind = (event: NDKEvent) => { switch (event.kind) { case NDKKind.Text: - return ; - case NDKKind.Article: - return ; - case 1063: - return ; + return ; default: return ; } @@ -106,9 +95,9 @@ export function TextNoteScreen() { )}
- +
- +
diff --git a/src/shared/notes/file.tsx b/src/shared/notes/file.tsx index 1792b906..6b86eddf 100644 --- a/src/shared/notes/file.tsx +++ b/src/shared/notes/file.tsx @@ -83,7 +83,7 @@ export function FileNote({ event }: { event: NDKEvent }) {
-
{renderFileType()}
+
{renderFileType()}
diff --git a/src/shared/notes/preview/image.tsx b/src/shared/notes/preview/image.tsx index 1f6840d9..640d67b7 100644 --- a/src/shared/notes/preview/image.tsx +++ b/src/shared/notes/preview/image.tsx @@ -1,15 +1,29 @@ import { downloadDir } from '@tauri-apps/api/path'; +import { Window } from '@tauri-apps/api/window'; import { download } from '@tauri-apps/plugin-upload'; -import { SyntheticEvent } from 'react'; -import Zoom from 'react-medium-image-zoom'; +import { SyntheticEvent, useState } from 'react'; -import { CancelIcon, DownloadIcon } from '@shared/icons'; +import { CheckCircleIcon, DownloadIcon } from '@shared/icons'; export function ImagePreview({ url }: { url: string }) { - const downloadImage = async (url: string) => { - const downloadDirPath = await downloadDir(); - const filename = url.substring(url.lastIndexOf('/') + 1); - return await download(url, downloadDirPath + `/${filename}`); + const [downloaded, setDownloaded] = useState(false); + + const downloadImage = async (e: { stopPropagation: () => void }) => { + try { + e.stopPropagation(); + + const downloadDirPath = await downloadDir(); + const filename = url.substring(url.lastIndexOf('/') + 1); + await download(url, downloadDirPath + `/${filename}`); + + setDownloaded(true); + } catch (e) { + console.error(e); + } + }; + + const open = () => { + return new Window('image-viewer', { url, title: 'Image Viewer' }); }; const fallback = (event: SyntheticEvent) => { @@ -17,25 +31,28 @@ export function ImagePreview({ url }: { url: string }) { }; return ( - }> -
- {url} - -
-
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions +
+ {url} + +
); } diff --git a/src/shared/notes/text.tsx b/src/shared/notes/text.tsx index 2540773c..72a104be 100644 --- a/src/shared/notes/text.tsx +++ b/src/shared/notes/text.tsx @@ -15,7 +15,7 @@ export function TextNote({ event }: { event: NDKEvent }) { const { addWidget } = useWidget(); const { getEventThread } = useNostr(); - const thread = getEventThread(event); + const thread = getEventThread(event.tags); return (
diff --git a/src/shared/widgets/thread.tsx b/src/shared/widgets/thread.tsx index b3236135..ff8b63e2 100644 --- a/src/shared/widgets/thread.tsx +++ b/src/shared/widgets/thread.tsx @@ -4,6 +4,7 @@ import { WVList } from 'virtua'; import { LoaderIcon } from '@shared/icons'; import { + ChildNote, MemoizedArticleKind, MemoizedFileKind, MemoizedTextKind, @@ -16,16 +17,33 @@ import { User } from '@shared/user'; import { WidgetWrapper } from '@shared/widgets'; import { useEvent } from '@utils/hooks/useEvent'; +import { useNostr } from '@utils/hooks/useNostr'; import { Widget } from '@utils/types'; export function ThreadWidget({ widget }: { widget: Widget }) { const { status, data } = useEvent(widget.content); + const { getEventThread } = useNostr(); const renderKind = useCallback( (event: NDKEvent) => { + const thread = getEventThread(event.tags); switch (event.kind) { case NDKKind.Text: - return ; + return ( + <> + {thread ? ( +
+
+ {thread.rootEventId ? ( + + ) : null} + {thread.replyEventId ? : null} +
+
+ ) : null} + + + ); case NDKKind.Article: return ; case 1063: diff --git a/src/utils/hooks/useNostr.ts b/src/utils/hooks/useNostr.ts index 6bda592b..ddb22411 100644 --- a/src/utils/hooks/useNostr.ts +++ b/src/utils/hooks/useNostr.ts @@ -1,4 +1,10 @@ -import { NDKEvent, NDKFilter, NDKKind, NDKSubscription } from '@nostr-dev-kit/ndk'; +import { + NDKEvent, + NDKFilter, + NDKKind, + NDKSubscription, + NDKTag, +} from '@nostr-dev-kit/ndk'; import { open } from '@tauri-apps/plugin-dialog'; import { readBinaryFile } from '@tauri-apps/plugin-fs'; import { fetch } from '@tauri-apps/plugin-http'; @@ -50,20 +56,30 @@ export function useNostr() { } }; - const getEventThread = (event: NDKEvent) => { - let rootEventId: string; - let replyEventId: string; + const getEventThread = (tags: NDKTag[]) => { + let rootEventId: string = null; + let replyEventId: string = null; - if (event.tags?.[0]?.[0] === 'e' && !event.tags?.[0]?.[3]) { - rootEventId = event.tags[0][1]; + const events = tags.filter((el) => el[0] === 'e'); + + if (!events.length) return null; + + if (events.length === 1) + return { + rootEventId: events[0][1], + replyEventId: null, + }; + + if (events.length > 1) { + rootEventId = events.find((el) => el[3] === 'root')?.[1]; + replyEventId = events.find((el) => el[3] === 'reply')?.[1]; + + if (!rootEventId && !replyEventId) { + rootEventId = events[0][1]; + replyEventId = events[1][1]; + } } - rootEventId = event.tags.find((el) => el[3] === 'root')?.[1] || null; - // eslint-disable-next-line prefer-const - replyEventId = event.tags.find((el) => el[3] === 'reply')?.[1] || null; - - if (!rootEventId && !replyEventId) return null; - return { rootEventId, replyEventId,