diff --git a/src/App.tsx b/src/App.tsx index 69b878b..09bcfa5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,9 +27,16 @@ const defaultConfig: AppConfig = { relayUrl: "wss://relay.nostr.band", }; +const presetRelays = [ + { url: 'wss://ditto.pub/relay', name: 'Ditto' }, + { url: 'wss://relay.nostr.band', name: 'Nostr.Band' }, + { url: 'wss://relay.damus.io', name: 'Damus' }, + { url: 'wss://relay.primal.net', name: 'Primal' }, +]; + export function App() { return ( - + diff --git a/src/components/AppProvider.tsx b/src/components/AppProvider.tsx index eeb0703..d571e24 100644 --- a/src/components/AppProvider.tsx +++ b/src/components/AppProvider.tsx @@ -8,13 +8,16 @@ interface AppProviderProps { storageKey: string; /** Default app configuration */ defaultConfig: AppConfig; + /** Optional list of preset relays to display in the RelaySelector */ + presetRelays?: { name: string; url: string }[]; } export function AppProvider(props: AppProviderProps) { const { children, storageKey, - defaultConfig + defaultConfig, + presetRelays, } = props; // App configuration state with localStorage persistence @@ -28,6 +31,7 @@ export function AppProvider(props: AppProviderProps) { const appContextValue: AppContextType = { config, updateConfig, + presetRelays, }; // Apply theme effects to document diff --git a/src/components/NostrProvider.tsx b/src/components/NostrProvider.tsx index 1de8cbb..978d3fa 100644 --- a/src/components/NostrProvider.tsx +++ b/src/components/NostrProvider.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react'; import { NostrEvent, NPool, NRelay1 } from '@nostrify/nostrify'; import { NostrContext } from '@nostrify/react'; import { useQueryClient } from '@tanstack/react-query'; -import { useAppConfig } from '@/hooks/useAppConfig'; +import { useAppContext } from '@/hooks/useAppContext'; interface NostrProviderProps { children: React.ReactNode; @@ -10,7 +10,7 @@ interface NostrProviderProps { const NostrProvider: React.FC = (props) => { const { children } = props; - const { config } = useAppConfig(); + const { config } = useAppContext(); const queryClient = useQueryClient(); diff --git a/src/components/RelaySelector.tsx b/src/components/RelaySelector.tsx index 7ab4b2a..ae032ef 100644 --- a/src/components/RelaySelector.tsx +++ b/src/components/RelaySelector.tsx @@ -14,21 +14,22 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; -import { useAppConfig } from "@/hooks/useAppConfig"; import { useState } from "react"; interface RelaySelectorProps { className?: string; - availableRelays?: { name: string; url: string }[]; + selectedRelay?: string; + setSelectedRelay: (relay: string) => void; + presetRelays?: { name: string; url: string }[]; } -export function RelaySelector({ className, availableRelays = [] }: RelaySelectorProps) { - const { config, updateConfig } = useAppConfig(); +export function RelaySelector(props: RelaySelectorProps) { + const { selectedRelay, setSelectedRelay, className, presetRelays = [] } = props; const [open, setOpen] = useState(false); const [inputValue, setInputValue] = useState(""); - const selectedOption = availableRelays.find((option) => option.url === config.relayUrl); + const selectedOption = presetRelays.find((option) => option.url === selectedRelay); // Function to normalize relay URL by adding wss:// if no protocol is present const normalizeRelayUrl = (url: string): string => { @@ -46,12 +47,9 @@ export function RelaySelector({ className, availableRelays = [] }: RelaySelector // Handle adding a custom relay const handleAddCustomRelay = (url: string) => { - const normalizedUrl = normalizeRelayUrl(url); - if (normalizedUrl) { - updateConfig(config => ({ ...config, relayUrl: normalizedUrl })); - setOpen(false); - setInputValue(""); - } + setSelectedRelay?.(normalizeRelayUrl(url)); + setOpen(false); + setInputValue(""); }; // Check if input value looks like a valid relay URL @@ -83,8 +81,8 @@ export function RelaySelector({ className, availableRelays = [] }: RelaySelector {selectedOption ? selectedOption.name - : config.relayUrl - ? config.relayUrl.replace(/^wss?:\/\//, '') + : selectedRelay + ? selectedRelay.replace(/^wss?:\/\//, '') : "Select relay..." } @@ -121,7 +119,7 @@ export function RelaySelector({ className, availableRelays = [] }: RelaySelector )} - {availableRelays + {presetRelays .filter((option) => !inputValue || option.name.toLowerCase().includes(inputValue.toLowerCase()) || @@ -132,7 +130,7 @@ export function RelaySelector({ className, availableRelays = [] }: RelaySelector key={option.url} value={option.url} onSelect={(currentValue) => { - updateConfig(config => ({ ...config, relayUrl: currentValue })); + setSelectedRelay(normalizeRelayUrl(currentValue)); setOpen(false); setInputValue(""); }} @@ -140,7 +138,7 @@ export function RelaySelector({ className, availableRelays = [] }: RelaySelector
diff --git a/src/components/auth/AccountSwitcher.tsx b/src/components/auth/AccountSwitcher.tsx index 696ab2b..52aaef2 100644 --- a/src/components/auth/AccountSwitcher.tsx +++ b/src/components/auth/AccountSwitcher.tsx @@ -12,6 +12,7 @@ import { import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar.tsx'; import { RelaySelector } from '@/components/RelaySelector'; import { useLoggedInAccounts, type Account } from '@/hooks/useLoggedInAccounts'; +import { useAppContext } from '@/hooks/useAppContext'; import { genUserName } from '@/lib/genUserName'; interface AccountSwitcherProps { @@ -19,11 +20,14 @@ interface AccountSwitcherProps { } export function AccountSwitcher({ onAddAccountClick }: AccountSwitcherProps) { + const { config, updateConfig, presetRelays } = useAppContext(); const { currentUser, otherUsers, setLogin, removeLogin } = useLoggedInAccounts(); if (!currentUser) return null; - const getDisplayName = (account: Account): string => account.metadata.name ?? genUserName(account.pubkey); + const getDisplayName = (account: Account): string => { + return account.metadata.name ?? genUserName(account.pubkey); + } return ( @@ -41,7 +45,12 @@ export function AccountSwitcher({ onAddAccountClick }: AccountSwitcherProps) {
Switch Relay
- + updateConfig((config) => ({ ...config, relayUrl }))} + presetRelays={presetRelays} + />
Switch Account
{otherUsers.map((user) => ( diff --git a/src/contexts/AppContext.ts b/src/contexts/AppContext.ts index 383e52d..e6cfa26 100644 --- a/src/contexts/AppContext.ts +++ b/src/contexts/AppContext.ts @@ -14,6 +14,8 @@ export interface AppContextType { config: AppConfig; /** Update configuration using a callback that receives current config and returns new config */ updateConfig: (updater: (currentConfig: AppConfig) => AppConfig) => void; + /** Optional list of preset relays to display in the RelaySelector */ + presetRelays?: { name: string; url: string }[]; } export const AppContext = createContext(undefined); diff --git a/src/hooks/useAppConfig.ts b/src/hooks/useAppContext.ts similarity index 72% rename from src/hooks/useAppConfig.ts rename to src/hooks/useAppContext.ts index 221fc88..7554806 100644 --- a/src/hooks/useAppConfig.ts +++ b/src/hooks/useAppContext.ts @@ -5,10 +5,10 @@ import { AppContext, type AppContextType } from "@/contexts/AppContext"; * Hook to access and update application configuration * @returns Application context with config and update methods */ -export function useAppConfig(): AppContextType { +export function useAppContext(): AppContextType { const context = useContext(AppContext); if (context === undefined) { - throw new Error('useAppConfig must be used within an AppProvider'); + throw new Error('useAppContext must be used within an AppProvider'); } return context; } \ No newline at end of file diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index 320cdc2..24f7a5d 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,12 +1,12 @@ import { type Theme } from "@/contexts/AppContext"; -import { useAppConfig } from "@/hooks/useAppConfig"; +import { useAppContext } from "@/hooks/useAppContext"; /** * Hook to get and set the active theme * @returns Theme context with theme and setTheme */ export function useTheme(): { theme: Theme; setTheme: (theme: Theme) => void } { - const { config, updateConfig } = useAppConfig(); + const { config, updateConfig } = useAppContext(); return { theme: config.theme,