|
|
|
|
@ -1,4 +1,5 @@
@@ -1,4 +1,5 @@
|
|
|
|
|
import { Button } from '@/components/ui/button' |
|
|
|
|
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer' |
|
|
|
|
import { |
|
|
|
|
DropdownMenu, |
|
|
|
|
DropdownMenuCheckboxItem, |
|
|
|
|
@ -6,11 +7,14 @@ import {
@@ -6,11 +7,14 @@ import {
|
|
|
|
|
DropdownMenuSeparator, |
|
|
|
|
DropdownMenuTrigger |
|
|
|
|
} from '@/components/ui/dropdown-menu' |
|
|
|
|
import { Separator } from '@/components/ui/separator' |
|
|
|
|
import { isProtectedEvent } from '@/lib/event' |
|
|
|
|
import { simplifyUrl } from '@/lib/url' |
|
|
|
|
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider' |
|
|
|
|
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' |
|
|
|
|
import { useScreenSize } from '@/providers/ScreenSizeProvider' |
|
|
|
|
import client from '@/services/client.service' |
|
|
|
|
import { Check } from 'lucide-react' |
|
|
|
|
import { NostrEvent } from 'nostr-tools' |
|
|
|
|
import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react' |
|
|
|
|
import { useTranslation } from 'react-i18next' |
|
|
|
|
@ -42,6 +46,8 @@ export default function PostRelaySelector({
@@ -42,6 +46,8 @@ export default function PostRelaySelector({
|
|
|
|
|
setAdditionalRelayUrls: Dispatch<SetStateAction<string[]>> |
|
|
|
|
}) { |
|
|
|
|
const { t } = useTranslation() |
|
|
|
|
const { isSmallScreen } = useScreenSize() |
|
|
|
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false) |
|
|
|
|
const { relayUrls } = useCurrentRelays() |
|
|
|
|
const { relaySets, favoriteRelays } = useFavoriteRelays() |
|
|
|
|
const [postTargetItems, setPostTargetItems] = useState<TPostTargetItem[]>([]) |
|
|
|
|
@ -147,63 +153,135 @@ export default function PostRelaySelector({
@@ -147,63 +153,135 @@ export default function PostRelaySelector({
|
|
|
|
|
[] |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<DropdownMenu> |
|
|
|
|
<div className="flex items-center gap-2"> |
|
|
|
|
{t('Post to')} |
|
|
|
|
<DropdownMenuTrigger asChild> |
|
|
|
|
<Button variant="outline" className="px-2"> |
|
|
|
|
{description} |
|
|
|
|
</Button> |
|
|
|
|
</DropdownMenuTrigger> |
|
|
|
|
</div> |
|
|
|
|
<DropdownMenuContent align="start" className="max-w-96"> |
|
|
|
|
<DropdownMenuCheckboxItem |
|
|
|
|
const content = useMemo(() => { |
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<MenuItem |
|
|
|
|
checked={postTargetItems.some((item) => item.type === 'writeRelays')} |
|
|
|
|
onSelect={(e) => e.preventDefault()} |
|
|
|
|
onCheckedChange={handleWriteRelaysCheckedChange} |
|
|
|
|
> |
|
|
|
|
{t('Write relays')} |
|
|
|
|
</DropdownMenuCheckboxItem> |
|
|
|
|
</MenuItem> |
|
|
|
|
{relaySets.length > 0 && ( |
|
|
|
|
<> |
|
|
|
|
<DropdownMenuSeparator /> |
|
|
|
|
<MenuSeparator /> |
|
|
|
|
{relaySets |
|
|
|
|
.filter(({ relayUrls }) => relayUrls.length) |
|
|
|
|
.map(({ id, name, relayUrls }) => ( |
|
|
|
|
<DropdownMenuCheckboxItem |
|
|
|
|
<MenuItem |
|
|
|
|
key={id} |
|
|
|
|
checked={postTargetItems.some( |
|
|
|
|
(item) => item.type === 'relaySet' && item.id === id |
|
|
|
|
)} |
|
|
|
|
onSelect={(e) => e.preventDefault()} |
|
|
|
|
onCheckedChange={(checked) => handleRelaySetCheckedChange(checked, id, relayUrls)} |
|
|
|
|
> |
|
|
|
|
<div className="truncate"> |
|
|
|
|
{name} ({relayUrls.length}) |
|
|
|
|
</div> |
|
|
|
|
</DropdownMenuCheckboxItem> |
|
|
|
|
</MenuItem> |
|
|
|
|
))} |
|
|
|
|
</> |
|
|
|
|
)} |
|
|
|
|
{selectableRelays.length > 0 && ( |
|
|
|
|
<> |
|
|
|
|
<DropdownMenuSeparator /> |
|
|
|
|
<MenuSeparator /> |
|
|
|
|
{selectableRelays.map((url) => ( |
|
|
|
|
<DropdownMenuCheckboxItem |
|
|
|
|
<MenuItem |
|
|
|
|
key={url} |
|
|
|
|
checked={postTargetItems.some((item) => item.type === 'relay' && item.url === url)} |
|
|
|
|
onSelect={(e) => e.preventDefault()} |
|
|
|
|
onCheckedChange={(checked) => handleRelayCheckedChange(checked, url)} |
|
|
|
|
className="flex items-center gap-2" |
|
|
|
|
> |
|
|
|
|
<RelayIcon url={url} /> |
|
|
|
|
<div className="truncate">{simplifyUrl(url)}</div> |
|
|
|
|
</DropdownMenuCheckboxItem> |
|
|
|
|
<div className="flex items-center gap-2"> |
|
|
|
|
<RelayIcon url={url} /> |
|
|
|
|
<div className="truncate">{simplifyUrl(url)}</div> |
|
|
|
|
</div> |
|
|
|
|
</MenuItem> |
|
|
|
|
))} |
|
|
|
|
</> |
|
|
|
|
)} |
|
|
|
|
</> |
|
|
|
|
) |
|
|
|
|
}, [postTargetItems, relaySets, selectableRelays]) |
|
|
|
|
|
|
|
|
|
if (isSmallScreen) { |
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<div className="flex items-center gap-2"> |
|
|
|
|
{t('Post to')} |
|
|
|
|
<Button |
|
|
|
|
variant="outline" |
|
|
|
|
className="px-2 flex-1 max-w-fit justify-start" |
|
|
|
|
onClick={() => setIsDrawerOpen(true)} |
|
|
|
|
> |
|
|
|
|
<div className="truncate">{description}</div> |
|
|
|
|
</Button> |
|
|
|
|
</div> |
|
|
|
|
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}> |
|
|
|
|
<DrawerOverlay onClick={() => setIsDrawerOpen(false)} /> |
|
|
|
|
<DrawerContent hideOverlay>{content}</DrawerContent> |
|
|
|
|
</Drawer> |
|
|
|
|
</> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<DropdownMenu> |
|
|
|
|
<div className="flex items-center gap-2"> |
|
|
|
|
{t('Post to')} |
|
|
|
|
<DropdownMenuTrigger asChild> |
|
|
|
|
<Button variant="outline" className="px-2 flex-1 max-w-fit justify-start"> |
|
|
|
|
<div className="truncate">{description}</div> |
|
|
|
|
</Button> |
|
|
|
|
</DropdownMenuTrigger> |
|
|
|
|
</div> |
|
|
|
|
<DropdownMenuContent align="start" className="max-w-96"> |
|
|
|
|
{content} |
|
|
|
|
</DropdownMenuContent> |
|
|
|
|
</DropdownMenu> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function MenuSeparator() { |
|
|
|
|
const { isSmallScreen } = useScreenSize() |
|
|
|
|
if (isSmallScreen) { |
|
|
|
|
return <Separator /> |
|
|
|
|
} |
|
|
|
|
return <DropdownMenuSeparator /> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function MenuItem({ |
|
|
|
|
children, |
|
|
|
|
checked, |
|
|
|
|
onCheckedChange |
|
|
|
|
}: { |
|
|
|
|
children: React.ReactNode |
|
|
|
|
checked: boolean |
|
|
|
|
onCheckedChange: (checked: boolean) => void |
|
|
|
|
}) { |
|
|
|
|
const { isSmallScreen } = useScreenSize() |
|
|
|
|
|
|
|
|
|
if (isSmallScreen) { |
|
|
|
|
return ( |
|
|
|
|
<div |
|
|
|
|
onClick={() => onCheckedChange(!checked)} |
|
|
|
|
className="flex items-center gap-2 px-4 py-3 clickable" |
|
|
|
|
> |
|
|
|
|
<div className="flex items-center justify-center size-4 shrink-0"> |
|
|
|
|
{checked && <Check className="size-4" />} |
|
|
|
|
</div> |
|
|
|
|
{children} |
|
|
|
|
</div> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<DropdownMenuCheckboxItem |
|
|
|
|
checked={checked} |
|
|
|
|
onSelect={(e) => e.preventDefault()} |
|
|
|
|
onCheckedChange={onCheckedChange} |
|
|
|
|
className="flex items-center gap-2" |
|
|
|
|
> |
|
|
|
|
{children} |
|
|
|
|
</DropdownMenuCheckboxItem> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|