fix(login): point a never-had-an-account user at the door that is for them

Local-only mode already WORKED — verified by driving a genuinely fresh
profile (no credentials, keyring unreachable): "Start offline" enters the
guest profile, Local Library opens with its proper empty state, Settings
renders in full, zero QML complaints. The capability was never the
problem. Two pieces of the screen were.

1. THE SIGNPOST WAS OFF FOR EXACTLY THE RIGHT PERSON. The callout with
   the caret pointing at the Start-offline link was gated on
   `hasPreviousSession && connectivity === 2`. `hasPreviousSession` is
   seeded from `load_last_user_id()` — None on a fresh profile — and only
   ever set true by a successful Qobuz login. So the one piece of UI that
   says "you can use this without an account" could not be seen by
   anybody who had never signed in. The gate was written for the
   returning-user-with-no-wifi case and the guest case was bolted onto
   the link alone.

2. THE COPY WAS FALSE. Once that box is visible to a first-run user with
   working internet, "No internet connection" is simply untrue, and the
   offline placeholder said the same thing after entering: measured on a
   fresh profile, the log read `connectivity Up, induced false,
   offline_session true` while the screen claimed the network was down.
   Both now branch on which of the THREE states this is — induced
   offline, no connectivity, or no account — and the captive-portal line
   is gated on connectivity too, so it cannot appear under a "No Qobuz
   account?" heading.

Two new msgids in all seven non-English catalogues.

Verified after the change on a fresh profile: the callout appears, the
link is reachable, and the placeholder reads "You're using QBZ without a
Qobuz account."

HARNESS NOTE for whoever tests this next: XDG_CONFIG_HOME sandboxes the
token FILE but NOT the system keyring, and a rejected token there calls
`clear_oauth_token`, which deletes the keyring entry for the real user.
Point DBUS_SESSION_BUS_ADDRESS at nothing so the Secret Service is
unreachable. (The file stays authoritative, so nothing is lost — but the
run is not clean either.)

cc
This commit is contained in:
vicrodh committed 2026-08-22 05:09:56 -06:00
1 parent d40fbb36d2
commit ef333cd7ec
9 files changed
+77 -6

No files matched your search

+26 -5
View File
@@ -283,10 +283,21 @@ Rectangle {
Item { width: 1; height: 10 }
// --- Offline-boot callout (spec §4.1) --------------------
// No connectivity: point the user at the Start-offline link
// right below. Gated on has-previous-session too.
// Points at the Start-offline link right below. TWO audiences, and
// until 2026-08-22 it served only one of them:
//
// returning user, no network — the case it was written for.
// NEVER HAD AN ACCOUNT — the case it was invisible for.
//
// The old gate was `hasPreviousSession && connectivity === 2`, and
// `hasPreviousSession` is seeded from `load_last_user_id()` — None
// on a fresh profile, and only ever set true by a successful Qobuz
// login. So the one piece of UI that points at "you can use this
// without an account" was structurally unreachable for exactly the
// person who needs it. Verified by driving a fresh profile: the
// capability works, the signpost never appears.
Column {
visible: QbzSession.hasPreviousSession && QbzSession.connectivity === 2
visible: QbzSession.connectivity === 2 || !QbzSession.hasPreviousSession
width: parent.width
spacing: 2
Rectangle {
@@ -305,14 +316,24 @@ Rectangle {
spacing: 4
Text {
width: parent.width
text: QbzSession.tr("No internet connection — you can start in offline mode with your local library and downloads", QbzSession.trRev)
// Say the RIGHT thing to each audience. Telling a
// first-run user with working internet that they
// have "no internet connection" is simply false,
// and it is what the screen used to imply the
// moment this box became visible to them.
text: QbzSession.connectivity === 2
? QbzSession.tr("No internet connection — you can start in offline mode with your local library and downloads", QbzSession.trRev)
: QbzSession.tr("No Qobuz account? You can still use QBZ as a player for your own music library", QbzSession.trRev)
color: theme.textSecondary
font.pixelSize: theme.fontBody
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Text {
visible: QbzSession.captivePortal
// ALSO gated on connectivity: a captive-portal line
// under a "No Qobuz account?" heading would be a
// non-sequitur for a first-run user who is online.
visible: QbzSession.captivePortal && QbzSession.connectivity === 2
width: parent.width
text: QbzSession.tr("A network sign-in page may be blocking the connection", QbzSession.trRev)
color: theme.textMuted
@@ -35,9 +35,17 @@ Column {
Item { width: 1; height: 8 }
Text {
width: 420
// THREE cases, not two. The third is a session that was started
// WITHOUT a Qobuz account at all ("Start offline" on the login
// screen): that user has working internet, and telling them "no
// internet connection" is simply false — measured on a fresh profile
// 2026-08-22, where the log read `connectivity Up, offline_session
// true` while this line claimed the network was down.
text: induced
? QbzSession.tr("Offline mode is enabled. Disable it in Settings to use Qobuz.", QbzSession.trRev)
: QbzSession.tr("No internet connection. Your local library and downloads keep working.", QbzSession.trRev)
: QbzSession.offlineSession
? QbzSession.tr("You're using QBZ without a Qobuz account. Your local library and downloads keep working.", QbzSession.trRev)
: QbzSession.tr("No internet connection. Your local library and downloads keep working.", QbzSession.trRev)
color: theme.textSecondary
font.pixelSize: theme.fontBody
horizontalAlignment: Text.AlignHCenter