Skip to content

Instantly share code, notes, and snippets.

@mbrandonw
Last active September 19, 2024 20:05
Show Gist options
  • Save mbrandonw/08b756da53ebf4e0612f0e078d2ca850 to your computer and use it in GitHub Desktop.
Save mbrandonw/08b756da53ebf4e0612f0e078d2ca850 to your computer and use it in GitHub Desktop.
/*
The following feature is 100% pure Swift code. It compiles for a multitude of platforms,
include iOS, macOS, Linux, Windows, Wasm, and more. It encapsulates all of the logic
and behavior for the feature so that the view can concentrate on just the UI by reading
state from the model and invoking methods on the model.
*/
import Dependencies
import FactClient
import Perception
import SwiftNavigation
@MainActor
@Perceptible
public class CounterModel: HashableObject {
@PerceptionIgnored
@Dependency(FactClient.self) var factClient
@PerceptionIgnored
@Dependency(\.continuousClock) var clock
public var alert: AlertState<Never>? {
didSet {
if alert == nil, shouldResumeTimerAfterFactDismissal {
shouldResumeTimerAfterFactDismissal = false
startTimer()
}
}
}
public var count = 0
public var factIsLoading = false
private var timerTask: Task<Void, Error>?
private var shouldResumeTimerAfterFactDismissal = false
public var isTimerRunning: Bool { timerTask != nil }
public init() {}
public func incrementButtonTapped() {
count += 1
alert = nil
}
public func decrementButtonTapped() {
count -= 1
alert = nil
}
public func factButtonTapped() async {
alert = nil
factIsLoading = true
defer { factIsLoading = false }
shouldResumeTimerAfterFactDismissal = isTimerRunning
stopTimer()
do {
try await Task.sleep(for: .seconds(1))
let fact = try await factClient.fetch(count)
alert = AlertState {
TextState("Fact")
} message: {
TextState(fact)
}
} catch {
}
}
public func toggleTimerButtonTapped() {
if isTimerRunning {
stopTimer()
} else {
startTimer()
}
}
private func startTimer() {
timerTask?.cancel()
timerTask = Task {
for await _ in clock.timer(interval: .seconds(1)) {
count += 1
}
}
}
private func stopTimer() {
timerTask?.cancel()
timerTask = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment