feat(qt): opt-in — a click on a section row opens its first tab

Settings > Appearance, OFF by default. With it on, clicking Discover lands on
Home and clicking Library lands on All, instead of only opening the section's
flyout and waiting for a pick.

The rule lives in NavFlyout because the catalog does: "the first tab" is
`entries[0]`, and routing it back through `activate` means the My QBZ section —
whose entries are plain views carrying no tab — needs no special case. Both
hosts call it from their row's click next to the open they already do, so the
sidebar and the title bar cannot drift.

The pref rides `settingsJson` like the two Purchases toggles beside it, so
nothing is wired beyond the write and the republish every settings toggle
already does. The read is a guarded parse: a bare JSON.parse in that binding
throws on the pre-publish frame and would take the whole nav catalog — and
therefore both hosts — down with it.

Eight locales. Release build clean, offscreen smoke green.

cc
This commit is contained in:
vicrodh committed 2026-08-19 09:34:05 -06:00
1 parent 81e172457f
commit e9f09a59a4
13 files changed
+120 -2

No files matched your search

@@ -478,6 +478,14 @@ Column {
onSelected: function (i) { QbzBridge.settingsSelect("startup-page", i) }
}
}
SettingRow {
label: QbzSession.tr("Click on menu item navigates to first tab", QbzSession.trRev)
description: QbzSession.tr("Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu", QbzSession.trRev)
QbzToggle {
checked: root.doc.navClickFirstTab === true
onToggled: function (v) { QbzBridge.settingsBool("nav-click-first-tab", v) }
}
}
SettingRow {
label: QbzSession.tr("Show Purchases", QbzSession.trRev)
description: QbzSession.tr("Show the Purchases section in the sidebar for browsing and downloading your purchased music", QbzSession.trRev)
+6 -1
View File
@@ -305,7 +305,12 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
// Full text tabs name their section already, so the dropdown gets
// no title row (HeaderBar.slint:167 sets title: "").
onClicked: navFlyout.openUnder(navTab, navTab.section, false)
onClicked: {
navFlyout.openUnder(navTab, navTab.section, false)
// The same opt-in the sidebar rows carry — one behaviour, both
// hosts, because the catalog and the rule live in NavFlyout.
navFlyout.sectionClicked(navTab.section)
}
onContainsMouseChanged: {
if (containsMouse) {
// Hover-to-open, and hovering a DIFFERENT tab overwrites
+30
View File
@@ -273,6 +273,36 @@ Item {
QbzShell.navigateTo(entry.view)
}
// OPT-IN (Settings > Appearance, OFF by default): a click on a top-level
// section row also navigates, landing on that section's FIRST entry —
// Discover on Home, Library on All. Shipped behaviour is that a click only
// opens the flyout and the user picks from it, which is what `false` keeps.
//
// It lives HERE and not in the two hosts because the catalog lives here:
// "the first tab" is `entries[0]`, and reusing `activate` means the MyQBZ
// section — whose entries are plain views with no tab — needs no special
// case. Sidebar.qml and HeaderBar.qml each call this from their row's
// `onClicked`, next to the open they already do.
//
// GUARDED parse, the same precedent as `branding` above: a bare
// JSON.parse in a binding throws on the pre-publish frame and would take
// the whole nav catalog — and therefore both hosts — down with it.
readonly property bool clickNavigates: {
try {
return JSON.parse(QbzBridge.settingsJson).navClickFirstTab === true
} catch (e) {
return false
}
}
/// Call from a section row's click. A no-op unless the user opted in.
function sectionClicked(section) {
if (!nav.clickNavigates || !section || section.enabled === false)
return
var entries = section.entries || []
if (entries.length > 0)
nav.activate(entries[0])
}
QbzTheme { id: theme }
// Idle-close (project rule: 1s), paused while the pointer rests on the
+6 -1
View File
@@ -412,7 +412,12 @@ Rectangle {
enabled: navRow.isEnabled
hoverEnabled: navRow.isEnabled
cursorShape: Qt.PointingHandCursor
onClicked: navFlyout.openBeside(navRow, navRow.section)
onClicked: {
navFlyout.openBeside(navRow, navRow.section)
// Opt-in "click lands on the first tab" — a no-op while the
// Appearance toggle is off, which is the default.
navFlyout.sectionClicked(navRow.section)
}
onContainsMouseChanged: {
if (containsMouse) {
// Hover-to-open; hovering another row overwrites the open
+14
View File
@@ -1526,6 +1526,12 @@ pub struct SettingsDoc {
pub show_purchases: bool,
#[serde(rename = "navTbPurchases")]
pub nav_tb_purchases: bool,
/// Opt-in: a click on a top-level section row (Discover / Library / Local
/// Library / My QBZ) also NAVIGATES, landing on that section's first entry.
/// Off by default, which is the behaviour that shipped: a click only opens
/// the section's flyout and the user picks a tab from it.
#[serde(rename = "navClickFirstTab")]
pub nav_click_first_tab: bool,
pub renderers: Vec<String>,
#[serde(rename = "rendererIndex")]
pub renderer_index: i32,
@@ -1968,6 +1974,7 @@ pub async fn publish_snapshot() {
startup_page_index: index_of(STARTUP_PAGE_VALUES, &pref_str("startup_page", "home"), 0),
show_purchases: pref_bool("show_purchases", false),
nav_tb_purchases: pref_bool("nav_tb_purchases", false),
nav_click_first_tab: pref_bool("nav_click_first_tab", false),
renderers: RENDERER_LABELS.iter().map(|l| qbz_i18n::t(l)).collect(),
renderer_index: index_of(RENDERER_VALUES, &pref_str("renderer", "auto"), 0),
gpu_powers: gpu_power_choice().0,
@@ -2278,6 +2285,13 @@ pub async fn settings_bool(runtime: &Arc<AppRuntime<LoggingAdapter>>, key: &str,
save_pref("nav_tb_purchases", serde_json::json!(value));
Ok(Apply::None)
}
// Read by BOTH nav hosts off `settingsJson` (shell/NavFlyout.qml), so
// there is nothing to apply here beyond the write and the republish
// every settings toggle already does.
"nav-click-first-tab" => {
save_pref("nav_click_first_tab", serde_json::json!(value));
Ok(Apply::None)
}
"tray-enable" => tray()
.set_enable_tray(value)
.map_err(|e| e.to_string())
@@ -5287,3 +5287,10 @@ msgstr "Favoriten"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Inhalte aktualisieren"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Klick auf einen Menüpunkt öffnet den ersten Tab"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Ein Klick auf eine Sektion in der Seitenleiste oder Titelleiste öffnet sie auf ihrem ersten Tab — Discover auf Home, Library auf All — statt nur ihr Menü zu zeigen"
@@ -903,3 +903,10 @@ msgstr "Favorites"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Refresh content"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Click on menu item navigates to first tab"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
@@ -5293,3 +5293,10 @@ msgstr "Favoritos"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Actualizar contenido"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Hacer clic en una sección abre su primera pestaña"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Al hacer clic en una sección de la barra lateral o del título, se abre en su primera pestaña — Discover en Home, Library en All — en vez de sólo mostrar su menú"
@@ -5285,3 +5285,10 @@ msgstr "Favoris"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Actualiser le contenu"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Cliquer sur une section ouvre son premier onglet"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Cliquer sur une section dans la barre latérale ou la barre de titre l'ouvre sur son premier onglet — Discover sur Home, Library sur All — au lieu d'afficher seulement son menu"
@@ -5270,3 +5270,10 @@ msgstr "お気に入り"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "コンテンツを更新"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "メニュー項目のクリックで最初のタブを開く"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "サイドバーやタイトルバーのセクションをクリックすると、メニューを表示するだけでなく最初のタブ(Discover は Home、Library は All)が開きます"
@@ -5275,3 +5275,10 @@ msgstr "Favorieten"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Inhoud vernieuwen"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Klik op een menu-item opent het eerste tabblad"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Klikken op een sectie in de zijbalk of titelbalk opent deze op het eerste tabblad — Discover op Home, Library op All — in plaats van alleen het menu te tonen"
@@ -5285,3 +5285,10 @@ msgstr "Favoritos"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Atualizar conteúdo"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Clicar em uma seção abre a primeira aba"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Clicar em uma seção na barra lateral ou na barra de título abre-a na primeira aba — Discover em Home, Library em All — em vez de apenas mostrar o menu"
@@ -5304,3 +5304,10 @@ msgstr "Избранное"
# Discover configurator: Refresh content (2026-08-19)
msgid "Refresh content"
msgstr "Обновить содержимое"
# Appearance: click-on-section opens the first tab (2026-08-19)
msgid "Click on menu item navigates to first tab"
msgstr "Клик по разделу открывает его первую вкладку"
msgid "Clicking a section in the sidebar or title bar opens it on its first tab — Discover on Home, Library on All — instead of only showing its menu"
msgstr "Клик по разделу в боковой панели или заголовке открывает его на первой вкладке — Discover на Home, Library на All — вместо показа только меню"