From 0d53bf23663c8547843f2b2b3be2f3437037c02e Mon Sep 17 00:00:00 2001 From: Silberengel Date: Mon, 2 Mar 2026 10:45:04 +0100 Subject: [PATCH] Bug-fixes Nostr-Signature: f0bc6f3d6edde211b36392f9752275efe6853f3c3f8eb26a08c8fe2017974bcd 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc 8545518302ccc35759cb10dcc2b24c6fc93389bfdb88c2a691e681fafcd06802cc702a1f3d784f404075c41c737cb001e1aa422a72d42eb3e4b6f341afe96c27 --- nostr/commit-signatures.jsonl | 1 + src/routes/admin/repos/+page.svelte | 53 ++++- src/routes/repos/+page.svelte | 38 +++- src/routes/repos/[npub]/[repo]/+page.ts | 188 +++++++++++++----- .../[npub]/[repo]/hooks/use-repo-effects.ts | 48 ++++- .../[repo]/read-announcement-from-fs.ts | 27 ++- src/routes/signup/+page.svelte | 19 +- 7 files changed, 301 insertions(+), 73 deletions(-) diff --git a/nostr/commit-signatures.jsonl b/nostr/commit-signatures.jsonl index ddd062b..baba18b 100644 --- a/nostr/commit-signatures.jsonl +++ b/nostr/commit-signatures.jsonl @@ -131,3 +131,4 @@ {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772303976,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fix"]],"content":"Signed commit: bug-fix","id":"a8e7a4f38f815abaa8cc807e43da842cc4715ff41e722ee6657cae57915b753e","sig":"9c427e839796099f8fdfc0dc4a6f4500ecb1835dbf62cf0b1d3dbe8f98c98a1bc7b28266cbc7a993a18f905ec6e57c610e10492c88e7f863319cefb2eab58fdc"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772305338,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","allow forks"]],"content":"Signed commit: allow forks","id":"47f1aa9a47f4488a9babf752466bb2e4cb7974bd67aa827a4b70c57bac839750","sig":"3652f31ee120f894f7dbb04bb2e625dc2f97758b9fe99fa24aa0efe23872851aceb6f460d2c479bbfc9aa495b5c6d993b2ec7d65e21c90ee8ca6a9f23bfac498"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772305971,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","correct search page"]],"content":"Signed commit: correct search page","id":"2a93ec13a9ae177dfd3f4b59cfc7341e9a3a073367b43976ea161802efc76c44","sig":"7821315a6b3b5761c8938fd9b247db0f3344336fbf706b1fb5921ee5645b0f77298cb41a96cd5d1afa8e05c25eb7d64d69d42de585cdd016ad1425ca5b1f4772"} +{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772312712,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"e4db3dfc316a2ae2edebbe25fef26a917710b9066df4ee168f83f3342359cdb5","sig":"a3f3ab6208ef1438778ffb399fdb40e0d8317812987e1360f896b106ab2a948b2d9878d23033c8d3c2a4fe70c5f2fa215ed81962162d94c1ec79767d5a4ebca5"} diff --git a/src/routes/admin/repos/+page.svelte b/src/routes/admin/repos/+page.svelte index 00187fb..ccfcbfc 100644 --- a/src/routes/admin/repos/+page.svelte +++ b/src/routes/admin/repos/+page.svelte @@ -2,6 +2,7 @@ import { onMount } from 'svelte'; import { goto } from '$app/navigation'; import { userStore } from '$lib/stores/user-store.js'; + import type { NostrEvent } from '$lib/types/nostr.js'; interface AdminRepo { npub: string; @@ -10,6 +11,7 @@ size: number; lastModified: number; createdAt: number; + announcement?: NostrEvent | null; } let repos = $state([]); @@ -160,6 +162,39 @@ function formatDate(timestamp: number): string { return new Date(timestamp).toLocaleString(); } + + // Helper function to navigate to a repo with announcement in sessionStorage + async function navigateToRepo(npub: string, repoName: string, announcement?: NostrEvent | null) { + // If we have the announcement, store it in sessionStorage + if (announcement && typeof window !== 'undefined') { + const repoKey = `${npub}/${repoName}`; + try { + sessionStorage.setItem(`repo_announcement_${repoKey}`, JSON.stringify(announcement)); + console.log(`[Admin] Stored announcement in sessionStorage for ${repoKey}`); + } catch (err) { + console.warn('[Admin] Failed to store announcement in sessionStorage:', err); + } + } else { + // Try to fetch announcement from API + try { + const response = await fetch(`/api/repos/local?domain=${encodeURIComponent(window.location.hostname)}`); + if (response.ok) { + const data = await response.json(); + const repo = data.find((r: { npub: string; repoName: string; announcement: NostrEvent | null }) => + r.npub === npub && r.repoName === repoName + ); + if (repo?.announcement) { + const repoKey = `${npub}/${repoName}`; + sessionStorage.setItem(`repo_announcement_${repoKey}`, JSON.stringify(repo.announcement)); + console.log(`[Admin] Fetched and stored announcement from API for ${repoKey}`); + } + } + } catch (err) { + console.warn('[Admin] Failed to fetch announcement from API:', err); + } + } + goto(`/repos/${npub}/${repoName}`); + } @@ -218,9 +253,13 @@ {repo.npub.substring(0, 20)}... - + {formatBytes(repo.size)} {formatDate(repo.lastModified)} @@ -378,13 +417,19 @@ border: 1px solid var(--border-color); } - .repo-name-cell a { + .repo-link-button { + background: none; + border: none; color: var(--link-color); text-decoration: none; font-weight: 500; + cursor: pointer; + padding: 0; + font-size: inherit; + font-family: inherit; } - .repo-name-cell a:hover { + .repo-link-button:hover { color: var(--link-hover); text-decoration: underline; } diff --git a/src/routes/repos/+page.svelte b/src/routes/repos/+page.svelte index 033c8bf..676d874 100644 --- a/src/routes/repos/+page.svelte +++ b/src/routes/repos/+page.svelte @@ -46,6 +46,20 @@ const nostrClient = new NostrClient(DEFAULT_NOSTR_RELAYS); + // Helper function to navigate to a repo with announcement in sessionStorage + function navigateToRepo(npub: string, repoName: string, announcement: NostrEvent | null) { + if (announcement && typeof window !== 'undefined') { + const repoKey = `${npub}/${repoName}`; + try { + sessionStorage.setItem(`repo_announcement_${repoKey}`, JSON.stringify(announcement)); + console.log(`[Repos Page] Stored announcement in sessionStorage for ${repoKey}`); + } catch (err) { + console.warn('[Repos Page] Failed to store announcement in sessionStorage:', err); + } + } + goto(`/repos/${npub}/${repoName}`); + } + onMount(async () => { await loadRepos(); await loadUserAndContacts(); @@ -719,9 +733,13 @@

{getRepoDescription(repo)}

{/if} - +
Created: {new Date(repo.created_at * 1000).toLocaleDateString()} @@ -772,9 +790,13 @@

{getRepoDescription(repo)}

{/if}
- +
Created: {new Date(repo.created_at * 1000).toLocaleDateString()} @@ -856,9 +878,13 @@

{getRepoDescription(repo)}

{/if}
- +
Created: {new Date(repo.created_at * 1000).toLocaleDateString()} diff --git a/src/routes/repos/[npub]/[repo]/+page.ts b/src/routes/repos/[npub]/[repo]/+page.ts index dc2d6fa..863784a 100644 --- a/src/routes/repos/[npub]/[repo]/+page.ts +++ b/src/routes/repos/[npub]/[repo]/+page.ts @@ -35,81 +35,163 @@ export const load: PageLoad = async ({ params, url, parent }) => { // Check if announcement was passed from search results via sessionStorage let announcement: NostrEvent | null = null; + let foundInSessionStorage = false; if (typeof window !== 'undefined') { const repoKey = `${npub}/${repo}`; const storedAnnouncement = sessionStorage.getItem(`repo_announcement_${repoKey}`); if (storedAnnouncement) { try { announcement = JSON.parse(storedAnnouncement); - // Clean up after using it - sessionStorage.removeItem(`repo_announcement_${repoKey}`); - } catch { + foundInSessionStorage = true; + console.log(`[Page Load] Found announcement in sessionStorage for ${npub}/${repo}`, { eventId: announcement?.id }); + // Don't remove it yet - keep it as fallback if server-side load fails + } catch (err) { + console.warn(`[Page Load] Failed to parse announcement from sessionStorage:`, err); // Invalid JSON, continue to fetch } + } else { + console.log(`[Page Load] No announcement in sessionStorage for ${npub}/${repo}`); } } // If not found in sessionStorage, fetch from Nostr (case-insensitive) if (!announcement) { - const nostrClient = new NostrClient(DEFAULT_NOSTR_RELAYS); - // Fetch all announcements by this author and filter case-insensitively - const allEvents = await nostrClient.fetchEvents([ - { - kinds: [KIND.REPO_ANNOUNCEMENT], - authors: [repoOwnerPubkey], - limit: 100 - } - ]); + try { + const nostrClient = new NostrClient(DEFAULT_NOSTR_RELAYS); + // Fetch all announcements by this author and filter case-insensitively + const allEvents = await nostrClient.fetchEvents([ + { + kinds: [KIND.REPO_ANNOUNCEMENT], + authors: [repoOwnerPubkey], + limit: 100 + } + ]); - // Filter case-insensitively to find the matching repo - const repoLower = repo.toLowerCase(); - const matchingEvents = allEvents.filter(event => { - const dTag = event.tags.find(t => t[0] === 'd')?.[1]; - return dTag && dTag.toLowerCase() === repoLower; - }); + // Filter case-insensitively to find the matching repo + const repoLower = repo.toLowerCase(); + const matchingEvents = allEvents.filter(event => { + const dTag = event.tags.find(t => t[0] === 'd')?.[1]; + return dTag && dTag.toLowerCase() === repoLower; + }); - if (matchingEvents.length === 0) { - // Not found in Nostr relays - try reading from filesystem (server-side only) - // This is important for private forks that weren't published to relays - // Only attempt on server-side using SvelteKit's SSR flag - if (import.meta.env.SSR) { - try { - // Dynamic import to prevent client-side bundling - const fsModule = await import('./read-announcement-from-fs.js'); - const announcementFromRepo = await fsModule.readAnnouncementFromFilesystem(npub, repo, repoOwnerPubkey); - if (announcementFromRepo) { - announcement = announcementFromRepo; + if (matchingEvents.length === 0) { + // Not found in Nostr relays - try reading from filesystem (server-side only) + // This is important for private forks that weren't published to relays + // Only attempt on server-side using SvelteKit's SSR flag + if (import.meta.env.SSR) { + // Retry filesystem read with exponential backoff (commit might still be in progress) + let retries = 3; + let delay = 500; // Start with 500ms delay + while (retries > 0 && !announcement) { + try { + // Dynamic import to prevent client-side bundling + // Wrap in additional try-catch to handle import errors gracefully + try { + const fsModule = await import('./read-announcement-from-fs.js'); + if (fsModule && typeof fsModule.readAnnouncementFromFilesystem === 'function') { + console.log(`[Page Load] Attempting to read announcement from filesystem for ${npub}/${repo} (${4 - retries}/3)`); + const announcementFromRepo = await fsModule.readAnnouncementFromFilesystem(npub, repo, repoOwnerPubkey); + if (announcementFromRepo) { + console.log(`[Page Load] Successfully read announcement from filesystem for ${npub}/${repo}`); + announcement = announcementFromRepo; + break; // Success, exit retry loop + } else { + console.log(`[Page Load] Announcement not found in filesystem for ${npub}/${repo}, retrying...`); + } + } else { + console.warn(`[Page Load] readAnnouncementFromFilesystem function not found in module`); + break; // Don't retry if function doesn't exist + } + } catch (importError) { + // Handle import errors (e.g., Vite SSR circular dependency issues) + // Don't retry on import errors - they won't be fixed by waiting + console.error('[Page Load] Failed to import readAnnouncementFromFilesystem (Vite SSR issue):', importError); + break; // Exit retry loop on import errors + } + } catch (err) { + // If filesystem read fails, log and retry + console.error(`[Page Load] Failed to read announcement from filesystem (attempt ${4 - retries}/3):`, err); + } + + if (!announcement && retries > 1) { + // Wait before retrying (exponential backoff) + await new Promise(resolve => setTimeout(resolve, delay)); + delay *= 2; // Double the delay for next retry + } + retries--; } - } catch (err) { - // If filesystem read fails, log on server-side but continue - // This is expected on client-side, so we silently continue - console.debug('Failed to read announcement from filesystem:', err); + } else { + // Client-side: log that we're skipping filesystem read + console.debug(`[Page Load] Skipping filesystem read (client-side) for ${npub}/${repo}`); } + } else { + announcement = matchingEvents[0]; } - - if (!announcement) { - return { - title: `${repo} - Repository Not Found`, - description: 'Repository announcement not found', - announcement: null, // Explicitly set to null so component knows it's missing - repoNotFound: true // Flag to indicate repo not found - }; + } catch (nostrError) { + // If Nostr fetch fails, log but continue - we might have it in sessionStorage or filesystem + console.error('[Page Load] Failed to fetch from Nostr relays:', nostrError); + } + } + + // Clean up sessionStorage only if we successfully loaded from Nostr (public repos) + // For private repos loaded from filesystem or sessionStorage, keep it for client-side navigation + if (foundInSessionStorage && announcement && typeof window !== 'undefined') { + // Check if we loaded from Nostr (not from sessionStorage or filesystem) + // If the announcement came from Nostr, it means it's public and we don't need sessionStorage + const repoKey = `${npub}/${repo}`; + const stillInStorage = sessionStorage.getItem(`repo_announcement_${repoKey}`); + + // Only remove if we have the announcement AND it's not from sessionStorage (meaning we got it from Nostr) + // This is a bit tricky: if foundInSessionStorage is true, we used sessionStorage, so don't remove it + // We only want to remove if we found it in Nostr AFTER checking sessionStorage + if (stillInStorage && !foundInSessionStorage) { + // This shouldn't happen, but if it does, it means we loaded from Nostr + sessionStorage.removeItem(`repo_announcement_${repoKey}`); + console.log(`[Page Load] Removed announcement from sessionStorage (loaded from Nostr)`); + } else if (foundInSessionStorage) { + // Keep sessionStorage - we're using it and client-side can't read filesystem + console.log(`[Page Load] Keeping announcement in sessionStorage (using it as source)`); + } + } + + // If still no announcement found, check sessionStorage one more time (client-side fallback) + if (!announcement && !import.meta.env.SSR && typeof window !== 'undefined') { + const repoKey = `${npub}/${repo}`; + const lastChanceAnnouncement = sessionStorage.getItem(`repo_announcement_${repoKey}`); + if (lastChanceAnnouncement) { + try { + announcement = JSON.parse(lastChanceAnnouncement); + console.log(`[Page Load] Found announcement in sessionStorage on final check (client-side)`); + } catch { + // Invalid JSON } - } else { - announcement = matchingEvents[0]; } } - // Ensure announcement exists before proceeding + // If still no announcement found, don't immediately return "not found" + // The repo might exist but announcement not found yet (e.g., private fork being committed) + // Let the component check if repo exists via API before showing "not found" if (!announcement) { + console.warn(`[Page Load] Announcement not found for ${npub}/${repo} after all attempts`, { + foundInSessionStorage, + isSSR: import.meta.env.SSR, + hasWindow: typeof window !== 'undefined' + }); + // Return announcement as null but don't set repoNotFound - let component verify repo exists return { - title: `${repo} - Repository Not Found`, - description: 'Repository announcement not found', - announcement: null, - repoNotFound: true + title: `${repo} - Repository`, + description: 'Repository', + announcement: null, // Explicitly set to null so component knows it's missing + repoNotFound: false // Don't assume repo doesn't exist - component will check }; } + console.log(`[Page Load] Successfully loaded announcement for ${npub}/${repo}`, { + eventId: announcement.id, + foundInSessionStorage, + isSSR: import.meta.env.SSR + }); + // Check privacy - for private repos, we'll let the API endpoints handle access control // The page load function runs server-side but doesn't have access to client auth headers // So we'll mark it as private and let the frontend handle access denial @@ -130,8 +212,14 @@ export const load: PageLoad = async ({ params, url, parent }) => { const banner = announcement.tags.find((t: string[]) => t[0] === 'banner')?.[1]; // Get git domain for constructing URLs - const layoutData = await parent(); - const gitDomain = (layoutData as { gitDomain?: string }).gitDomain || url.host || 'localhost:6543'; + let gitDomain = url.host || 'localhost:6543'; + try { + const layoutData = await parent(); + gitDomain = (layoutData as { gitDomain?: string }).gitDomain || gitDomain; + } catch (parentError) { + // If parent() fails (e.g., due to SSR issues), use fallback + console.debug('Failed to get layout data, using fallback:', parentError); + } const protocol = gitDomain.startsWith('localhost') ? 'http' : 'https'; const repoUrl = `${protocol}://${gitDomain}/repos/${npub}/${repo}`; diff --git a/src/routes/repos/[npub]/[repo]/hooks/use-repo-effects.ts b/src/routes/repos/[npub]/[repo]/hooks/use-repo-effects.ts index ec51c15..71752c1 100644 --- a/src/routes/repos/[npub]/[repo]/hooks/use-repo-effects.ts +++ b/src/routes/repos/[npub]/[repo]/hooks/use-repo-effects.ts @@ -20,21 +20,55 @@ export function usePageDataEffect(state: RepoState, getPageData: () => any): () const data = getPageData(); if (data && state.isMounted) { state.pageData = data || {}; - // Set repoNotFound flag if announcement is missing or repoNotFound is explicitly set - if (data.repoNotFound === true || (data.announcement === null || data.announcement === undefined)) { - state.repoNotFound = true; - state.loading.main = false; + + // Only set repoNotFound if explicitly set to true AND we've verified the repo doesn't exist + // Don't set it just because announcement is null - the repo might exist but announcement not found yet + if (data.repoNotFound === true) { + // Check if repo actually exists by trying to verify via API + // If repo exists (e.g., branches endpoint returns 200), don't show "not found" + fetch(`/api/repos/${state.npub}/${state.repo}/branches?skipApiFallback=true`) + .then(response => { + if (state.isMounted) { + if (response.ok || response.status === 200) { + // Repo exists! Clear repoNotFound even if announcement is missing + console.log(`[Page Data Effect] Repo exists (status ${response.status}), clearing repoNotFound flag`); + state.repoNotFound = false; + } else if (response.status === 404) { + // Repo truly doesn't exist + console.log(`[Page Data Effect] Repo doesn't exist (status 404), setting repoNotFound`); + state.repoNotFound = true; + state.loading.main = false; + } else { + // Other error - don't assume repo doesn't exist + console.log(`[Page Data Effect] Repo check returned status ${response.status}, keeping current state`); + } + } + }) + .catch(err => { + if (state.isMounted) { + console.warn('[Page Data Effect] Failed to verify repo existence:', err); + // On error checking, if repoNotFound was explicitly set, keep it + // Otherwise, don't assume repo doesn't exist + if (data.repoNotFound === true) { + state.repoNotFound = true; + state.loading.main = false; + } + } + }); } else if (data.announcement) { // Clear repoNotFound if we have a valid announcement state.repoNotFound = false; + } else { + // Announcement is null but repoNotFound wasn't explicitly set + // Don't set repoNotFound - let the component try to load the repo anyway + // The repo might exist but announcement not found yet (e.g., private fork) + console.log('[Page Data Effect] Announcement is null but repoNotFound not explicitly set - allowing page to load'); } } } catch (err) { if (state.isMounted) { console.warn('Failed to update pageData:', err); - // On error, mark as not found to prevent blank page - state.repoNotFound = true; - state.loading.main = false; + // On error, don't automatically mark as not found - might be a transient error } } }; diff --git a/src/routes/repos/[npub]/[repo]/read-announcement-from-fs.ts b/src/routes/repos/[npub]/[repo]/read-announcement-from-fs.ts index 014f1cf..11bd46e 100644 --- a/src/routes/repos/[npub]/[repo]/read-announcement-from-fs.ts +++ b/src/routes/repos/[npub]/[repo]/read-announcement-from-fs.ts @@ -30,29 +30,46 @@ export async function readAnnouncementFromFilesystem(npub: string, repoName: str try { const repoPath = join(repoRoot, npub, `${repoName}.git`); + logger.debug({ npub, repoName, repoPath }, '[readAnnouncementFromFilesystem] Checking repo path'); + if (!existsSync(repoPath)) { + logger.debug({ npub, repoName, repoPath }, '[readAnnouncementFromFilesystem] Repo path does not exist'); return null; } + logger.debug({ npub, repoName }, '[readAnnouncementFromFilesystem] Repo exists, reading git log'); const git = simpleGit(repoPath); // Get the most recent commit that modified repo-events.jsonl - const logOutput = await git.raw(['log', '--all', '--format=%H', '--reverse', '--', 'nostr/repo-events.jsonl']).catch(() => ''); + const logOutput = await git.raw(['log', '--all', '--format=%H', '--reverse', '--', 'nostr/repo-events.jsonl']).catch((err) => { + logger.debug({ npub, repoName, error: err }, '[readAnnouncementFromFilesystem] Failed to get git log'); + return ''; + }); const commitHashes = logOutput.trim().split('\n').filter(Boolean); + logger.debug({ npub, repoName, commitCount: commitHashes.length }, '[readAnnouncementFromFilesystem] Found commits'); + if (commitHashes.length === 0) { + logger.debug({ npub, repoName }, '[readAnnouncementFromFilesystem] No commits found for repo-events.jsonl'); return null; } const mostRecentCommit = commitHashes[commitHashes.length - 1]; + logger.debug({ npub, repoName, commit: mostRecentCommit }, '[readAnnouncementFromFilesystem] Using most recent commit'); // Read the file content from git - const fileContent = await git.show([`${mostRecentCommit}:nostr/repo-events.jsonl`]).catch(() => null); + const fileContent = await git.show([`${mostRecentCommit}:nostr/repo-events.jsonl`]).catch((err) => { + logger.debug({ npub, repoName, commit: mostRecentCommit, error: err }, '[readAnnouncementFromFilesystem] Failed to read file from git'); + return null; + }); if (!fileContent) { + logger.debug({ npub, repoName }, '[readAnnouncementFromFilesystem] File content is empty'); return null; } + logger.debug({ npub, repoName, contentLength: fileContent.length }, '[readAnnouncementFromFilesystem] File content read successfully'); + // Parse repo-events.jsonl to find the most recent announcement let announcementEvent: NostrEvent | null = null; let latestTimestamp = 0; @@ -90,17 +107,19 @@ export async function readAnnouncementFromFilesystem(npub: string, repoName: str // Check if d-tag matches repo name (case-insensitive) if (!dTag || dTag.toLowerCase() !== repoName.toLowerCase()) { - logger.debug({ npub, repoName, dTag }, 'Announcement d-tag does not match repo name (case-insensitive)'); + logger.debug({ npub, repoName, dTag, expectedRepoName: repoName.toLowerCase(), actualDTag: dTag?.toLowerCase() }, '[readAnnouncementFromFilesystem] Announcement d-tag does not match repo name (case-insensitive)'); return null; } + logger.debug({ npub, repoName, dTag }, '[readAnnouncementFromFilesystem] d-tag matches, validating announcement'); const validation = validateAnnouncementEvent(announcementEvent, repoName); if (!validation.valid) { - logger.debug({ error: validation.error, npub, repoName }, 'Announcement validation failed'); + logger.debug({ error: validation.error, npub, repoName }, '[readAnnouncementFromFilesystem] Announcement validation failed'); return null; } + logger.info({ npub, repoName, eventId: announcementEvent.id }, '[readAnnouncementFromFilesystem] Successfully read and validated announcement'); return announcementEvent; } catch (error) { logger.debug({ error, npub, repoName }, 'Error reading announcement from filesystem'); diff --git a/src/routes/signup/+page.svelte b/src/routes/signup/+page.svelte index 25e02a3..5458045 100644 --- a/src/routes/signup/+page.svelte +++ b/src/routes/signup/+page.svelte @@ -2271,7 +2271,8 @@ fetch(`/api/repos/${userNpub}/${dTag}/clone`, { method: 'POST', headers: { - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', + 'X-User-Pubkey': pubkey }, body: JSON.stringify({ announcementEvent: signedEvent // Pass the signed announcement event directly @@ -2296,10 +2297,24 @@ // Redirect to the newly created repository page const userNpub = nip19.npubEncode(pubkey); + // Store announcement in sessionStorage for private repos (not on relays yet) + // This allows the page load function to find it immediately + if (typeof window !== 'undefined' && signedEvent) { + const repoKey = `${userNpub}/${dTag}`; + try { + sessionStorage.setItem(`repo_announcement_${repoKey}`, JSON.stringify(signedEvent)); + console.log(`[Signup] Stored announcement in sessionStorage for ${repoKey}`); + } catch (err) { + console.warn('[Signup] Failed to store announcement in sessionStorage:', err); + } + } + // Check if this is a transfer completion (from query params) const urlParams = $page.url.searchParams; const isTransfer = urlParams.get('transfer') === 'true'; + // Wait longer for commit to complete and filesystem to sync + // The Vite SSR error during commit is harmless, but we need to wait for the commit to finish setTimeout(() => { // Invalidate all caches and redirect if (isTransfer) { @@ -2308,7 +2323,7 @@ } else { goto(`/repos/${userNpub}/${dTag}`, { invalidateAll: true, replaceState: false }); } - }, 1000); + }, 3000); // Increased from 1000ms to 3000ms to allow commit to complete return; }