feat: remind users to optimize relay settings

This commit is contained in:
codytseng
2025-08-17 16:28:15 +08:00
parent 6350ddc224
commit 2d237866fb
23 changed files with 383 additions and 29 deletions

View File

@@ -0,0 +1,13 @@
import { TriangleAlert } from 'lucide-react'
export default function AlertCard({ title, content }: { title: string; content: string }) {
return (
<div className="p-3 rounded-lg text-sm bg-amber-100/20 dark:bg-amber-950/20 border border-amber-500 text-amber-500 [&_svg]:size-4">
<div className="flex items-center gap-2">
<TriangleAlert />
<div className="font-medium">{title}</div>
</div>
<div className="pl-6">{content}</div>
</div>
)
}

View File

@@ -0,0 +1,37 @@
import { TMailboxRelay } from '@/types'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import AlertCard from '../AlertCard'
export default function RelayCountWarning({ relays }: { relays: TMailboxRelay[] }) {
const { t } = useTranslation()
const readRelayCount = useMemo(() => {
return relays.filter((r) => r.scope !== 'write').length
}, [relays])
const writeRelayCount = useMemo(() => {
return relays.filter((r) => r.scope !== 'read').length
}, [relays])
const showReadWarning = readRelayCount > 4
const showWriteWarning = writeRelayCount > 4
if (!showReadWarning && !showWriteWarning) {
return null
}
return (
<AlertCard
title={showReadWarning ? t('Too many read relays') : t('Too many write relays')}
content={
showReadWarning
? t(
'You have {{count}} read relays. Most clients only use 2-4 relays, setting more is unnecessary.',
{ count: readRelayCount }
)
: t(
'You have {{count}} write relays. Most clients only use 2-4 relays, setting more is unnecessary.',
{ count: writeRelayCount }
)
}
/>
)
}

View File

@@ -6,6 +6,7 @@ import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import MailboxRelay from './MailboxRelay'
import NewMailboxRelayInput from './NewMailboxRelayInput'
import RelayCountWarning from './RelayCountWarning'
import SaveButton from './SaveButton'
export default function MailboxSetting() {
@@ -65,6 +66,7 @@ export default function MailboxSetting() {
<div>{t('write relays description')}</div>
<div>{t('read & write relays notice')}</div>
</div>
<RelayCountWarning relays={relays} />
<SaveButton mailboxRelays={relays} hasChange={hasChange} setHasChange={setHasChange} />
<div className="space-y-2">
{relays.map((relay) => (

View File

@@ -5,9 +5,10 @@ import { Switch } from '@/components/ui/switch'
import { normalizeUrl } from '@/lib/url'
import { TPollCreateData } from '@/types'
import dayjs from 'dayjs'
import { AlertCircle, Eraser, X } from 'lucide-react'
import { Eraser, X } from 'lucide-react'
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AlertCard from '../AlertCard'
export default function PollEditor({
pollCreateData,
@@ -124,17 +125,12 @@ export default function PollEditor({
</div>
<div className="grid gap-2">
<div className="p-3 rounded-lg text-sm bg-destructive [&_svg]:size-4">
<div className="flex items-center gap-2">
<AlertCircle />
<div className="font-medium">{t('This is a poll note.')}</div>
</div>
<div className="pl-6">
{t(
'Unlike regular notes, polls are not widely supported and may not display on other clients.'
)}
</div>
</div>
<AlertCard
title={t('This is a poll note.')}
content={t(
'Unlike regular notes, polls are not widely supported and may not display on other clients.'
)}
/>
<Button variant="ghost-destructive" className="w-full" onClick={() => setIsPoll(false)}>
{t('Remove poll')}

View File

@@ -0,0 +1,110 @@
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle
} from '@/components/ui/drawer'
import { toRelaySettings } from '@/lib/link'
import { useSecondaryPage } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import storage from '@/services/local-storage.service'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
export default function TooManyRelaysAlertDialog() {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { push } = useSecondaryPage()
const { relayList } = useNostr()
const [open, setOpen] = useState(false)
useEffect(() => {
const dismissed = storage.getDismissedTooManyRelaysAlert()
if (dismissed) return
if (relayList && (relayList.read.length > 4 || relayList.write.length > 4)) {
setOpen(true)
} else {
setOpen(false)
}
}, [relayList])
if (!relayList) return null
const handleFixNow = () => {
setOpen(false)
push(toRelaySettings('mailbox'))
}
const handleDismiss = () => {
storage.setDismissedTooManyRelaysAlert(true)
setOpen(false)
}
const handleMaybeLater = () => {
setOpen(false)
}
const title = t('Optimize Relay Settings')
const description = t(
'Your current relay configuration may not be optimal. This could make it difficult for others to find your posts and may result in incomplete notifications.'
)
if (isSmallScreen) {
return (
<Drawer open={open} onOpenChange={setOpen}>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>{title}</DrawerTitle>
<DrawerDescription>{description}</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button onClick={handleFixNow}>{t('Optimize Now')}</Button>
<Button variant="outline" onClick={handleMaybeLater}>
{t('Maybe Later')}
</Button>
<Button
onClick={handleDismiss}
variant="link"
className="text-muted-foreground text-xs"
>
{t("Don't remind me again")}
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{title}</AlertDialogTitle>
<AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<Button onClick={handleDismiss} variant="link" className="text-muted-foreground text-xs">
{t("Don't remind me again")}
</Button>
<Button variant="outline" onClick={handleMaybeLater}>
{t('Maybe Later')}
</Button>
<Button onClick={handleFixNow}>{t('Optimize Now')}</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}