Files

161 lines
5.8 KiB
QML

// The focus tab: the modes that quiet this machine, and the timed session that
// is deliberately not one of them.
//
// Modes are conditions rather than alarms -- a mode is on because something is
// true right now -- so the editor never asks anyone to schedule an event. It
// asks what has to be true. Order is priority, which is why the list can be
// reordered and says so.
import QtQuick
import qs.config
import qs.services
SettingsPage {
id: root
// One mode is open for editing at a time; the point is a card you can read,
// not every mode unfolded at once.
property string expandedMode: ""
// The exception list belongs to the page rather than to the row: the
// applications it is chosen from are the same universe the per-application
// notification rules use, and the page is what reads it.
function toggleAllowed(mode: var, appId: string, allowed: bool): void {
const current = Array.isArray(mode.allow) ? mode.allow.map(String) : [];
const at = current.indexOf(appId);
if (allowed && at < 0)
current.push(appId);
else if (!allowed && at >= 0)
current.splice(at, 1);
FocusModes.update(String(mode.id), { allow: current });
}
title: "Focus"
lede: "Modes quiet this machine on their own terms — first matching mode wins, and the order below is the priority."
SettingsCard {
title: "Focus modes"
subtitle: FocusModes.active
? FocusModes.activeName + " is on because " + FocusModes.activeReason + "."
: "Drag a mode by its grip, or press up and down on it, to change which one wins."
TextRow {
visible: FocusModes.modes.length === 0
label: "No focus modes"
detail: "Add one below and give it something to react to"
divider: false
}
Repeater {
model: FocusModes.modes
delegate: FocusModeRow {
id: modeRow
required property var modelData
width: parent.width
mode: modeRow.modelData
knownApps: Notifs.applications
expanded: root.expandedMode === String(modeRow.modelData.id ?? "")
running: FocusModes.activeMode?.id === String(modeRow.modelData.id ?? "")
onActivated: root.expandedMode = modeRow.expanded
? ""
: String(modeRow.modelData.id ?? "")
onAllowToggled: (appId, allowed) =>
root.toggleAllowed(modeRow.modelData, appId, allowed)
}
}
Item {
width: parent.width
height: 58
Rectangle {
id: newMode
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 44
radius: Theme.cardRadius
color: Theme.alpha(Theme.fg, newModeHover.hovered ? 0.06 : 0.02)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.16)
Text {
anchors.centerIn: parent
text: "+ New focus mode"
color: newModeHover.hovered ? Theme.fg : Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.weight: Font.Medium
}
HoverHandler {
id: newModeHover
cursorShape: Qt.PointingHandCursor
}
// Created open, so the first thing anyone sees is the editor
// rather than a row named "New mode" with nothing to react to.
TapHandler {
onTapped: root.expandedMode = String(FocusModes.createMode("New mode"))
}
}
}
}
SettingsCard {
title: "Focus sessions"
subtitle: "A timed, workspace-bound sprint — separate from modes, and it owns Do Not Disturb while it runs."
SegmentRow {
label: "Default duration"
detail: "Used by Super+Shift+F and Quick Settings"
options: [
{ value: 25, label: "25 min" },
{ value: 45, label: "45 min" },
{ value: 60, label: "60 min" },
{ value: 90, label: "90 min" }
]
value: DesktopPreferences.get("focusDurationMinutes")
onSelected: value => SystemSettings.commitPreference("focusDurationMinutes", value)
}
SettingRow {
label: "Keep the machine awake"
detail: Caffeine.enabled
? "The display will not blank or lock while this is on"
: "Caffeine — outside of sessions and modes too"
controlWidth: 48
SettingsToggle {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: Caffeine.enabled
onToggled: value => Caffeine.enabled = value
}
}
SettingRow {
label: FocusSession.active
? `Active on ${FocusSession.workspaceLabel}`
: "No session running"
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()
}
}
}
}