import QtQuick import qs.config import qs.services SettingsPage { id: root // Only one application is expanded at a time; the point is a card you // can read, not twenty open at once. property string expandedApp: "" title: "Notifications & Focus" lede: "Control interruptions without losing useful history." SettingsCard { title: "Notifications" SettingRow { label: "Do Not Disturb" detail: "Keep notifications in the center but suppress banners" controlWidth: 48 SettingsToggle { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter checked: Notifs.doNotDisturb onToggled: value => Notifs.doNotDisturb = value } } TextRow { label: "Notification history" detail: "Live notifications retained by the shell" value: Notifs.history.length === 1 ? "1 item" : `${Notifs.history.length} items` } ActionRow { label: "Clear notification history" detail: "Dismiss every item currently in the notification center" divider: false action: "Clear all" enabled: Notifs.history.length > 0 onTriggered: Notifs.dismissAll() } } SettingsCard { title: "Banner behavior" SliderRow { setting: "notificationTimeoutMs" } SliderRow { setting: "notificationTimeoutCriticalMs" zeroLabel: "Never" } SliderRow { setting: "notificationHistoryLimit" } SliderRow { setting: "maxVisibleToasts"; divider: false } } SettingsCard { title: "Application rules" subtitle: "Apps appear here after they send a notification." TextRow { visible: Notifs.applications.length === 0 label: "No applications remembered yet" detail: "Application controls will appear after the first notification arrives." divider: false } Repeater { model: Notifs.applications Column { id: appEntry required property var modelData readonly property var app: appEntry.modelData readonly property var rule: Notifs.appRule(appEntry.app.id) readonly property bool open: root.expandedApp === String(appEntry.app.id) // What the two lock-screen switches add up to, so the common // case -- reading rather than changing -- needs no interaction. // Every app repeated both switch labels verbatim before this, // which made twenty apps sixty rows of identical sentences. readonly property string summary: { if (!appEntry.rule.enabled) return "Notifications off"; if (!appEntry.rule.showOnLockScreen) return "On · hidden on the lock screen"; return appEntry.rule.showContentOnLockScreen ? "On · lock screen shows content" : "On · lock screen shows the sender only"; } width: parent.width SettingRow { width: parent.width label: appEntry.app.name // The identifier is only worth the space while the app is // open, which is the only time it disambiguates anything. detail: appEntry.open ? String(appEntry.app.id) : appEntry.summary activatable: true divider: !appEntry.open controlWidth: 92 onActivated: root.expandedApp = appEntry.open ? "" : String(appEntry.app.id) Row { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: 11 SettingsToggle { anchors.verticalCenter: parent.verticalCenter checked: appEntry.rule.enabled onToggled: value => Notifs.setAppRule(appEntry.app.id, { enabled: value }) } Text { anchors.verticalCenter: parent.verticalCenter text: appEntry.open ? "\u25B4" : "\u25BE" color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } } } SettingRow { width: parent.width visible: appEntry.open label: "Show on lock screen" detail: "Allow this app's notifications on the lock screen" controlWidth: 48 SettingsToggle { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter checked: appEntry.rule.showOnLockScreen onToggled: value => Notifs.setAppRule(appEntry.app.id, { showOnLockScreen: value }) } } SettingRow { width: parent.width visible: appEntry.open label: "Show content on lock screen" detail: "Show message details when this app is visible there" divider: false controlWidth: 48 // Meaningless unless the app reaches the lock screen at all. opacity: appEntry.rule.showOnLockScreen ? 1 : 0.45 SettingsToggle { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter enabled: appEntry.rule.showOnLockScreen checked: appEntry.rule.showContentOnLockScreen onToggled: value => Notifs.setAppRule(appEntry.app.id, { showContentOnLockScreen: value }) } } } } } SettingsCard { title: "Focus sessions" subtitle: "A focus session binds quiet mode and Caffeine to the current workspace." SettingRow { label: "Keep the screen awake" detail: Caffeine.enabled ? "The display will not blank or lock while this is on" : "Idle timings on Power & Lock apply normally" controlWidth: 48 SettingsToggle { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter checked: Caffeine.enabled onToggled: value => Caffeine.enabled = value } } SettingRow { id: durationRow label: "Default duration" detail: "Used by Super+Shift+F and Quick Settings" controlWidth: 264 Row { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter spacing: 6 Repeater { model: [25, 45, 60, 90] SettingsButton { required property int modelData text: `${modelData}m` tone: DesktopPreferences.get("focusDurationMinutes") === modelData ? "accent" : "normal" onClicked: SystemSettings.commitPreference("focusDurationMinutes", modelData) } } } } SettingRow { label: FocusSession.active ? `Active on ${FocusSession.workspaceLabel}` : "No active focus session" detail: FocusSession.active ? `${FocusSession.remainingText} remaining` : "Start one without leaving Settings" divider: false controlWidth: 120 SettingsButton { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter text: FocusSession.active ? "Show controls" : "Start focus" tone: FocusSession.active ? "normal" : "accent" onClicked: FocusSession.reveal() } } } }