This commit is contained in:
2023-11-01 13:01:52 +07:00
parent e218ebee89
commit f2dddf97f5
11 changed files with 115 additions and 837 deletions

View File

@@ -1,10 +1,4 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import ReactMarkdown from 'react-markdown';
import { Link } from 'react-router-dom';
import rehypeExternalLinks from 'rehype-external-links';
import remarkGfm from 'remark-gfm';
import { Boost, Hashtag, Invoice, MentionUser } from '@shared/notes';
export function ArticleDetailNote({ event }: { event: NDKEvent }) {
/*const metadata = useMemo(() => {
@@ -30,39 +24,8 @@ export function ArticleDetailNote({ event }: { event: NDKEvent }) {
}, [event.id]);*/
return (
<ReactMarkdown
className="break-p prose prose-neutral max-w-none select-text whitespace-pre-line leading-normal dark:prose-invert prose-headings:mb-1 prose-headings:mt-3 prose-p:mb-0 prose-p:mt-0 prose-p:last:mb-1 prose-a:font-normal prose-a:text-blue-500 prose-blockquote:mb-1 prose-blockquote:mt-1 prose-blockquote:border-l-[2px] prose-blockquote:border-blue-500 prose-blockquote:pl-2 prose-pre:whitespace-pre-wrap prose-pre:bg-white/10 prose-ol:m-0 prose-ol:mb-1 prose-ul:mb-1 prose-ul:mt-1 prose-img:mb-2 prose-img:mt-3 prose-hr:mx-0 prose-hr:my-2 hover:prose-a:text-blue-500"
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeExternalLinks({ target: '_blank' })]}
components={{
a: ({ href }) => {
const cleanURL = new URL(href);
cleanURL.search = '';
return (
<Link to={href} target="_blank" className="w-max break-all hover:!underline">
{cleanURL.hostname + cleanURL.pathname}
</Link>
);
},
del: ({ children }) => {
const key = children[0] as string;
if (typeof key !== 'string') return;
if (key.startsWith('pub') && key.length > 50 && key.length < 100) {
return <MentionUser pubkey={key.replace('pub-', '')} />;
}
if (key.startsWith('tag')) {
return <Hashtag tag={key.replace('tag-', '')} />;
}
if (key.startsWith('boost')) {
return <Boost boost={key.replace('boost-', '')} />;
}
if (key.startsWith('lnbc')) {
return <Invoice invoice={key.replace('lnbc-', '')} />;
}
},
}}
>
<div className="break-p prose prose-neutral max-w-none select-text whitespace-pre-line leading-normal dark:prose-invert prose-headings:mb-1 prose-headings:mt-3 prose-p:mb-0 prose-p:mt-0 prose-p:last:mb-1 prose-a:font-normal prose-a:text-blue-500 prose-blockquote:mb-1 prose-blockquote:mt-1 prose-blockquote:border-l-[2px] prose-blockquote:border-blue-500 prose-blockquote:pl-2 prose-pre:whitespace-pre-wrap prose-pre:bg-white/10 prose-ol:m-0 prose-ol:mb-1 prose-ul:mb-1 prose-ul:mt-1 prose-img:mb-2 prose-img:mt-3 prose-hr:mx-0 prose-hr:my-2 hover:prose-a:text-blue-500">
{event.content}
</ReactMarkdown>
</div>
);
}

View File

@@ -1,4 +1,6 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { downloadDir } from '@tauri-apps/api/path';
import { download } from '@tauri-apps/plugin-upload';
import {
MediaControlBar,
MediaController,
@@ -9,7 +11,9 @@ import {
MediaVolumeRange,
} from 'media-chrome/dist/react';
import { memo } from 'react';
import { Link } from 'react-router-dom';
import { DownloadIcon } from '@shared/icons';
import { LinkPreview } from '@shared/notes';
import { fileType } from '@utils/nip94';
@@ -17,56 +21,58 @@ export function FileNote(props: { event?: NDKEvent }) {
const url = props.event.tags.find((el) => el[0] === 'url')[1];
const type = fileType(url);
const downloadImage = async (url: string) => {
const downloadDirPath = await downloadDir();
const filename = url.substring(url.lastIndexOf('/') + 1);
return await download(url, downloadDirPath + `/${filename}`);
};
if (type === 'image') {
return (
<div className="mb-2 mt-3">
<div key={url} className="group relative mt-2">
<img
src={url}
alt={props.event.content}
className="h-auto w-full rounded-lg object-cover"
loading="lazy"
decoding="async"
style={{ contentVisibility: 'auto' }}
alt={url}
className="h-auto w-full rounded-lg border border-neutral-300 object-cover dark:border-neutral-700"
/>
<button
type="button"
onClick={() => downloadImage(url)}
className="absolute right-2 top-2 hidden h-10 w-10 items-center justify-center rounded-lg bg-black/50 backdrop-blur-xl group-hover:inline-flex hover:bg-blue-500"
>
<DownloadIcon className="h-5 w-5 text-white" />
</button>
</div>
);
}
if (type === 'video') {
return (
<div className="mb-2 mt-3">
<MediaController
key={url}
className="aspect-video w-full overflow-hidden rounded-lg"
>
<video
slot="media"
src={url}
poster={`https://thumbnail.video/api/get?url=${url}&seconds=1`}
preload="none"
muted
/>
<MediaControlBar>
<MediaPlayButton></MediaPlayButton>
<MediaTimeRange></MediaTimeRange>
<MediaTimeDisplay showDuration></MediaTimeDisplay>
<MediaMuteButton></MediaMuteButton>
<MediaVolumeRange></MediaVolumeRange>
</MediaControlBar>
</MediaController>
</div>
<MediaController
key={url}
className="mt-2 aspect-video w-full overflow-hidden rounded-lg"
>
<video
slot="media"
src={url}
poster={`https://thumbnail.video/api/get?url=${url}&seconds=1`}
preload="none"
muted
/>
<MediaControlBar>
<MediaPlayButton></MediaPlayButton>
<MediaTimeRange></MediaTimeRange>
<MediaTimeDisplay showDuration></MediaTimeDisplay>
<MediaMuteButton></MediaMuteButton>
<MediaVolumeRange></MediaVolumeRange>
</MediaControlBar>
</MediaController>
);
}
return (
<div className="mb-2">
<Link
to={url}
target="_blank"
className="break-all font-normal text-blue-500 hover:text-blue-600"
>
{url}
</Link>
<div className="mt-2">
<LinkPreview urls={[url]} />
</div>
);
}

View File

@@ -26,7 +26,7 @@ export function TextNote(props: { content?: string; truncate?: boolean }) {
}
return (
<div>
<div className="flex w-full flex-col items-start gap-2">
<Markdown
options={{
overrides: {