diff --git a/e2e/test-helpers.ts b/e2e/test-helpers.ts index a82577f..233d28f 100644 --- a/e2e/test-helpers.ts +++ b/e2e/test-helpers.ts @@ -134,7 +134,20 @@ export async function loginWithNsec(page: Page, nsec: string = TEST_NSEC) { await page.getByPlaceholder('nsec1...').fill(nsec); await page.getByRole('button', { name: 'Mit nsec anmelden' }).click(); + // Wait for auth avatar to become visible await expect(page.getByTestId('auth-user-avatar')).toBeVisible({ timeout: 10000 }); + + // CRITICAL: Wait for any dialogs and overlays to fully close + // The dialog should auto-close via $effect, but we need to wait for the animation + await page.waitForTimeout(1000); // Wait for close animation and any async work + + // Verify no overlays are blocking the UI + const dialogOverlay = page.locator('[data-dialog-overlay][data-state="open"]'); + const overlayCount = await dialogOverlay.count(); + if (overlayCount > 0) { + console.warn(`Warning: ${overlayCount} dialog overlay(s) still open after login, waiting longer...`); + await page.waitForTimeout(2000); + } } /** diff --git a/src/routes/cardsboard/LeftSidebarFooter.svelte b/src/routes/cardsboard/LeftSidebarFooter.svelte index 4483386..d6c36ff 100644 --- a/src/routes/cardsboard/LeftSidebarFooter.svelte +++ b/src/routes/cardsboard/LeftSidebarFooter.svelte @@ -16,6 +16,7 @@ import SettingsPanel from "$lib/components/settings/SettingsPanel.svelte"; import RelayStatusInfo from "./RelayStatusInfo.svelte"; import FAQDialog from "./FAQDialog.svelte"; + import PublicBoardsDialog from "./PublicBoardsDialog.svelte"; import LogInIcon from "@lucide/svelte/icons/log-in"; import LogOutIcon from "@lucide/svelte/icons/log-out"; import PlayIcon from "@lucide/svelte/icons/play"; @@ -28,6 +29,7 @@ import BookIcon from "@lucide/svelte/icons/book"; import InfoIcon from "@lucide/svelte/icons/info"; import HelpCircleIcon from "@lucide/svelte/icons/help-circle"; + import GlobeIcon from "@lucide/svelte/icons/globe"; import { ProfileEditor } from '$lib/components/auth/index.js'; @@ -46,6 +48,7 @@ let uiSettingsOpen = $state(false); let llmSettingsOpen = $state(false); let defaultsSettingsOpen = $state(false); + let publicBoardsDialogOpen = $state(false); let faqDialogOpen = $state(false); // Demo-Error Message @@ -154,6 +157,14 @@ Wissenswertes + publicBoardsDialogOpen = true} + class="gap-2 editor-menu-item" + > + + Öffentliche Boards + + window.open(settingsStore.settings.sourceCodeUrl, "_blank")} class="gap-2 editor-menu-item" @@ -248,6 +259,11 @@ + +{#if publicBoardsDialogOpen} + +{/if} + showProfileEditor = false} diff --git a/src/routes/cardsboard/LoginDialog.svelte b/src/routes/cardsboard/LoginDialog.svelte index b88d070..63477f5 100644 --- a/src/routes/cardsboard/LoginDialog.svelte +++ b/src/routes/cardsboard/LoginDialog.svelte @@ -19,6 +19,32 @@ let nsecInput = $state(''); let isLoading = $derived(authStore.isLoading); let errorMessage = $derived(authStore.errorMessage); + let isAuthenticated = $derived(authStore.isAuthenticated); + + // Track if dialog was open when auth was NOT active, then close after fresh auth // This prevents premature closing if user was already authenticated + let wasUnauthenticatedWhenOpened = $state(false); + + $effect(() => { + if (open && !isAuthenticated) { + wasUnauthenticatedWhenOpened = true; + } else if (!open) { + // Reset when dialog closes + wasUnauthenticatedWhenOpened = false; + } + }); + + // Auto-close after successful login (with small delay to avoid race conditions) + $effect(() => { + if (wasUnauthenticatedWhenOpened && isAuthenticated && open && !isLoading) { + // Small delay to ensure all UI updates complete before closing + setTimeout(() => { + console.log('[LoginDialog] Closing after successful auth'); + open = false; + nsecInput = ''; + wasUnauthenticatedWhenOpened = false; + }, 500); + } + }); // Browser detection let browserType = $state<'chrome' | 'firefox' | 'safari' | 'edge' | 'opera' | 'brave' | 'unknown'>('unknown'); diff --git a/src/routes/cardsboard/PublicBoardsDialog.svelte b/src/routes/cardsboard/PublicBoardsDialog.svelte new file mode 100644 index 0000000..6f41680 --- /dev/null +++ b/src/routes/cardsboard/PublicBoardsDialog.svelte @@ -0,0 +1,428 @@ + + + + + + + + Öffentliche Boards + {#if allBoards.length > 0} + + {displayedBoards.length} / {allBoards.length} + + {/if} + + + Entdecke veröffentlichte Boards aus dem Nostr-Netzwerk + {#if !isLoading} + + {/if} + + + +
+ {#if isLoading} + +
+
+

Suche nach veröffentlichten Boards...

+
+ {#each Array(3) as _} +
+ + +
+ + +
+
+ {/each} +
+ {:else if error} + +
+
Fehler beim Laden der Boards
+

{error}

+

+ Bitte überprüfe deine Relay-Verbindungen in den Einstellungen. +

+ +
+ {:else if allBoards.length === 0} + +
+ +

Keine öffentlichen Boards gefunden

+

+ Es sind derzeit keine veröffentlichten Boards in den Relays verfügbar. +

+ +
+ {:else} + +
+
+ {#each displayedBoards as board (`${board.author}-${board.id}`)} + + + + {board.name} + + {#if board.description} + + {board.description} + + {/if} + + + + +
+ + {formatPubkey(board.author || "")} +
+ + +
+ + {board.columns?.length || 0} Spalten +
+ + + {#if board.createdAt} +
+ + {formatDate(board.createdAt)} +
+ {/if} + + + {#if board.tags && board.tags.length > 0} +
+ +
+ {#each board.tags.slice(0, 3) as tag} + + {tag} + + {/each} + {#if board.tags.length > 3} + + +{board.tags.length - 3} + + {/if} +
+
+ {/if} +
+ + + + +
+ {/each} +
+ + + {#if displayedBoards.length < allBoards.length} +
+ +
+ {/if} +
+ {/if} +
+ + + + +
+