mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-18 11:13:30 +00:00
updated preview component
This commit is contained in:
parent
672298daf9
commit
fe2fef0f85
@ -42,11 +42,11 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time:
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex w-full flex-1 items-start justify-between">
|
<div className="flex w-full flex-1 items-start justify-between">
|
||||||
<div className="flex w-full justify-between">
|
<div className="flex w-full justify-between">
|
||||||
<div className="flex items-center gap-2 text-sm">
|
<div className="flex items-baseline gap-2 text-sm">
|
||||||
<span className="font-bold leading-tight">
|
<span className="font-bold leading-tight">
|
||||||
{userData?.name ? userData.name : truncate(pubkey, 16, ' .... ')}
|
{userData?.name ? userData.name : truncate(pubkey, 16, ' .... ')}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-zinc-500">·</span>
|
<span className="leading-tight text-zinc-500">·</span>
|
||||||
<Moment fromNow unix className="text-zinc-500">
|
<Moment fromNow unix className="text-zinc-500">
|
||||||
{time}
|
{time}
|
||||||
</Moment>
|
</Moment>
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
import Image from 'next/image';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export default function ImagePreview({ data }: { data: object }) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`relative mt-2 flex flex-col overflow-hidden rounded-xl border border-zinc-800`}>
|
|
||||||
<div className="relative h-full w-full">
|
|
||||||
<Image
|
|
||||||
src={data['image']}
|
|
||||||
alt="image preview"
|
|
||||||
width="0"
|
|
||||||
height="0"
|
|
||||||
sizes="100vw"
|
|
||||||
className="h-auto w-full object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,16 +1,20 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
import ImageCard from '@components/note/content/preview/imageCard';
|
||||||
|
import Video from '@components/note/content/preview/video';
|
||||||
|
|
||||||
import { MarkdownPreviewProps } from '@uiw/react-markdown-preview';
|
import { MarkdownPreviewProps } from '@uiw/react-markdown-preview';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import ReactPlayer from 'react-player';
|
||||||
|
|
||||||
const MarkdownPreview = dynamic<MarkdownPreviewProps>(() => import('@uiw/react-markdown-preview'), {
|
const MarkdownPreview = dynamic<MarkdownPreviewProps>(() => import('@uiw/react-markdown-preview'), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function Content({ data }: { data: string }) {
|
export default function Content({ data }: { data: string }) {
|
||||||
const imagesRef = useRef([]);
|
const [preview, setPreview] = useState({});
|
||||||
const videosRef = useRef([]);
|
|
||||||
|
|
||||||
|
const content = useRef(data);
|
||||||
const urls = useMemo(
|
const urls = useMemo(
|
||||||
() =>
|
() =>
|
||||||
data.match(
|
data.match(
|
||||||
@ -19,52 +23,56 @@ export default function Content({ data }: { data: string }) {
|
|||||||
[data]
|
[data]
|
||||||
);
|
);
|
||||||
|
|
||||||
const extractURL = useCallback((urls: any[]) => {
|
|
||||||
if (urls !== null && urls.length > 0) {
|
|
||||||
urls.forEach((url: string | URL) => {
|
|
||||||
const parseURL = new URL(url);
|
|
||||||
const path = parseURL.pathname.toLowerCase();
|
|
||||||
switch (path) {
|
|
||||||
case path.match(/\.(jpg|jpeg|gif|png|webp)$/)?.input:
|
|
||||||
imagesRef.current.push(parseURL.href);
|
|
||||||
break;
|
|
||||||
case path.match(
|
|
||||||
/(http:|https:)?\/\/(www\.)?(youtube.com|youtu.be)\/(watch)?(\?v=)?(\S+)?/
|
|
||||||
)?.input:
|
|
||||||
videosRef.current.push(parseURL.href);
|
|
||||||
break;
|
|
||||||
case path.match(/\.(mp4|webm|m4v|mov|avi|mkv|flv)$/)?.input:
|
|
||||||
videosRef.current.push(parseURL.href);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
extractURL(urls);
|
if (urls !== null && urls.length > 0) {
|
||||||
}, [extractURL, urls]);
|
const parseURL = new URL(urls[0]);
|
||||||
|
|
||||||
|
if (parseURL.pathname.toLowerCase().match(/\.(jpg|jpeg|gif|png|webp)$/)) {
|
||||||
|
// add image to preview
|
||||||
|
setPreview({ image: parseURL.href, type: 'image' });
|
||||||
|
content.current = content.current.replace(parseURL.href, '');
|
||||||
|
} else if (ReactPlayer.canPlay(parseURL.href)) {
|
||||||
|
// add video to preview
|
||||||
|
setPreview({ url: parseURL.href, type: 'video' });
|
||||||
|
content.current = content.current.replace(parseURL.href, '');
|
||||||
|
} // #TODO: support multiple preview
|
||||||
|
}
|
||||||
|
}, [urls]);
|
||||||
|
|
||||||
|
const previewAttachment = useCallback(() => {
|
||||||
|
if (Object.keys(preview).length > 0) {
|
||||||
|
switch (preview['type']) {
|
||||||
|
case 'image':
|
||||||
|
return <ImageCard data={preview} />;
|
||||||
|
case 'video':
|
||||||
|
return <Video data={preview} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [preview]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<MarkdownPreview
|
<div>
|
||||||
source={data}
|
<MarkdownPreview
|
||||||
className={
|
source={content.current}
|
||||||
'prose prose-zinc max-w-none break-words dark:prose-invert prose-headings:mt-3 prose-headings:mb-2 prose-p:m-0 prose-p:leading-normal prose-ul:mt-2 prose-li:my-1'
|
className={
|
||||||
}
|
'prose prose-zinc max-w-none break-words dark:prose-invert prose-headings:mt-3 prose-headings:mb-2 prose-p:m-0 prose-p:leading-normal prose-ul:mt-2 prose-li:my-1'
|
||||||
linkTarget="_blank"
|
}
|
||||||
disallowedElements={[
|
linkTarget="_blank"
|
||||||
'Table',
|
disallowedElements={[
|
||||||
'Heading ID',
|
'Table',
|
||||||
'Highlight',
|
'Heading ID',
|
||||||
'Fenced Code Block',
|
'Highlight',
|
||||||
'Footnote',
|
'Fenced Code Block',
|
||||||
'Definition List',
|
'Footnote',
|
||||||
'Task List',
|
'Definition List',
|
||||||
]}
|
'Task List',
|
||||||
/>
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>{previewAttachment()}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ export default function ImageCard({ data }: { data: object }) {
|
|||||||
<div className="relative h-full w-full">
|
<div className="relative h-full w-full">
|
||||||
<Image
|
<Image
|
||||||
src={data['image']}
|
src={data['image']}
|
||||||
alt="image preview"
|
alt={data['image']}
|
||||||
width="0"
|
width="0"
|
||||||
height="0"
|
height="0"
|
||||||
sizes="100vw"
|
sizes="100vw"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Reaction from '@components/note/atoms/reaction';
|
import Reaction from '@components/note/atoms/reaction';
|
||||||
import Reply from '@components/note/atoms/reply';
|
import Reply from '@components/note/atoms/reply';
|
||||||
import RootUser from '@components/note/atoms/rootUser';
|
import RootUser from '@components/note/atoms/rootUser';
|
||||||
import User from '@components/note/atoms/user';
|
import { User } from '@components/note/atoms/user';
|
||||||
import { Placeholder } from '@components/note/placeholder';
|
import { Placeholder } from '@components/note/placeholder';
|
||||||
|
|
||||||
import LikeSolidIcon from '@assets/icons/LikeSolid';
|
import LikeSolidIcon from '@assets/icons/LikeSolid';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Reaction from '@components/note/atoms/reaction';
|
import Reaction from '@components/note/atoms/reaction';
|
||||||
import Reply from '@components/note/atoms/reply';
|
import Reply from '@components/note/atoms/reply';
|
||||||
import User from '@components/note/atoms/user';
|
import { User } from '@components/note/atoms/user';
|
||||||
import { Placeholder } from '@components/note/placeholder';
|
import { Placeholder } from '@components/note/placeholder';
|
||||||
|
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Reaction from '@components/note/atoms/reaction';
|
import Reaction from '@components/note/atoms/reaction';
|
||||||
import Reply from '@components/note/atoms/reply';
|
import Reply from '@components/note/atoms/reply';
|
||||||
import RootUser from '@components/note/atoms/rootUser';
|
import RootUser from '@components/note/atoms/rootUser';
|
||||||
import User from '@components/note/atoms/user';
|
import { User } from '@components/note/atoms/user';
|
||||||
import { Placeholder } from '@components/note/placeholder';
|
import { Placeholder } from '@components/note/placeholder';
|
||||||
|
|
||||||
import RepostIcon from '@assets/icons/Repost';
|
import RepostIcon from '@assets/icons/Repost';
|
||||||
|
Loading…
Reference in New Issue
Block a user