diff --git a/src/App.tsx b/src/App.tsx index 1eba0c7..77b8bde 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -42,6 +42,7 @@ const defaultConfig: AppConfig = { ], updatedAt: 0, }, + preferMinimalCards: false, }; export function App() { diff --git a/src/components/AppProvider.tsx b/src/components/AppProvider.tsx index 8b72567..5c6df7c 100644 --- a/src/components/AppProvider.tsx +++ b/src/components/AppProvider.tsx @@ -25,6 +25,7 @@ const RelayMetadataSchema = z.object({ const AppConfigSchema = z.object({ theme: z.enum(['dark', 'light', 'system']), relayMetadata: RelayMetadataSchema, + preferMinimalCards: z.boolean(), }) satisfies z.ZodType; export function AppProvider(props: AppProviderProps) { diff --git a/src/contexts/AppContext.ts b/src/contexts/AppContext.ts index 6af4057..1db4ccf 100644 --- a/src/contexts/AppContext.ts +++ b/src/contexts/AppContext.ts @@ -14,6 +14,8 @@ export interface AppConfig { theme: Theme; /** NIP-65 relay list metadata */ relayMetadata: RelayMetadata; + /** Prefer minimal picture cards in the feed */ + preferMinimalCards: boolean; } export interface AppContextType { diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index b58b340..8f504f8 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -2,10 +2,12 @@ import { useSeoMeta } from '@unhead/react'; import { Layout } from '@/components/Layout'; import { usePictureFeed } from '@/hooks/usePictureFeed'; import { PictureCard } from '@/components/feed/PictureCard'; +import { MinimalPictureCard } from '@/components/feed/MinimalPictureCard'; import { useInView } from 'react-intersection-observer'; import { useEffect, useMemo } from 'react'; import { Skeleton } from '@/components/ui/skeleton'; import { Card, CardContent } from '@/components/ui/card'; +import { useAppContext } from '@/hooks/useAppContext'; const Index = () => { useSeoMeta({ @@ -13,6 +15,7 @@ const Index = () => { description: 'Discover amazing pictures shared on Nostr.', }); + const { config } = useAppContext(); const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = usePictureFeed(); const { ref, inView } = useInView(); @@ -72,7 +75,11 @@ const Index = () => { // Picture feed <> {pictures.map((picture) => ( - + config.preferMinimalCards ? ( + + ) : ( + + ) ))} {/* Infinite scroll trigger */} diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index f3431a2..1c14bfb 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -5,10 +5,12 @@ import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { RelayListManager } from '@/components/RelayListManager'; import { useTheme } from '@/hooks/useTheme'; -import { Moon, Sun } from 'lucide-react'; +import { useAppContext } from '@/hooks/useAppContext'; +import { Moon, Sun, LayoutGrid } from 'lucide-react'; export function Settings() { const { theme, setTheme } = useTheme(); + const { config, updateConfig } = useAppContext(); useSeoMeta({ title: 'Settings - Lumina', @@ -33,7 +35,7 @@ export function Settings() { Customize how the app looks and feels - +
{theme === 'light' ? ( @@ -56,6 +58,27 @@ export function Settings() { onCheckedChange={(checked) => setTheme(checked ? 'dark' : 'light')} />
+ +
+
+ +
+ +

+ Show compact picture-only cards in feed +

+
+
+ + updateConfig((current) => ({ ...current, preferMinimalCards: checked })) + } + /> +
diff --git a/src/test/TestApp.tsx b/src/test/TestApp.tsx index 3b2d4b9..bb993ec 100644 --- a/src/test/TestApp.tsx +++ b/src/test/TestApp.tsx @@ -29,6 +29,7 @@ export function TestApp({ children }: TestAppProps) { ], updatedAt: 0, }, + preferMinimalCards: false, }; return (