Files
swiftapp/swift/Sources/App/AppControlService.swift
T

67 lines
2.2 KiB
Swift
Raw Normal View History

2026-04-17 20:46:27 +02:00
import Foundation
protocol AppControlServicing {
func commands() -> AsyncStream<AppNavigationCommand>
}
struct MockBackendControlService: AppControlServicing {
static let controlFileEnvironmentKey = "SOCIALIO_CONTROL_FILE"
static let pollingIntervalEnvironmentKey = "SOCIALIO_CONTROL_POLL_MS"
private let environment: [String: String]
init(environment: [String: String] = ProcessInfo.processInfo.environment) {
self.environment = environment
}
func commands() -> AsyncStream<AppNavigationCommand> {
guard let controlFilePath = environment[Self.controlFileEnvironmentKey]?
.trimmingCharacters(in: .whitespacesAndNewlines),
!controlFilePath.isEmpty else {
return AsyncStream { continuation in
continuation.finish()
}
}
let controlFileURL = URL(fileURLWithPath: controlFilePath)
let pollingInterval = pollingIntervalDuration
return AsyncStream { continuation in
let task = Task.detached(priority: .background) {
var lastAppliedPayload: String?
while !Task.isCancelled {
if let payload = try? String(contentsOf: controlFileURL, encoding: .utf8) {
let trimmedPayload = payload.trimmingCharacters(in: .whitespacesAndNewlines)
if !trimmedPayload.isEmpty,
trimmedPayload != lastAppliedPayload,
let command = AppNavigationCommand.parse(trimmedPayload) {
lastAppliedPayload = trimmedPayload
continuation.yield(command)
}
}
try? await Task.sleep(for: pollingInterval)
}
continuation.finish()
}
continuation.onTermination = { _ in
task.cancel()
}
}
}
private var pollingIntervalDuration: Duration {
guard let rawValue = environment[Self.pollingIntervalEnvironmentKey],
let milliseconds = Int(rawValue),
milliseconds > 0 else {
return .milliseconds(600)
}
return .milliseconds(milliseconds)
}
}