Fold thirty-one settings pages into fifteen categories with tabs
The sidebar was a flat scan of thirty-one rows; now it reads like a settings app. Multi-subject categories (Input, Network & Sharing, Applications, Users & Accounts, Privacy & Security, System) carry an Appearance-style tab strip above the page, drawn by the shell so the leaf pages themselves are untouched. The taxonomy lives in one new file, services/SettingsRoutes.qml; the sidebar, the strip, route validation, search breadcrumbs, and both generators derive from it. ShellState.settingsPage still holds leaf ids, so every deep link, IPC call, and search result keeps working — and now lands on the exact tab. Dictation moves out of Sound onto its own page under Input, with a handoff back to Sound for the microphone. The strip scrolls when System's nine tabs outgrow a tiled window. All 161 contracts pass. Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -95,11 +95,39 @@ Rectangle {
|
||||
color: Theme.alpha(Theme.fg, 0.06)
|
||||
}
|
||||
|
||||
// The tab strip for the current category, rendered above the page so the
|
||||
// leaf pages themselves stay untouched by the grouping. A category with a
|
||||
// single subject earns no strip.
|
||||
readonly property var categoryTabs: SettingsRoutes.tabsFor(ShellState.settingsPage)
|
||||
|
||||
Item {
|
||||
id: categoryStrip
|
||||
|
||||
readonly property bool shown: root.categoryTabs.length > 1
|
||||
|
||||
anchors.left: sidebar.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: titlebar.bottom
|
||||
anchors.leftMargin: 34
|
||||
anchors.rightMargin: 34
|
||||
height: shown ? 48 : 0
|
||||
visible: shown
|
||||
|
||||
SettingsTabs {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
tabs: root.categoryTabs.map(tab => ({ value: tab.page, label: tab.label }))
|
||||
current: ShellState.settingsPage
|
||||
onSelected: value => ShellState.openSettings(value)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: pageLoader
|
||||
anchors.left: sidebar.right
|
||||
anchors.right: parent.right
|
||||
anchors.top: titlebar.bottom
|
||||
anchors.top: categoryStrip.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
sourceComponent: {
|
||||
switch (ShellState.settingsPage) {
|
||||
@@ -114,6 +142,7 @@ Rectangle {
|
||||
case "screen-intelligence": return screenIntelligencePage;
|
||||
case "shortcuts": return shortcutsPage;
|
||||
case "mouse": return mousePage;
|
||||
case "dictation": return dictationPage;
|
||||
case "privacy": return privacyPage;
|
||||
case "region": return regionPage;
|
||||
case "accounts": return onlineAccountsPage;
|
||||
@@ -192,6 +221,7 @@ Rectangle {
|
||||
Component { id: screenIntelligencePage; ScreenIntelligencePage {} }
|
||||
Component { id: shortcutsPage; ShortcutsPage {} }
|
||||
Component { id: mousePage; MousePage {} }
|
||||
Component { id: dictationPage; DictationPage {} }
|
||||
Component { id: privacyPage; PrivacyPage {} }
|
||||
Component { id: regionPage; RegionPage {} }
|
||||
Component { id: onlineAccountsPage; OnlineAccountsPage {} }
|
||||
|
||||
Reference in New Issue
Block a user