import { useSeoMeta } from '@unhead/react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Smartphone, Shield, ExternalLink, Star, CheckCircle2, Info, Apple, Chrome } from 'lucide-react'; import { useTranslation } from '@/contexts/language'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useNostrLogin } from '@nostrify/react/login'; import { isInteractiveSigner } from '@/lib/signerCapabilities'; // Platform detection const isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent); const isIOS = typeof navigator !== 'undefined' && /iPhone|iPad|iPod/i.test(navigator.userAgent); const isMobile = isAndroid || isIOS; interface SignerApp { name: string; description: string; features: string[]; url: string; recommended?: boolean; platforms: ('android' | 'ios' | 'web' | 'desktop')[]; protocol?: string; } const androidSigners: SignerApp[] = [ { name: 'Amber', description: 'settingsUi.signers.amberDesc', features: ['settingsUi.signers.fNativeApp', 'settingsUi.signers.fMultiKey', 'settingsUi.signers.fEventSigning', 'settingsUi.signers.fSecureStorage'], url: 'https://github.com/greenart7c3/Amber', recommended: true, platforms: ['android'], protocol: 'NIP-55', }, { name: 'Nsec.app', description: 'settingsUi.signers.nsecAppDesc', features: ['settingsUi.signers.fRemoteSigning', 'settingsUi.signers.fAnyClient', 'settingsUi.signers.fCrossDevice'], url: 'https://nsec.app', platforms: ['android', 'ios', 'web'], protocol: 'NIP-46', }, { name: 'Nostria Signer', description: 'settingsUi.signers.nostriaDesc', features: ['settingsUi.signers.fSecureStorage', 'settingsUi.signers.fRemoteSigning', 'settingsUi.signers.fMultiKeySupport'], url: 'https://nostria.app', platforms: ['android', 'ios'], protocol: 'NIP-46', }, { name: 'Nowser', description: 'settingsUi.signers.nowserDesc', features: ['settingsUi.signers.fNip07', 'settingsUi.signers.fNip46', 'settingsUi.signers.fFlexibleSigning'], url: 'https://nowser.app', platforms: ['android', 'ios'], protocol: 'NIP-07 / NIP-46', }, ]; const iosSigners: SignerApp[] = [ { name: 'Nsec.app', description: 'settingsUi.signers.nsecAppIosDesc', features: ['settingsUi.signers.fRemoteSigning', 'settingsUi.signers.fAnyClient', 'settingsUi.signers.fCrossDevice'], url: 'https://nsec.app', recommended: true, platforms: ['android', 'ios', 'web'], protocol: 'NIP-46', }, { name: 'Nowser (TestFlight)', description: 'settingsUi.signers.nowserTfDesc', features: ['settingsUi.signers.fNip07', 'settingsUi.signers.fNip46', 'settingsUi.signers.fNativeIos'], url: 'https://testflight.apple.com/join/nowser', platforms: ['ios'], protocol: 'NIP-07 / NIP-46', }, { name: 'Nostria Signer', description: 'settingsUi.signers.nostriaIosDesc', features: ['settingsUi.signers.fSecureStorage', 'settingsUi.signers.fRemoteSigning', 'settingsUi.signers.fMultiKeySupport'], url: 'https://nostria.app', platforms: ['android', 'ios'], protocol: 'NIP-46', }, ]; const browserSigners: SignerApp[] = [ { name: 'nos2x', description: 'settingsUi.signers.nos2xDesc', features: ['settingsUi.signers.fLightweight', 'settingsUi.signers.fEasyToUse', 'settingsUi.signers.fChromeSupport'], url: 'https://chrome.google.com/webstore/detail/nos2x/kpgefcfmnafjgpblomihpgmejjdanjjp', recommended: true, platforms: ['web'], protocol: 'NIP-07', }, { name: 'Alby', description: 'settingsUi.signers.albyDesc', features: ['settingsUi.signers.fLightningPayments', 'settingsUi.signers.fNostrSigning', 'settingsUi.signers.fWebln', 'settingsUi.signers.fNwc'], url: 'https://getalby.com', platforms: ['web', 'desktop'], protocol: 'NIP-07', }, { name: 'Flamingo', description: 'settingsUi.signers.flamingoDesc', features: ['settingsUi.signers.fNostrSigning', 'settingsUi.signers.fCleanUi', 'settingsUi.signers.fPrivacyFocused'], url: 'https://www.flamingowallet.com', platforms: ['web'], protocol: 'NIP-07', }, { name: 'Kiwi Browser + Extension', description: 'settingsUi.signers.kiwiDesc', features: ['settingsUi.signers.fExtensionMobile', 'settingsUi.signers.fFullBrowser', 'settingsUi.signers.fGraphene'], url: 'https://kiwibrowser.com', platforms: ['android'], protocol: 'NIP-07', }, ]; function SignerCard({ signer }: { signer: SignerApp }) { const { t } = useTranslation(); return (
{signer.name} {signer.recommended && ( {t('settingsUi.signers.recommended')} )} {signer.protocol && ( {signer.protocol} )}
{t(signer.description)}
{signer.features.map((feature) => ( {t(feature)} ))}
); } function PlatformSection({ icon: Icon, title, description, signers, highlighted, }: { icon: React.ComponentType<{ className?: string }>; title: string; description: string; signers: SignerApp[]; highlighted?: boolean; }) { const { t } = useTranslation(); return (

{title}

{highlighted && ( {t('settingsUi.signers.yourPlatform')} )}

{description}

{signers.map((signer) => ( ))}
); } export default function SignersPage() { const { t } = useTranslation(); const { user } = useCurrentUser(); const { logins } = useNostrLogin(); const amber = isInteractiveSigner(user, logins); useSeoMeta({ title: t('settingsUi.signers.seoTitle'), description: t('settingsUi.signers.seoDescription'), }); // Determine platform order - show user's platform first const platformOrder = isAndroid ? ['android', 'ios', 'browser'] as const : isIOS ? ['ios', 'android', 'browser'] as const : ['browser', 'android', 'ios'] as const; return ( <>
{/* Hero Section */}
{t('settingsUi.signers.securityGuide')}

{t('settingsUi.signers.protect')}{' '} {t('settingsUi.signers.nostrKeys')}

{t('settingsUi.signers.heroDesc')}

{t('settingsUi.signers.whySignerStrong')} {t('settingsUi.signers.whySigner')} {amber && ( {t('signerPromptUi.title')} {t('signerPromptUi.body')} {t('signerPromptUi.bunker')} )}
{/* Signer Sections */}
{platformOrder.map((platform, index) => { if (platform === 'android') { return ( ); } if (platform === 'ios') { return ( ); } return ( ); })} {/* Protocol Info */}

{t('settingsUi.signers.protocolsTitle')}

NIP-07 {t('settingsUi.signers.nip07Desc')} NIP-46 {t('settingsUi.signers.nip46Desc')} NIP-55 {t('settingsUi.signers.nip55Desc')} {t('settingsUi.signers.whichChoose')} {t('settingsUi.signers.chooseAndroid')} {t('settingsUi.signers.chooseAndroidDesc')}
{t('settingsUi.signers.chooseIos')} {t('settingsUi.signers.chooseIosDesc')}
{t('settingsUi.signers.chooseDesktop')} {t('settingsUi.signers.chooseDesktopDesc')}
); }