aboutsummaryrefslogtreecommitdiff
path: root/Sources/phbar/Models/Block.swift
diff options
context:
space:
mode:
authorTommaso Negri <me@tommasongr.com>2026-07-27 16:18:34 +0200
committerTommaso Negri <me@tommasongr.com>2026-07-27 16:18:34 +0200
commit535b42a7b8304340182ca1367aa42f047eb06bff (patch)
tree88e15512f874a00886fc7b97861feb5e92c6aaf5 /Sources/phbar/Models/Block.swift
parent6d165c74a5a6b471c155b12ab15ef833d6b2aa36 (diff)
downloadbar-535b42a7b8304340182ca1367aa42f047eb06bff.tar.gz
bar-535b42a7b8304340182ca1367aa42f047eb06bff.zip
scaffold basic structure
Diffstat (limited to 'Sources/phbar/Models/Block.swift')
-rw-r--r--Sources/phbar/Models/Block.swift65
1 files changed, 65 insertions, 0 deletions
diff --git a/Sources/phbar/Models/Block.swift b/Sources/phbar/Models/Block.swift
new file mode 100644
index 0000000..7eca7c9
--- /dev/null
+++ b/Sources/phbar/Models/Block.swift
@@ -0,0 +1,65 @@
+import Foundation
+
+@MainActor
+final class Block: ObservableObject, Identifiable {
+ let id = UUID()
+
+ let name: String
+ let placement: Config.Block.Placement
+ let command: String
+ let interval: Double?
+
+ @Published var cells: [String] = []
+
+ private var tick: Task<Void, Never>?
+
+ init(name: String, placement: Config.Block.Placement, command: String, interval: Double? = nil) {
+ self.name = name
+ self.placement = placement
+ self.command = command
+ self.interval = interval
+ }
+
+ /// Initial paint + interval timer.
+ func start() {
+ runScript()
+ startTick()
+ }
+
+ /// Re-run the command and update the cells on the main actor.
+ func runScript() {
+ let command = self.command
+ Task.detached(priority: .utility) { [weak self] in
+ let cells = Runner.run(command)
+ await self?.apply(cells)
+ }
+ }
+
+ /// Stop the interval timer.
+ func stop() {
+ tick?.cancel()
+ }
+
+ @MainActor
+ private func apply(_ cells: [String]) {
+ self.cells = cells
+ }
+
+ private func startTick() {
+ guard let interval, interval > 0 else { return }
+ tick = Task { [weak self] in
+ while !Task.isCancelled {
+ try? await Task.sleep(for: .seconds(interval))
+ if Task.isCancelled { break }
+ self?.runScript()
+ }
+ }
+ }
+}
+
+extension Config.Block {
+ @MainActor
+ var resolved: phbar.Block {
+ .init(name: name, placement: placement, command: command, interval: interval)
+ }
+}