Files
OSGKeyboard/OSGKeyboardExt/Services/EditHintScheduler.swift
Rocky 9f308fadd2 feat(keyboard): ship AI hint carousel, home library cards, and clipboard polish
Rotate AI idle suggestions with optional remote packs, move history/dictionary onto self-sizing Home preview cards, harden clipboard capture/prompting, and simplify keyboard chrome by dropping most liquid-glass shadows.
2026-08-13 01:00:51 +08:00

72 lines
1.7 KiB
Swift

// EditHintScheduler.swift
// OSGKeyboard · Keyboard Extension
//
// Owns the edit-hint lifetime so every producer shares one expiration order.
import Foundation
import OSGKeyboardShared
@MainActor
final class EditHintScheduler {
typealias Sleeper = @MainActor (Duration) async -> Void
private let state: KeyboardState
private let sleeper: Sleeper
private var task: Task<Void, Never>?
private var generation: UInt64 = 0
init(
state: KeyboardState,
sleeper: @escaping Sleeper = { duration in
try? await Task.sleep(for: duration)
}
) {
self.state = state
self.sleeper = sleeper
}
func show(message: String, isPositive: Bool, duration: Duration) {
let scheduledGeneration = advanceGeneration()
task?.cancel()
state.editHint = message
state.editHintIsPositive = isPositive
let sleeper = sleeper
task = Task { @MainActor [weak self, sleeper] in
await sleeper(duration)
guard let self, self.generation == scheduledGeneration else {
return
}
self.task = nil
self.clearHint()
}
}
func clearPositive() {
guard state.editHintIsPositive else { return }
advanceGeneration()
task?.cancel()
task = nil
clearHint()
}
func invalidate() {
advanceGeneration()
task?.cancel()
task = nil
clearHint()
}
@discardableResult
private func advanceGeneration() -> UInt64 {
generation &+= 1
return generation
}
private func clearHint() {
state.editHint = nil
state.editHintIsPositive = false
}
}