Files
Panama/config/dot/quickshell/modules/settings/SettingsSidebar.qml
T
Gabriel Brown 6377bfb8fd Route the Applications page and add its settings
Wires the schema entries and routing the codex agent needs for default
applications, weather, vitals refresh, notification timing, and capture,
so its pages can be written against keys that already exist.

Capture directories and encoder arguments are enums rather than free
text. Both are handed to a recorder process, and a settings page has no
reason to expose an arbitrary string there.

ApplicationsPage.qml is a placeholder so the page id can be routed,
registered, and searchable before the real page lands. It is owned by
the other agent and expected to be replaced wholesale.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 00:51:10 -04:00

284 lines
11 KiB
QML

import QtQuick
import qs.config
import qs.services
Rectangle {
id: root
property string selectedPage: "home"
property string query: searchInput.text.trim().toLowerCase()
signal pageRequested(string page)
readonly property var results: SettingsSearch.search(root.query)
function pageLabel(page: string): string {
const found = root.destinations.find(item => item.page === page);
return found ? found.label : "Settings";
}
readonly property var destinations: [
{ page: "home", label: "Home", icon: "\u{F02DC}" },
{ page: "appearance", label: "Appearance", icon: "\u{F0E0D}" },
{ page: "displays", label: "Displays", icon: "\u{F0379}" },
{ page: "connectivity", label: "Network & Devices", icon: "\u{F08D4}" },
{ page: "home-phone", label: "Home & Phone", icon: "\u{F02DC}" },
{ page: "desktop", label: "Desktop & Dock", icon: "\u{F04A4}" },
{ page: "sound", label: "Sound", icon: "\u{F057E}" },
{ page: "notifications", label: "Notifications & Focus", icon: "\u{F009A}" },
{ page: "screen-intelligence", label: "Screen Intelligence", icon: "\u{F05A8}" },
{ page: "shortcuts", label: "Input & Shortcuts", icon: "\u{F030C}" },
{ page: "accessibility", label: "Accessibility", icon: "\u{F0208}" },
{ page: "power", label: "Power & Lock", icon: "\u{F0425}" },
{ page: "datetime", label: "Date & Time", icon: "\u{F0954}" },
{ page: "applications", label: "Applications", icon: "\u{F003B}" },
{ page: "services", label: "Startup & Services", icon: "\u{F0493}" },
{ page: "about", label: "About Panama", icon: "\u{F02FD}" }
]
width: 272
color: Theme.alpha(Theme.bgDark, 0.96)
border.width: 0
Column {
anchors.fill: parent
anchors.margins: 18
spacing: 12
Text {
text: "PANAMA"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
font.letterSpacing: 2.2
}
Rectangle {
width: parent.width
height: 36
radius: 10
color: Theme.alpha(Theme.fg, searchArea.containsMouse || searchInput.activeFocus ? 0.105 : 0.065)
border.width: 1
border.color: searchInput.activeFocus ? Theme.alpha(Theme.accent, 0.5) : Theme.alpha(Theme.fg, 0.055)
Text {
anchors.left: parent.left
anchors.leftMargin: 11
anchors.verticalCenter: parent.verticalCenter
text: "\u{F0349}"
color: Theme.fgDim
font.family: Theme.fontMono
font.pixelSize: 14
}
TextInput {
id: searchInput
anchors.left: parent.left
anchors.leftMargin: 35
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
color: Theme.fg
selectionColor: Theme.accent
selectedTextColor: Theme.bgDark
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
clip: true
Text {
anchors.fill: parent
visible: !searchInput.text && !searchInput.activeFocus
text: "Search settings"
color: Theme.fgMuted
font: searchInput.font
verticalAlignment: Text.AlignVCenter
}
}
MouseArea {
id: searchArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.IBeamCursor
onClicked: searchInput.forceActiveFocus()
}
}
// ── Search results ──────────────────────────────────────────────────
// Typing searches the settings themselves, not the twelve page names.
// "gaps", "wallpaper", and "screenshot" all used to find nothing, which
// made the app feel far smaller than it is.
Column {
width: parent.width
spacing: 3
visible: root.query !== ""
Text {
width: parent.width
leftPadding: 4
bottomPadding: 4
text: root.results.length === 0
? "Nothing matches"
: root.results.length + (root.results.length === 1 ? " result" : " results")
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Repeater {
model: root.results
Rectangle {
id: hit
required property var modelData
width: parent.width
height: 44
radius: 10
color: hitMouse.containsMouse ? Theme.alpha(Theme.fg, 0.08) : "transparent"
border.width: 0
Column {
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 12
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
spacing: 1
Text {
width: parent.width
text: hit.modelData.label
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
elide: Text.ElideRight
}
Text {
width: parent.width
text: hit.modelData.kind === "shortcut"
? hit.modelData.detail
: root.pageLabel(hit.modelData.page)
color: hit.modelData.kind === "shortcut" ? Theme.accent : Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
elide: Text.ElideRight
}
}
MouseArea {
id: hitMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.pageRequested(hit.modelData.page);
searchInput.text = "";
}
}
}
}
}
Column {
width: parent.width
spacing: 4
visible: root.query === ""
Repeater {
model: root.destinations
Rectangle {
id: navItem
required property var modelData
width: parent.width
height: 40
radius: 10
color: modelData.page === root.selectedPage
? Theme.alpha(Theme.accent, 0.17)
: (navMouse.containsMouse ? Theme.alpha(Theme.fg, Theme.hoverAlpha * 0.55) : Theme.alpha(Theme.fg, 0))
border.width: modelData.page === root.selectedPage ? 1 : 0
border.color: Theme.alpha(Theme.accent, 0.26)
Rectangle {
width: 2
height: 18
radius: 1
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
visible: navItem.modelData.page === root.selectedPage
gradient: Gradient {
GradientStop { position: 0; color: Theme.accent }
GradientStop { position: 1; color: Theme.accentSecondary }
}
}
Text {
anchors.left: parent.left
anchors.leftMargin: 13
anchors.verticalCenter: parent.verticalCenter
width: 25
text: navItem.modelData.icon
color: navItem.modelData.page === root.selectedPage ? Theme.accent : Theme.fgDim
font.family: Theme.fontMono
font.pixelSize: 15
}
Text {
anchors.left: parent.left
anchors.leftMargin: 47
anchors.right: parent.right
anchors.rightMargin: 9
anchors.verticalCenter: parent.verticalCenter
text: navItem.modelData.label
color: navItem.modelData.page === root.selectedPage ? Theme.fg : Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.weight: navItem.modelData.page === root.selectedPage ? Font.Medium : Font.Normal
elide: Text.ElideRight
}
MouseArea {
id: navMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.pageRequested(navItem.modelData.page)
}
}
}
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 54
color: Theme.alpha(Theme.bg, 0.35)
border.width: 0
Rectangle {
width: 7
height: 7
radius: 4
anchors.left: parent.left
anchors.leftMargin: 19
anchors.verticalCenter: parent.verticalCenter
color: Theme.ok
}
Text {
anchors.left: parent.left
anchors.leftMargin: 36
anchors.verticalCenter: parent.verticalCenter
text: "Panama desktop is healthy"
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
}