From a6c1820a83f8a970bdaf9563406b7cec8ddea0ae Mon Sep 17 00:00:00 2001 From: Dorian Date: Mon, 9 Mar 2026 19:32:28 +0000 Subject: [PATCH] fix: mobile onboarding viewport + filebrowser demo fixes Onboarding: - Fixed viewport to use dvh units with position:fixed container - All views use scrollable glass containers that fit within viewport - Responsive typography and spacing (mobile-first breakpoints) - Tighter padding/margins on small screens - RootRedirect checks localStorage first for instant redirect - Spinner only appears after 500ms delay to avoid flash Filebrowser: - Fix CloudFolder null initialPath crash (watch both useNativeUI + section) - Remove unused `host` computed (was causing TS error) - Add mock GET /app/filebrowser/ landing page - Increase express.json limit to 50mb Co-Authored-By: Claude Opus 4.6 --- neode-ui/mock-backend.js | 11 +++- neode-ui/src/style.css | 37 ++++++++++++ neode-ui/src/views/CloudFolder.vue | 7 +-- neode-ui/src/views/OnboardingBackup.vue | 4 +- neode-ui/src/views/OnboardingDid.vue | 8 +-- neode-ui/src/views/OnboardingDone.vue | 4 +- neode-ui/src/views/OnboardingIdentity.vue | 20 +++---- neode-ui/src/views/OnboardingIntro.vue | 14 ++--- neode-ui/src/views/OnboardingOptions.vue | 68 +++++++++++------------ neode-ui/src/views/OnboardingPath.vue | 4 +- neode-ui/src/views/OnboardingVerify.vue | 12 ++-- neode-ui/src/views/OnboardingWrapper.vue | 19 ++++++- neode-ui/src/views/RootRedirect.vue | 28 ++++++++-- 13 files changed, 153 insertions(+), 83 deletions(-) diff --git a/neode-ui/mock-backend.js b/neode-ui/mock-backend.js index 582a9e2b..08e0eb8c 100755 --- a/neode-ui/mock-backend.js +++ b/neode-ui/mock-backend.js @@ -40,7 +40,7 @@ const corsOptions = { } app.use(cors(corsOptions)) -app.use(express.json()) +app.use(express.json({ limit: '50mb' })) app.use(cookieParser()) // Mock session storage @@ -1340,6 +1340,15 @@ const MOCK_FILE_CONTENTS = { '/Documents/backup-log.json': JSON.stringify({ backups: [{ id: 'bkp-2025-03-01', timestamp: '2025-03-01T02:00:00Z', type: 'full', apps: ['bitcoin-knots', 'lnd', 'mempool'], size_mb: 2340, status: 'success' }] }, null, 2), } +// FileBrowser UI (demo placeholder when launched directly) +app.get('/app/filebrowser/', (req, res) => { + res.type('html').send(` +File Browser +

File Browser

File Browser is running. Use the Cloud page in Archipelago to manage your files.

`) +}) + // FileBrowser login - return mock JWT app.post('/app/filebrowser/api/login', (req, res) => { res.send('"mock-filebrowser-token-demo"') diff --git a/neode-ui/src/style.css b/neode-ui/src/style.css index 1cce938d..a17265af 100644 --- a/neode-ui/src/style.css +++ b/neode-ui/src/style.css @@ -446,6 +446,28 @@ input[type="radio"]:active + * { overflow-x: hidden; } + /* Onboarding scroll container — constrains to viewport and scrolls */ + .onb-scroll-container { + max-height: calc(100dvh - 2rem); + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + } + + /* Mobile: tighter padding and margins for onboarding containers */ + @media (max-width: 639px) { + .path-glass-container { + width: calc(100% - 24px); + margin: 12px auto; + padding: 12px; + border-radius: 20px; + gap: 8px; + } + .onb-scroll-container { + max-height: calc(100dvh - 1.5rem); + } + } + /* Choose Your Path - Option Cards */ .path-option-card { position: relative; @@ -585,6 +607,21 @@ input[type="radio"]:active + * { font-weight: 600; } + @media (max-width: 639px) { + .path-action-button { + font-size: 15px; + border-radius: 14px; + } + .path-action-button--skip { + padding: 10px 24px; + font-size: 14px; + } + .path-action-button--continue { + padding: 12px 28px; + font-size: 15px; + } + } + .path-action-button::before { content: ''; position: absolute; diff --git a/neode-ui/src/views/CloudFolder.vue b/neode-ui/src/views/CloudFolder.vue index 5cd2d330..d3be011a 100644 --- a/neode-ui/src/views/CloudFolder.vue +++ b/neode-ui/src/views/CloudFolder.vue @@ -217,7 +217,6 @@ interface ContentSection { initialPath: string } -const host = computed(() => window.location.hostname) const origin = computed(() => window.location.origin) const sections: Record ContentSection> = { @@ -285,12 +284,12 @@ const useNativeUI = computed(() => section.value?.nativeUI === true && appRunnin const iframeUrl = computed(() => section.value?.iframeUrl || '') // Initialize native file browser when entering a native-UI section -watch(useNativeUI, async (native) => { - if (native && section.value) { +watch([useNativeUI, section], async ([native, sec]) => { + if (native && sec) { cloudStore.reset() const ok = await cloudStore.init() if (ok) { - await cloudStore.navigate(section.value.initialPath) + await cloudStore.navigate(sec.initialPath) } } }, { immediate: true }) diff --git a/neode-ui/src/views/OnboardingBackup.vue b/neode-ui/src/views/OnboardingBackup.vue index 326573a1..272da530 100644 --- a/neode-ui/src/views/OnboardingBackup.vue +++ b/neode-ui/src/views/OnboardingBackup.vue @@ -1,7 +1,7 @@