update navigation design
This commit is contained in:
@@ -82,13 +82,13 @@ export default function ChannelCreateModal() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => openModal()}
|
||||
className="group inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900"
|
||||
className="group inline-flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:bg-zinc-900"
|
||||
>
|
||||
<div className="inline-flex h-5 w-5 shrink items-center justify-center rounded bg-zinc-900 group-hover:bg-zinc-800">
|
||||
<PlusIcon width={12} height={12} className="text-zinc-500" />
|
||||
</div>
|
||||
<div>
|
||||
<h5 className="text-sm font-medium text-zinc-500 group-hover:text-zinc-400">Add a new channel</h5>
|
||||
<h5 className="text-[13px] font-semibold text-zinc-500 group-hover:text-zinc-400">Add a new channel</h5>
|
||||
</div>
|
||||
</button>
|
||||
<Transition appear show={isOpen} as={Fragment}>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { DEFAULT_AVATAR } from '@lume/stores/constants';
|
||||
import { useChannelProfile } from '@lume/utils/hooks/useChannelProfile';
|
||||
import { usePageContext } from '@lume/utils/hooks/usePageContext';
|
||||
|
||||
@@ -15,19 +14,15 @@ export default function ChannelsListItem({ data }: { data: any }) {
|
||||
<a
|
||||
href={`/app/channel?id=${data.event_id}&pubkey=${data.pubkey}`}
|
||||
className={twMerge(
|
||||
'inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900',
|
||||
'group inline-flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:bg-zinc-900',
|
||||
pageID === data.event_id ? 'dark:bg-zinc-900 dark:text-zinc-100 hover:dark:bg-zinc-800' : ''
|
||||
)}
|
||||
>
|
||||
<div className="relative h-5 w-5 shrink-0 rounded">
|
||||
<img
|
||||
src={channel?.picture || DEFAULT_AVATAR}
|
||||
alt={data.event_id}
|
||||
className="h-5 w-5 rounded bg-white object-cover"
|
||||
/>
|
||||
<div className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900 group-hover:bg-zinc-800">
|
||||
<span className="text-xs text-zinc-200">#</span>
|
||||
</div>
|
||||
<div>
|
||||
<h5 className="truncate text-sm font-medium text-zinc-400">{channel?.name}</h5>
|
||||
<h5 className="truncate text-[13px] font-semibold text-zinc-400">{channel?.name}</h5>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
|
||||
@@ -10,24 +10,21 @@ export default function ChannelsList() {
|
||||
const { data, error }: any = useSWR('channels', fetcher);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-px">
|
||||
<>
|
||||
{error && <div>failed to fetch</div>}
|
||||
{!data ? (
|
||||
<>
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
data.map((item: { event_id: string }) => <ChannelsListItem key={item.event_id} data={item} />)
|
||||
)}
|
||||
</>
|
||||
<div className="flex flex-col">
|
||||
{!data || error ? (
|
||||
<>
|
||||
<div className="inline-flex h-8 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
<div className="inline-flex h-8 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
data.map((item: { event_id: string }) => <ChannelsListItem key={item.event_id} data={item} />)
|
||||
)}
|
||||
<ChannelCreateModal />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function ChatsListItem({ pubkey }: { pubkey: string }) {
|
||||
<>
|
||||
{isError && <div>error</div>}
|
||||
{isLoading && !user ? (
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="inline-flex h-8 items-center gap-2.5 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div>
|
||||
<div className="h-2.5 w-full animate-pulse truncate rounded bg-zinc-800 text-sm font-medium"></div>
|
||||
@@ -27,7 +27,7 @@ export default function ChatsListItem({ pubkey }: { pubkey: string }) {
|
||||
<a
|
||||
href={`/app/chat?pubkey=${pubkey}`}
|
||||
className={twMerge(
|
||||
'inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900',
|
||||
'group inline-flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:bg-zinc-900',
|
||||
pagePubkey === pubkey ? 'dark:bg-zinc-900 dark:text-zinc-100 hover:dark:bg-zinc-800' : ''
|
||||
)}
|
||||
>
|
||||
@@ -35,7 +35,7 @@ export default function ChatsListItem({ pubkey }: { pubkey: string }) {
|
||||
<img src={user.picture || DEFAULT_AVATAR} alt={pubkey} className="h-5 w-5 rounded bg-white object-cover" />
|
||||
</div>
|
||||
<div>
|
||||
<h5 className="truncate text-sm font-medium text-zinc-400">
|
||||
<h5 className="truncate text-[13px] font-semibold text-zinc-400 group-hover:text-zinc-200">
|
||||
{user.display_name || user.name || shortenKey(pubkey)}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
@@ -13,24 +13,21 @@ export default function ChatsList() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-px">
|
||||
<>
|
||||
<ChatsListSelfItem />
|
||||
{error && <div>failed to fetch</div>}
|
||||
{!chats ? (
|
||||
<>
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
chats.map((item: { pubkey: string }) => <ChatsListItem key={item.pubkey} pubkey={item.pubkey} />)
|
||||
)}
|
||||
</>
|
||||
<ChatsListSelfItem />
|
||||
{!chats || error ? (
|
||||
<>
|
||||
<div className="inline-flex h-8 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
<div className="inline-flex h-8 items-center gap-2 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div className="h-3 w-full animate-pulse bg-zinc-800"></div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
chats.map((item: { pubkey: string }) => <ChatsListItem key={item.pubkey} pubkey={item.pubkey} />)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function ChatsListSelfItem() {
|
||||
<>
|
||||
{isError && <div>error</div>}
|
||||
{isLoading && !account ? (
|
||||
<div className="inline-flex items-center gap-2 rounded-md px-2.5 py-1.5">
|
||||
<div className="inline-flex h-8 items-center gap-2.5 rounded-md px-2.5">
|
||||
<div className="relative h-5 w-5 shrink-0 animate-pulse rounded bg-zinc-800"></div>
|
||||
<div>
|
||||
<div className="h-2.5 w-full animate-pulse truncate rounded bg-zinc-800 text-sm font-medium"></div>
|
||||
@@ -28,7 +28,7 @@ export default function ChatsListSelfItem() {
|
||||
<a
|
||||
href={`/app/chat?pubkey=${account.pubkey}`}
|
||||
className={twMerge(
|
||||
'inline-flex items-center gap-2 rounded-md px-2.5 py-1.5 hover:bg-zinc-900',
|
||||
'inline-flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:bg-zinc-900',
|
||||
pagePubkey === account.pubkey ? 'dark:bg-zinc-900 dark:text-zinc-100 hover:dark:bg-zinc-800' : ''
|
||||
)}
|
||||
>
|
||||
@@ -40,8 +40,9 @@ export default function ChatsListSelfItem() {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h5 className="truncate text-sm font-medium text-zinc-400">
|
||||
{profile?.display_name || profile?.name || shortenKey(account.pubkey)} (you)
|
||||
<h5 className="truncate text-[13px] font-semibold text-zinc-400">
|
||||
{profile?.display_name || profile?.name || shortenKey(account.pubkey)}{' '}
|
||||
<span className="text-zinc-500">(you)</span>
|
||||
</h5>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
15
src/shared/icons/myspace.tsx
Normal file
15
src/shared/icons/myspace.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export default function MyspaceIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg width={24} height={24} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M8.75 7.75H15.25M8.75 11.75H12.25M4.25 3.25V20.75H19.75V3.25H4.25Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth={1.5}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
12
src/shared/icons/threads.tsx
Normal file
12
src/shared/icons/threads.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export default function ThreadsIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg width={24} height={24} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M2.75 3.75V3C2.33579 3 2 3.33579 2 3.75H2.75ZM16.25 3.75H17C17 3.33579 16.6642 3 16.25 3V3.75ZM21.25 12H22C22 11.5858 21.6642 11.25 21.25 11.25V12ZM6.75 15C6.33579 15 6 15.3358 6 15.75C6 16.1642 6.33579 16.5 6.75 16.5V15ZM6.75 7.75V7C6.33579 7 6 7.33579 6 7.75H6.75ZM12.25 7.75H13C13 7.33579 12.6642 7 12.25 7V7.75ZM12.25 12.25V13C12.6642 13 13 12.6642 13 12.25H12.25ZM6.75 12.25H6C6 12.6642 6.33579 13 6.75 13V12.25ZM2.75 4.5H16.25V3H2.75V4.5ZM22 17.75V12H20.5V17.75H22ZM15.5 3.75V12H17V3.75H15.5ZM15.5 12V17.75H17V12H15.5ZM21.25 11.25H16.25V12.75H21.25V11.25ZM2 3.75V17.75H3.5V3.75H2ZM5.25 21H18.5V19.5H5.25V21ZM2 17.75C2 19.5449 3.45507 21 5.25 21V19.5C4.2835 19.5 3.5 18.7165 3.5 17.75H2ZM18.75 21C20.5449 21 22 19.5449 22 17.75H20.5C20.5 18.7165 19.7165 19.5 18.75 19.5V21ZM18.75 19.5C17.7835 19.5 17 18.7165 17 17.75H15.5C15.5 19.5449 16.9551 21 18.75 21V19.5ZM6.75 16.5H12.25V15H6.75V16.5ZM6.75 8.5H12.25V7H6.75V8.5ZM11.5 7.75V12.25H13V7.75H11.5ZM12.25 11.5H6.75V13H12.25V11.5ZM7.5 12.25V7.75H6V12.25H7.5Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
15
src/shared/icons/world.tsx
Normal file
15
src/shared/icons/world.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { SVGProps } from 'react';
|
||||
|
||||
export default function WorldIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg width={24} height={24} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
d="M19.7783 4.22184L4.22197 19.7782M21.25 12C21.25 17.1086 17.1086 21.25 12 21.25C6.89137 21.25 2.75 17.1086 2.75 12C2.75 6.89137 6.89137 2.75 12 2.75C17.1086 2.75 21.25 6.89137 21.25 12ZM18.5163 18.516C17.3167 19.7156 13.427 17.7707 9.82826 14.172C6.22955 10.5733 4.28467 6.68352 5.48424 5.48395C6.68381 4.28438 10.5736 6.22927 14.1723 9.82798C17.771 13.4267 19.7159 17.3165 18.5163 18.516Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth={1.5}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import ActiveAccount from '@lume/shared/accounts/active';
|
||||
import InactiveAccount from '@lume/shared/accounts/inactive';
|
||||
import LumeIcon from '@lume/shared/icons/lume';
|
||||
import PlusIcon from '@lume/shared/icons/plus';
|
||||
import { APP_VERSION } from '@lume/stores/constants';
|
||||
import { getAccounts } from '@lume/utils/storage';
|
||||
@@ -13,14 +12,8 @@ export default function MultiAccounts() {
|
||||
const { data, error }: any = useSWR('allAccounts', fetcher);
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-between px-2 pb-4 pt-3">
|
||||
<div className="flex h-full flex-col items-center justify-between pb-4 pt-3">
|
||||
<div className="flex flex-col gap-3">
|
||||
<a
|
||||
href="/app/newsfeed/following"
|
||||
className="group relative flex h-11 w-11 shrink cursor-pointer items-center justify-center rounded-lg bg-zinc-900 hover:bg-zinc-800"
|
||||
>
|
||||
<LumeIcon className="h-6 w-auto text-zinc-400 group-hover:text-zinc-200" />
|
||||
</a>
|
||||
<>
|
||||
{error && <div>failed to load</div>}
|
||||
{!data ? (
|
||||
|
||||
@@ -1,53 +1,59 @@
|
||||
import ChannelsList from '@lume/app/channel/components/list';
|
||||
import ChatsList from '@lume/app/chat/components/list';
|
||||
import ActiveLink from '@lume/shared/activeLink';
|
||||
import MyspaceIcon from '@lume/shared/icons/myspace';
|
||||
import NavArrowDownIcon from '@lume/shared/icons/navArrowDown';
|
||||
import ThreadsIcon from '@lume/shared/icons/threads';
|
||||
import WorldIcon from '@lume/shared/icons/world';
|
||||
|
||||
import { Disclosure } from '@headlessui/react';
|
||||
|
||||
export default function Navigation() {
|
||||
return (
|
||||
<div className="relative flex h-full flex-col gap-1 overflow-hidden pt-3">
|
||||
<div className="relative flex h-full flex-col gap-3 overflow-hidden pt-3">
|
||||
{/* Newsfeed */}
|
||||
<Disclosure defaultOpen={true}>
|
||||
{({ open }) => (
|
||||
<div className="flex flex-col px-2">
|
||||
<Disclosure.Button className="flex cursor-pointer items-center gap-1 px-1 py-1">
|
||||
<div
|
||||
className={`inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out ${
|
||||
open ? '' : 'rotate-180'
|
||||
}`}
|
||||
>
|
||||
<NavArrowDownIcon width={12} height={12} className="text-zinc-700" />
|
||||
</div>
|
||||
<h3 className="text-[11px] font-bold uppercase tracking-widest text-zinc-600">Newsfeed</h3>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel className="flex flex-col text-zinc-400">
|
||||
<ActiveLink
|
||||
href="/app/newsfeed/following"
|
||||
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-sm font-medium hover:text-zinc-200"
|
||||
activeClassName="dark:bg-zinc-900 dark:text-zinc-100 hover:dark:bg-zinc-800"
|
||||
>
|
||||
<span>#</span>
|
||||
<span>Following</span>
|
||||
</ActiveLink>
|
||||
<ActiveLink
|
||||
href="/app/newsfeed/circle"
|
||||
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-sm font-medium hover:text-zinc-200"
|
||||
activeClassName="dark:bg-zinc-900 dark:text-zinc-100 hover:dark:bg-zinc-800"
|
||||
>
|
||||
<span>#</span>
|
||||
<span>Circle</span>
|
||||
</ActiveLink>
|
||||
</Disclosure.Panel>
|
||||
</div>
|
||||
)}
|
||||
</Disclosure>
|
||||
<div className="flex flex-col gap-0.5 px-1.5">
|
||||
<div className="px-2.5">
|
||||
<h3 className="text-[11px] font-bold uppercase tracking-widest text-zinc-600">Feeds</h3>
|
||||
</div>
|
||||
<div className="flex flex-col text-zinc-400">
|
||||
<ActiveLink
|
||||
href="/app/newsfeed/following"
|
||||
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-[13px] font-semibold hover:text-zinc-200"
|
||||
activeClassName=""
|
||||
>
|
||||
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">
|
||||
<WorldIcon width={12} height={12} className="text-zinc-200" />
|
||||
</span>
|
||||
<span>Daily</span>
|
||||
</ActiveLink>
|
||||
<ActiveLink
|
||||
href="/app/threads"
|
||||
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-[13px] font-semibold hover:text-zinc-200"
|
||||
activeClassName=""
|
||||
>
|
||||
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">
|
||||
<ThreadsIcon width={12} height={12} className="text-zinc-200" />
|
||||
</span>
|
||||
<span>Threads</span>
|
||||
</ActiveLink>
|
||||
<ActiveLink
|
||||
href="/app/myspace"
|
||||
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-[13px] font-semibold hover:text-zinc-200"
|
||||
activeClassName=""
|
||||
>
|
||||
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">
|
||||
<MyspaceIcon width={12} height={12} className="text-zinc-200" />
|
||||
</span>
|
||||
<span>MySpace</span>
|
||||
</ActiveLink>
|
||||
</div>
|
||||
</div>
|
||||
{/* Channels */}
|
||||
<Disclosure defaultOpen={true}>
|
||||
{({ open }) => (
|
||||
<div className="flex flex-col px-2">
|
||||
<Disclosure.Button className="flex cursor-pointer items-center gap-1 px-1 py-1">
|
||||
<div className="flex flex-col gap-0.5 px-1.5">
|
||||
<Disclosure.Button className="flex cursor-pointer items-center gap-1 px-2.5">
|
||||
<div
|
||||
className={`inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out ${
|
||||
open ? '' : 'rotate-180'
|
||||
@@ -66,8 +72,8 @@ export default function Navigation() {
|
||||
{/* Chats */}
|
||||
<Disclosure defaultOpen={true}>
|
||||
{({ open }) => (
|
||||
<div className="flex flex-col px-2">
|
||||
<Disclosure.Button className="flex cursor-pointer items-center gap-1 px-1 py-1">
|
||||
<div className="flex flex-col gap-0.5 px-1.5">
|
||||
<Disclosure.Button className="flex cursor-pointer items-center gap-1 px-2.5">
|
||||
<div
|
||||
className={`inline-flex h-5 w-5 transform items-center justify-center transition-transform duration-150 ease-in-out ${
|
||||
open ? '' : 'rotate-180'
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
export default function ImagePreview({ url, size }: { url: string; size: string }) {
|
||||
return (
|
||||
<div className={`relative h-full ${size === 'large' ? 'w-4/5' : 'w-1/2'} mt-2 rounded-lg border border-zinc-800`}>
|
||||
<img
|
||||
src={url}
|
||||
alt={url}
|
||||
className="h-auto w-full rounded-lg object-cover"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
style={{ contentVisibility: 'auto' }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { MediaOutlet, MediaPlayer } from '@vidstack/react';
|
||||
|
||||
export default function VideoPreview({ url, size }: { url: string; size: string }) {
|
||||
return (
|
||||
<div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className={`relative mt-2 flex flex-col overflow-hidden rounded-lg ${size === 'large' ? 'w-4/5' : 'w-2/3'}`}
|
||||
>
|
||||
<MediaPlayer src={url} poster="" controls>
|
||||
<MediaOutlet />
|
||||
</MediaPlayer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import YouTube from 'react-youtube';
|
||||
|
||||
function getVideoId(url: string) {
|
||||
const regex = /(youtu.*be.*)\/(watch\?v=|embed\/|v|shorts|)(.*?((?=[&#?])|$))/gm;
|
||||
return regex.exec(url)[3];
|
||||
}
|
||||
|
||||
export default function YoutubePreview({ url, size }: { url: string; size: string }) {
|
||||
const id = getVideoId(url);
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className={`relative mt-2 flex flex-col overflow-hidden rounded-lg ${size === 'large' ? 'w-4/5' : 'w-2/3'}`}
|
||||
>
|
||||
<YouTube videoId={id} className="aspect-video xl:w-2/3" opts={{ width: '100%', height: '100%' }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { messageParser } from '@lume/utils/parser';
|
||||
|
||||
import { nip04 } from 'nostr-tools';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
@@ -10,7 +8,7 @@ export const useDecryptMessage = (
|
||||
eventTags: string[],
|
||||
encryptedContent: string
|
||||
) => {
|
||||
const [content, setContent] = useState('');
|
||||
const [content, setContent] = useState(null);
|
||||
|
||||
const extractSenderKey = useCallback(() => {
|
||||
const keyInTags = eventTags.find(([k, v]) => k === 'p' && v && v !== '')[1];
|
||||
@@ -32,5 +30,5 @@ export const useDecryptMessage = (
|
||||
decrypt().catch(console.error);
|
||||
}, [decrypt]);
|
||||
|
||||
return content.length > 0 ? messageParser(content) : '';
|
||||
return content ? content : '';
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user