cleanup Theme

This commit is contained in:
2026-07-12 00:08:46 +02:00
parent 0ed9e4dbf2
commit d0b945574a
13 changed files with 84 additions and 127 deletions
+1 -5
View File
@@ -33,11 +33,7 @@ let package = Package(
], ],
resources: [ resources: [
.process("config.toml"), .process("config.toml"),
.process("Themes/voltage.toml"), .process("Models/Theme/theme.toml"),
// .process("Themes/catppuccin-mocha.toml"),
.process("Themes/dracula.toml"),
// .process("Themes/gruvbox.toml"),
// .process("Themes/tokyo-night.toml"),
], ],
), ),
.testTarget( .testTarget(
+2 -2
View File
@@ -37,10 +37,10 @@ final class PHController: ObservableObject {
// Style // Style
extension PHController { extension PHController {
func style(for block: PHBlock) -> PHTheme.Style { func style(for block: PHBlock) -> PHThemeStyle {
guard let style = theme.styles.first(where: { $0.name == block.styleName }) else { guard let style = theme.styles.first(where: { $0.name == block.styleName }) else {
guard let defaultStyle = theme.styles.first(where: { $0.name == "default" }) else { guard let defaultStyle = theme.styles.first(where: { $0.name == "default" }) else {
return PHTheme.Style.default return PHThemeStyle.default
} }
return defaultStyle return defaultStyle
} }
+1 -1
View File
@@ -9,7 +9,7 @@ final class PHBlock: ObservableObject, Decodable, Identifiable {
let command: String let command: String
let name: String? let name: String?
let styleName: String? let styleName: String?
@Published var style: PHTheme.Style = .default @Published var style: PHThemeStyle = .default
let refresh: Double? let refresh: Double?
let centered: Bool? let centered: Bool?
var debug: Bool = false var debug: Bool = false
-53
View File
@@ -1,53 +0,0 @@
struct PHTheme: Decodable {
static let `default` = "dracula"
static let bundled = [
"voltage",
"catppuccin-mocha",
"dracula",
"gruvbox",
"tokyo-night",
]
let window: Window
let styles: [Style]
enum CodingKeys: String, CodingKey {
case window
case styles = "style"
}
}
// Window
extension PHTheme {
struct Window: Decodable {
let hasShadow: Bool
let blur: Double
enum CodingKeys: String, CodingKey {
case hasShadow = "shadow"
case blur
}
}
}
// Style
extension PHTheme {
struct Style: Decodable {
let name: String
let foreground: PHTheme.Color
let background: PHTheme.Color
let padding: PHTheme.Padding
static let `default`: Self = {
Style(
name: "_default",
foreground: .init(color: "#000000", alpha: nil),
background: .init(color: "#ffffff", alpha: nil),
padding: .init(leading: 10, trailing: 10)
)
}()
}
}
@@ -1,27 +0,0 @@
import SwiftUI
extension PHTheme {
struct Color: Decodable, ShapeStyle {
typealias Resolved = SwiftUI.Color
let color: String
let alpha: Double?
var uiColor: SwiftUI.Color {
SwiftUI.Color(hex: color, opacity: alpha)
}
var nsColor: NSColor? {
guard let cgColor else { return nil }
return NSColor(cgColor: cgColor)
}
var cgColor: CGColor? {
uiColor.cgColor
}
func resolve(in environment: EnvironmentValues) -> SwiftUI.Color {
uiColor
}
}
}
@@ -1,12 +0,0 @@
extension PHTheme {
struct Padding: Decodable {
let leading: Double
let trailing: Double
var total: Double { leading + trailing }
static var zero: Padding {
Self.init(leading: 0, trailing: 0)
}
}
}
@@ -1,11 +1,24 @@
import Foundation import Foundation
import TOML import TOML
struct PHTheme: Decodable {
let window: PHThemeWindow
let styles: [PHThemeStyle]
enum CodingKeys: String, CodingKey {
case window
case styles = "style"
}
}
// Loading
extension PHTheme { extension PHTheme {
/// Load theme from the default path (~/.config/phbar/theme.toml). /// Load theme from the config directory (~/.config/phbar/themes/).
/// If the file doesn't exist or fails to parse, defaults are used (non-fatal). /// If the file doesn't exist or fails to parse, defaults are used (non-fatal).
static func load(_ theme: String?) throws -> PHTheme { static func load(_ theme: String?) throws -> PHTheme {
let theme = theme ?? Self.default guard let theme else { return try loadFromBundle() }
let url = FileManager.default.homeDirectoryForCurrentUser.appending( let url = FileManager.default.homeDirectoryForCurrentUser.appending(
path: ".config/phbar/themes/\(theme).toml" path: ".config/phbar/themes/\(theme).toml"
) )
@@ -13,16 +26,16 @@ extension PHTheme {
if FileManager.default.fileExists(atPath: url.relativePath) { if FileManager.default.fileExists(atPath: url.relativePath) {
return try load(from: url) return try load(from: url)
} else { } else {
return try load(bundled: theme) return try loadFromBundle()
} }
} }
/// Load a bundled theme. /// Load the bundled theme.
/// If the theme doesn't exist or fails to parse, the execution is interrupted. /// If the theme doesn't exist or fails to parse, the execution is interrupted.
static func load(bundled theme: String) throws -> PHTheme { static private func loadFromBundle() throws -> PHTheme {
guard guard
let defaultConfig = Bundle.module.url( let defaultConfig = Bundle.module.url(
forResource: theme, forResource: "theme",
withExtension: "toml" withExtension: "toml"
)?.resolvingSymlinksInPath() )?.resolvingSymlinksInPath()
else { else {
@@ -33,7 +46,7 @@ extension PHTheme {
/// Load theme from a file at URL. /// Load theme from a file at URL.
/// If the file doesn't exist or fails to parse, the execution is interrupted. /// If the file doesn't exist or fails to parse, the execution is interrupted.
static func load(from url: URL) throws -> PHTheme { static private func load(from url: URL) throws -> PHTheme {
do { do {
let data = try Data(contentsOf: url) let data = try Data(contentsOf: url)
guard let contents = String(data: data, encoding: .utf8), !contents.isEmpty else { guard let contents = String(data: data, encoding: .utf8), !contents.isEmpty else {
@@ -47,7 +60,7 @@ extension PHTheme {
/// Load theme from a TOML string. /// Load theme from a TOML string.
/// If the content fails to parse, the execution is interrupted. /// If the content fails to parse, the execution is interrupted.
static func load(from contents: String) throws -> PHTheme { static private func load(from contents: String) throws -> PHTheme {
do { do {
let decoder = TOMLDecoder() let decoder = TOMLDecoder()
return try decoder.decode(PHTheme.self, from: contents) return try decoder.decode(PHTheme.self, from: contents)
@@ -0,0 +1,25 @@
import SwiftUI
struct PHThemeColor: Decodable, ShapeStyle {
typealias Resolved = SwiftUI.Color
let color: String
let alpha: Double?
var uiColor: SwiftUI.Color {
SwiftUI.Color(hex: color, opacity: alpha)
}
var nsColor: NSColor? {
guard let cgColor else { return nil }
return NSColor(cgColor: cgColor)
}
var cgColor: CGColor? {
uiColor.cgColor
}
func resolve(in environment: EnvironmentValues) -> SwiftUI.Color {
uiColor
}
}
@@ -0,0 +1,10 @@
struct PHThemePadding: Decodable {
let leading: Double
let trailing: Double
var total: Double { leading + trailing }
static var zero: PHThemePadding {
Self.init(leading: 0, trailing: 0)
}
}
@@ -0,0 +1,15 @@
struct PHThemeStyle: Decodable {
let name: String
let foreground: PHThemeColor
let background: PHThemeColor
let padding: PHThemePadding
static let `default`: Self = {
PHThemeStyle(
name: "_default",
foreground: .init(color: "#000000", alpha: nil),
background: .init(color: "#ffffff", alpha: nil),
padding: .init(leading: 10, trailing: 10)
)
}()
}
@@ -0,0 +1,9 @@
struct PHThemeWindow: Decodable {
let hasShadow: Bool
let blur: Double
enum CodingKeys: String, CodingKey {
case hasShadow = "shadow"
case blur
}
}
-19
View File
@@ -1,19 +0,0 @@
# phbar theme file ~ Dracula
#
# Place at ~/.config/phbar/themes/dracula.toml
[window]
shadow = false
blur = 10.0
[[style]]
name = "default"
foreground = { color = "#f8f8f2" }
background = { color = "#000000", alpha = 0.5 }
padding = { leading = 0.0, trailing = 0.0 }
[[style]]
name = "tinted"
foreground = { color = "#282a36" }
background = { color = "#bd93f9" }
padding = { leading = 10.0, trailing = 10.0 }