feat: Settings is one page per section down a left rail, Account first, every setting a row; the profile form no longer saves blanks over your name and email (M503 #5595 #5596 #5597)
release / govulncheck (push) Successful in 18s
release / web (push) Successful in 1m45s
release / go (push) Successful in 1m58s
release / integration (push) Successful in 5m39s
release / android (push) Successful in 5m43s
release / Build signed APK (releases and dev) (push) Successful in 5m58s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 26s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 18s
release / web (push) Successful in 1m45s
release / go (push) Successful in 1m58s
release / integration (push) Successful in 5m39s
release / android (push) Successful in 5m43s
release / Build signed APK (releases and dev) (push) Successful in 5m58s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 26s
release / Verify release artifacts (tag releases only) (push) Skipped
- /settings lands on Account: the Android app, profile, password, signed-in devices. Then Playback, Appearance, Notifications, Connections, About. - Each setting is a row (name, one short line, control at the end) in a capped-width column; one-of-N choices are a shared Segmented control. - Collection and Settings share one SectionRail. - Connections leads ListenBrainz with a status line: not connected, connected and not sending, or sending with the last scrobble's age. - Notifications prints its column labels once; the digest email's settings link points at /settings/notifications. - #5596: the profile form now loads what is stored and sends only the fields that changed. It used to start blank, and the server reads a blank as "clear", so one Save wiped the display name and email. - Recommendation metrics moves to Library › Your listening, and Hidden tracks gets a Library tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,19 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { Smartphone } from 'lucide-svelte';
|
||||
import { Download, Smartphone } from 'lucide-svelte';
|
||||
import { api } from '#lib/api/client.js';
|
||||
import SettingsGroup from '#lib/components/settings/SettingsGroup.svelte';
|
||||
import SettingRow from '#lib/components/settings/SettingRow.svelte';
|
||||
|
||||
// Polls /api/client/version once on mount. Renders nothing on 404
|
||||
// (no bundled APK — graceful degradation in dev / pre-CI images)
|
||||
// or 401 (defensive — caller must be logged in).
|
||||
// The Android app this server bundles, at the top of Settings › Account
|
||||
// (#5595). Polls /api/client/version once on mount. Renders nothing on
|
||||
// 404 (no bundled APK: dev and pre-CI images) or 401.
|
||||
//
|
||||
// The /api/client/* endpoints are auth-gated to prevent anonymous
|
||||
// bandwidth abuse on the APK stream, so this component only shows
|
||||
// for logged-in users. Mount in Settings, never in pre-auth surfaces.
|
||||
// bandwidth abuse on the APK stream, so this only shows to a signed-in
|
||||
// user. Mount in Settings, never on a pre-auth page.
|
||||
|
||||
// Server returns snake_case (clientVersionResponse in
|
||||
// internal/api/client_assets.go). Map to a camelCase struct for
|
||||
// the rest of the component.
|
||||
// internal/api/client_assets.go).
|
||||
type WireInfo = { version: string; apk_url: string; size_bytes: number };
|
||||
type Info = { version: string; apkUrl: string; sizeBytes: number };
|
||||
|
||||
@@ -40,23 +41,19 @@
|
||||
</script>
|
||||
|
||||
{#if info}
|
||||
<section class="space-y-3 rounded border border-border bg-surface p-4">
|
||||
<h2 class="text-lg font-semibold">Mobile app</h2>
|
||||
<p class="text-sm text-text-secondary">
|
||||
Install the Android app paired to this server. Sign in with the same account.
|
||||
</p>
|
||||
<a
|
||||
href={info.apkUrl}
|
||||
download="minstrel.apk"
|
||||
class="mobile-app-download flex items-center gap-3 rounded-md border border-border bg-surface px-3 py-2 text-sm text-text-primary no-underline transition-colors hover:bg-surface-hover hover:text-accent-fg focus-visible:ring-2 focus-visible:ring-accent"
|
||||
<SettingsGroup title="Android app">
|
||||
<SettingRow
|
||||
label="Minstrel for Android"
|
||||
hint="{info.version}{info.sizeBytes > 0 ? ` · ${formatSize(info.sizeBytes)}` : ''} · sign in with this account"
|
||||
>
|
||||
<Smartphone size={18} strokeWidth={1.5} class="shrink-0 text-accent-fg" />
|
||||
<span class="flex flex-col leading-tight">
|
||||
<span class="font-medium">Get the Android app</span>
|
||||
<span class="text-xs text-text-secondary">
|
||||
{info.version}{info.sizeBytes > 0 ? ` · ${formatSize(info.sizeBytes)}` : ''}
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</section>
|
||||
<Smartphone size={18} strokeWidth={1.5} class="text-text-secondary" aria-hidden="true" />
|
||||
<a
|
||||
href={info.apkUrl}
|
||||
download="minstrel.apk"
|
||||
class="inline-flex items-center gap-1.5 rounded-md bg-action-secondary px-3 py-1.5 text-sm text-action-fg hover:opacity-90 focus-visible:ring-2 focus-visible:ring-accent"
|
||||
>
|
||||
<Download size={16} strokeWidth={1.75} aria-hidden="true" /> Download
|
||||
</a>
|
||||
</SettingRow>
|
||||
</SettingsGroup>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user