fix: batch beta fixes — 13 issues from 2026-03-28 testing
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled

Frontend (neode-ui):
- Login double-enter: change @keyup.enter to @keydown.enter (#10)
- Login loop on LAN: post-login session verify before navigation (#12)
- Splash flash: reorder isReady/showSplash, add black fallback div (#7)
- Skip button text: remove "skip this step" from onboarding (#8)
- Password UI: import existing ChangePasswordSection in Settings (#11)
- Arrow key focus trap: add tab-order fallback when spatial nav fails (#13)

ISO/Boot (image-recipe):
- Step counter: TOTAL_STEPS=7 → 8 to match actual step count
- GRUB theme: add desktop-image-scale-method stretch, widen menu
- Boot noise: add loglevel=0, rd.systemd.show_status=false to kernel
- USB removal: copy reboot script to tmpfs, exec from there
- Tor setup: rewrite python3 JSON generation as bash heredoc
- Doctor/reconcile: copy scripts into rootfs, fix missing file errors
- zstd: add to rootfs packages for initramfs compression

Docs:
- BETA-ISSUES-20260328.md: full issue tracker
- INSTALL-SCREENS-DESIGN.md: editable TUI mockups

522 tests pass, vue-tsc clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-28 23:41:40 +00:00
parent 6be30b99fa
commit b47fec7fba
10 changed files with 330 additions and 57 deletions

View File

@@ -56,7 +56,7 @@
autocomplete="off"
class="w-full px-4 py-3 bg-transparent border border-white/20 rounded-lg text-white placeholder-white/40 focus:outline-none focus:border-white/40 focus:ring-1 focus:ring-white/20 transition-colors"
:placeholder="t('login.enterPasswordSetup')"
@keyup.enter="handleSetupWithSound"
@keydown.enter="handleSetupWithSound"
:disabled="loading || formDisabled"
/>
</div>
@@ -72,7 +72,7 @@
autocomplete="off"
class="w-full px-4 py-3 bg-transparent border border-white/20 rounded-lg text-white placeholder-white/40 focus:outline-none focus:border-white/40 focus:ring-1 focus:ring-white/20 transition-colors"
:placeholder="t('login.confirmPasswordPlaceholder')"
@keyup.enter="handleSetupWithSound"
@keydown.enter="handleSetupWithSound"
:disabled="loading || formDisabled"
/>
</div>
@@ -156,7 +156,7 @@
autocomplete="off"
class="w-full px-4 py-3 bg-transparent border border-white/20 rounded-lg text-white placeholder-white/40 focus:outline-none focus:border-white/40 focus:ring-1 focus:ring-white/20 transition-colors"
:placeholder="t('login.enterPasswordPlaceholder')"
@keyup.enter="handleLoginWithSound"
@keydown.enter="handleLoginWithSound"
:disabled="loading || formDisabled"
/>
</div>
@@ -424,6 +424,14 @@ async function handleLogin() {
setTimeout(() => totpInputRef.value?.focus(), 100)
return
}
// Verify session cookie works before navigating (prevents login loop on LAN)
try {
await rpcClient.call({ method: 'server.echo', params: { message: 'session-check' } })
} catch {
error.value = 'Login succeeded but session could not be established. Try clearing cookies and refreshing.'
store.logout()
return
}
stopSynthwave()
whooshAway.value = true
playLoginSuccessWhoosh()

View File

@@ -15,7 +15,7 @@
<!-- Content Area -->
<div class="flex flex-col items-center gap-4 sm:gap-6 mb-4 sm:mb-6 px-3 sm:px-4">
<div class="w-full max-w-[600px] space-y-4 sm:space-y-6">
<p v-if="serverStarting" class="text-orange-400/80 text-sm">Server is still starting up. You can try again shortly or skip this step.</p>
<p v-if="serverStarting" class="text-orange-400/80 text-sm">Server is still starting up. Please try again shortly.</p>
<p v-else-if="errorMessage" class="text-red-400 text-sm">{{ errorMessage }}</p>
<!-- Passphrase Input -->
<div class="path-option-card cursor-default px-4 py-4 sm:px-6 sm:py-6">

View File

@@ -14,7 +14,7 @@
<!-- Content Area -->
<div class="flex flex-col items-center gap-6 mb-6">
<p v-if="serverStarting" class="text-orange-400/80 text-sm">Server is still starting up. You can try again shortly or skip this step.</p>
<p v-if="serverStarting" class="text-orange-400/80 text-sm">Server is still starting up. Please try again shortly.</p>
<p v-else-if="errorMessage" class="text-red-400 text-sm">{{ errorMessage }}</p>
<!-- Sign Button (if not verified yet) -->
<button
@@ -127,7 +127,7 @@ async function signChallenge() {
if (isRetryable) {
serverStarting.value = true
} else {
errorMessage.value = msg || 'Failed to sign challenge. You can retry or skip this step.'
errorMessage.value = msg || 'Failed to sign challenge. Please try again.'
}
} else {
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)))

View File

@@ -1,11 +1,13 @@
<script setup lang="ts">
import AccountSection from '@/views/settings/AccountSection.vue'
import ChangePasswordSection from '@/views/settings/ChangePasswordSection.vue'
import SystemSection from '@/views/settings/SystemSection.vue'
</script>
<template>
<div class="pb-6">
<AccountSection />
<ChangePasswordSection />
<SystemSection />
</div>
</template>