diff options
| author | Tommaso Negri <me@tommasongr.com> | 2026-08-07 23:52:00 +0200 |
|---|---|---|
| committer | Tommaso Negri <me@tommasongr.com> | 2026-08-07 23:52:00 +0200 |
| commit | 618799ee703cc4addc7e50550ccf87b4b4cc7780 (patch) | |
| tree | edf2c51bd21144805538e8962a2ee6826f3884a6 /Sources/phbar/Models | |
| parent | 1268a436aea11d998289c41266059929a68d61e6 (diff) | |
| download | bar-618799ee703cc4addc7e50550ccf87b4b4cc7780.tar.gz bar-618799ee703cc4addc7e50550ccf87b4b4cc7780.zip | |
make Cell a proper entity
Diffstat (limited to 'Sources/phbar/Models')
| -rw-r--r-- | Sources/phbar/Models/Block.swift | 48 | ||||
| -rw-r--r-- | Sources/phbar/Models/Cell.swift | 46 |
2 files changed, 89 insertions, 5 deletions
diff --git a/Sources/phbar/Models/Block.swift b/Sources/phbar/Models/Block.swift index 7eca7c9..95c4ada 100644 --- a/Sources/phbar/Models/Block.swift +++ b/Sources/phbar/Models/Block.swift @@ -1,15 +1,46 @@ import Foundation +/// A named, self-updating unit of the bar. +/// +/// Each block runs a shell command on an optional timer, +/// splits its stdout into ``Cell`` values, and publishes +/// them for rendering. Blocks are identified by ``name`` +/// so they can be refreshed on demand via Darwin +/// notifications (see ``Notifier``). @MainActor final class Block: ObservableObject, Identifiable { + /// Stable identity for SwiftUI diffing. let id = UUID() + /// Identifier used for manual updates via Darwin + /// notifications. + /// + /// Multiple blocks can share the same name. + /// In such case, a single notification will refresh + /// all of them. let name: String + + /// Whether the block is anchored to the left or right + /// side of the bar. let placement: Config.Block.Placement + + /// The shell command to execute for producing the cells. + /// + /// Can be an inline expression or a path to an executable + /// script. Inherits the environment of the phbar process. let command: String + + /// Refresh interval in seconds, or `nil` for a one-shot block. + /// + /// A one-shot block can still be manually refreshed via + /// a Darwin notification (see ``Notifier``). let interval: Double? - @Published var cells: [String] = [] + /// The current cells produced by the last command execution. + /// + /// SwiftUI observes this `@Published` property and re-renders + /// the view tree automatically. + @Published var cells: [Cell] = [] private var tick: Task<Void, Never>? @@ -30,8 +61,8 @@ final class Block: ObservableObject, Identifiable { func runScript() { let command = self.command Task.detached(priority: .utility) { [weak self] in - let cells = Runner.run(command) - await self?.apply(cells) + let lines = Runner.run(command) + await self?.apply(lines) } } @@ -40,11 +71,18 @@ final class Block: ObservableObject, Identifiable { tick?.cancel() } + /// Replace the current cells with freshly parsed lines. + /// + /// Each line becomes a ``Cell``. This is always called + /// on the main actor so SwiftUI sees the update immediately. @MainActor - private func apply(_ cells: [String]) { - self.cells = cells + private func apply(_ lines: [String]) { + self.cells = lines.map { Cell(rawValue: $0) } } + /// Start the interval timer that re-runs the command periodically. + /// + /// Does nothing when ``interval`` is `nil` or ≤ 0. private func startTick() { guard let interval, interval > 0 else { return } tick = Task { [weak self] in diff --git a/Sources/phbar/Models/Cell.swift b/Sources/phbar/Models/Cell.swift new file mode 100644 index 0000000..789f615 --- /dev/null +++ b/Sources/phbar/Models/Cell.swift @@ -0,0 +1,46 @@ +import Foundation +import SwiftUI + +/// A thin wrapper around a single text line captured +/// by a block. +/// +/// When a block executes the command it captures stdout +/// and splits each line into a cell. Each cell is then +/// laid out horizontally respecting the order. +/// +/// Besides the underlying text value, a cell holds an +/// highlighted status that, if true, applies the special +/// background color defined in `Config.swift`. +/// You can set the highlight at runtime by prefixing the +/// text line with the special notation `!!`. +/// +/// E.g: `echo "!! $(date "+%a %d, %H:%M:%S") "` +/// +/// Highlight can have multiple use cases, but it was +/// imagined specifically for distinguishing a single cell +/// within a group. For example when you want to show which +/// workspace is currently active. +struct Cell: RawRepresentable, Identifiable { + /// Stable identity for SwiftUI diffing. + let id = UUID() + + /// The represented text content. + let rawValue: String + + /// Whether the cell is highlighted or not. + let highlighted: Bool + + /// The background color derived from the highlighted state. + /// + /// Returns `Config.highlight` when the cell is highlighted, + /// otherwise `.clear` so the underlying bar background + /// shows through. + var background: Color { + highlighted ? Config.highlight : .clear + } + + init(rawValue: String) { + self.highlighted = rawValue.hasPrefix("!!") + self.rawValue = highlighted ? String(rawValue.dropFirst(2)) : rawValue + } +} |
