Consolidate omarchy-shell colors into a single shell.toml surface
Five plugins each owned their own colors.toml watcher with subtly different parsers, plus two ad-hoc per-theme override files (notifications.json, image-picker-colors.json). This collapses all of that into one source of truth: Commons/Color.qml watches colors.toml + shell.toml and exposes Color.bar.*, Color.popups.*, Color.notifications.*, Color.menu.*, Color.imagePicker.* for every surface to bind to. shell.toml is generated by the existing template pipeline from default/themed/shell.toml.tpl. Themes can ship their own shell.toml to override individual keys; everything missing falls back to the foundational palette via root.pick(). Settings panel is intentionally not themable beyond the foundational tokens. last-horizon and solitude ship a minimal shell.toml to preserve their historical 'notification border matches Hyprland active border' behavior, which previously came from parsing the theme's hyprland.conf (now removed).
This commit is contained in:
@@ -33,17 +33,6 @@ Item {
|
||||
readonly property string cacheDir: home + "/.cache/omarchy/"
|
||||
readonly property string imageCacheDir: cacheDir + "notification-images/"
|
||||
readonly property string styleStatePath: home + "/.local/state/omarchy/toggles/quickshell-menu.json"
|
||||
// Optional per-theme override file. Themes that want notification colors
|
||||
// to diverge from the rest of the palette can ship this file. Schema:
|
||||
// {
|
||||
// "borderColor": "#hex",
|
||||
// "backgroundColor": "#hex",
|
||||
// "textColor": "#hex",
|
||||
// "countdownColor": "#hex" // progress bar at bottom of popup
|
||||
// }
|
||||
// All keys optional; unset keys fall back to the live Color.* tokens.
|
||||
readonly property string themeOverridePath: home + "/.config/omarchy/current/theme/notifications.json"
|
||||
readonly property string themeNamePath: home + "/.config/omarchy/current/theme.name"
|
||||
|
||||
// Corner radius is shared with omarchy-shell menu and settings panel —
|
||||
// `omarchy style corners <sharp|round>` writes this file once and every
|
||||
@@ -78,57 +67,6 @@ Item {
|
||||
onFileChanged: reload()
|
||||
}
|
||||
|
||||
// ----------------------------------------------- per-theme color overrides
|
||||
|
||||
property string overrideBorder: ""
|
||||
property string overrideBackground: ""
|
||||
property string overrideText: ""
|
||||
property string overrideCountdown: ""
|
||||
|
||||
// Match the compact mako-style layout, but keep colors live-bound to the
|
||||
// current Omarchy theme unless a theme explicitly ships notifications.json.
|
||||
readonly property color effectiveBorder: overrideBorder.length > 0 ? overrideBorder : Color.accent
|
||||
readonly property color effectiveBackground: overrideBackground.length > 0 ? overrideBackground : Color.background
|
||||
readonly property color effectiveText: overrideText.length > 0 ? overrideText : Color.foreground
|
||||
readonly property color effectiveCountdown: overrideCountdown.length > 0 ? overrideCountdown : Color.accent
|
||||
|
||||
function loadThemeOverride(raw) {
|
||||
try {
|
||||
var parsed = JSON.parse(raw || "{}")
|
||||
overrideBorder = typeof parsed.borderColor === "string" ? parsed.borderColor : ""
|
||||
overrideBackground = typeof parsed.backgroundColor === "string" ? parsed.backgroundColor : ""
|
||||
overrideText = typeof parsed.textColor === "string" ? parsed.textColor : ""
|
||||
overrideCountdown = typeof parsed.countdownColor === "string" ? parsed.countdownColor : ""
|
||||
} catch (e) {
|
||||
overrideBorder = ""
|
||||
overrideBackground = ""
|
||||
overrideText = ""
|
||||
overrideCountdown = ""
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: themeOverrideFile
|
||||
path: service.themeOverridePath
|
||||
watchChanges: true
|
||||
printErrors: false
|
||||
onLoaded: service.loadThemeOverride(text())
|
||||
onLoadFailed: service.loadThemeOverride("")
|
||||
onFileChanged: reload()
|
||||
}
|
||||
|
||||
// Theme switching recreates ~/.config/omarchy/current/theme, which can leave
|
||||
// the notifications.json watcher attached to the old symlink target. Watch
|
||||
// theme.name (overwritten in place) as the stable tripwire and force a fresh
|
||||
// override reload; if the new theme has no override, onLoadFailed clears the
|
||||
// old colors instead of leaving stale theme-specific notification styling.
|
||||
FileView {
|
||||
path: service.themeNamePath
|
||||
watchChanges: true
|
||||
printErrors: false
|
||||
onFileChanged: themeOverrideFile.reload()
|
||||
}
|
||||
|
||||
// Fired by IPC (`omarchy-shell-ipc notifications showHistory`) so the
|
||||
// bar widget can drop its PopupCard from the same anchor a click would.
|
||||
signal historyOpenRequested()
|
||||
@@ -948,10 +886,6 @@ Item {
|
||||
urgency: cardSlot.urgency
|
||||
timestamp: cardSlot.timestamp
|
||||
cornerRadius: service.cornerRadius
|
||||
borderColorOverride: service.effectiveBorder
|
||||
backgroundColorOverride: service.effectiveBackground
|
||||
textColorOverride: service.effectiveText
|
||||
countdownColorOverride: service.effectiveCountdown
|
||||
fontFamily: service.shell && service.shell.bar ? service.shell.bar.fontFamily : ""
|
||||
glyph: cardSlot.glyph
|
||||
progress: cardSlot.progress
|
||||
|
||||
+10
-17
@@ -27,13 +27,6 @@ Rectangle {
|
||||
property real progress: 1.0
|
||||
property bool showProgress: false
|
||||
|
||||
// Container can override the theme defaults per-card. Defaults bind to
|
||||
// the live Color.* tokens, so when the container leaves them alone the
|
||||
// card still tracks the theme.
|
||||
property color borderColorOverride: Color.border
|
||||
property color backgroundColorOverride: Color.background
|
||||
property color textColorOverride: Color.foreground
|
||||
property color countdownColorOverride: Color.accent
|
||||
// System font from shell.json bar.fontFamily, injected by the container.
|
||||
property string fontFamily: ""
|
||||
|
||||
@@ -77,10 +70,10 @@ Rectangle {
|
||||
readonly property bool hasGlyph: glyph.length > 0
|
||||
readonly property bool hasSmallIcon: !mediaMode && (smallIconSource.length > 0 || hasGlyph)
|
||||
|
||||
readonly property color dimColor: Qt.darker(textColorOverride, 1.4)
|
||||
readonly property color bodyColor: Qt.darker(textColorOverride, 1.15)
|
||||
readonly property color hoverColor: Qt.rgba(textColorOverride.r, textColorOverride.g, textColorOverride.b, 0.14)
|
||||
readonly property color accentColor: urgency === 2 ? Color.urgent : (urgency === 0 ? dimColor : countdownColorOverride)
|
||||
readonly property color dimColor: Qt.darker(Color.notifications.text, 1.4)
|
||||
readonly property color bodyColor: Qt.darker(Color.notifications.text, 1.15)
|
||||
readonly property color hoverColor: Qt.rgba(Color.notifications.text.r, Color.notifications.text.g, Color.notifications.text.b, 0.14)
|
||||
readonly property color accentColor: urgency === 2 ? Color.urgent : (urgency === 0 ? dimColor : Color.notifications.countdown)
|
||||
|
||||
function sanitizeBody(s) {
|
||||
return String(s).replace(/<img[^>]*>/gi, "")
|
||||
@@ -92,8 +85,8 @@ Rectangle {
|
||||
// for symmetry except when the progress bar replaces it.
|
||||
implicitHeight: mainColumn.implicitHeight + border.width * 2
|
||||
radius: cornerRadius
|
||||
color: backgroundColorOverride
|
||||
border.color: urgency === 2 ? Color.urgent : borderColorOverride
|
||||
color: Color.notifications.background
|
||||
border.color: urgency === 2 ? Color.urgent : Color.notifications.border
|
||||
border.width: 2
|
||||
clip: true
|
||||
|
||||
@@ -145,7 +138,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: root.border.width
|
||||
color: root.urgency === 2 ? Color.urgent : root.borderColorOverride
|
||||
color: root.urgency === 2 ? Color.urgent : Color.notifications.border
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -194,7 +187,7 @@ Rectangle {
|
||||
anchors.centerIn: parent
|
||||
visible: root.hasGlyph && smallIconImage.status !== Image.Ready
|
||||
text: root.glyph
|
||||
color: root.textColorOverride
|
||||
color: Color.notifications.text
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: 18
|
||||
}
|
||||
@@ -210,7 +203,7 @@ Rectangle {
|
||||
visible: root.summary.length > 0
|
||||
text: root.summary
|
||||
font.family: root.fontFamily
|
||||
color: root.textColorOverride
|
||||
color: Color.notifications.text
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -243,7 +236,7 @@ Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
height: 3
|
||||
color: root.borderColorOverride
|
||||
color: Color.notifications.border
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
|
||||
Reference in New Issue
Block a user