2 Commits
main ... dev

Author SHA1 Message Date
061785d77b feat: Updates tracking state of sensors 2024-11-20 22:45:20 -05:00
c4c4fed4bc feat: Updates tracking state of sensors 2024-11-20 22:43:05 -05:00
3 changed files with 39 additions and 34 deletions

View File

@@ -84,12 +84,11 @@ public struct TemperatureAndHumiditySensor: Identifiable, Sendable {
/// Check whether any of the sensor values have changed and need processed.
///
/// - Note: Setting a value will set to both the temperature and humidity properties.
public var needsProcessed: Bool {
get { $temperature.needsProcessed || $humidity.needsProcessed }
set {
$temperature.needsProcessed = newValue
$humidity.needsProcessed = newValue
}
public var needsProcessed: Bool { $temperature.needsProcessed || $humidity.needsProcessed }
public mutating func setHasProcessed() {
$temperature.setHasProcessed()
$humidity.setHasProcessed()
}
/// Represents the different locations of a temperature and humidity sensor, which can

View File

@@ -5,24 +5,20 @@
@propertyWrapper
public struct TrackedChanges<Value: Sendable>: Sendable {
/// The current tracking state.
private var tracking: TrackingState
/// The current wrapped value.
private var value: Value
/// The current value wrapped in a tracking state.
private var value: TrackingState
/// Used to check if a new value is equal to an old value.
private var isEqual: @Sendable (Value, Value) -> Bool
/// Access to the underlying property that we are wrapping.
public var wrappedValue: Value {
get { value }
get { value.currentValue }
set {
// Check if the new value is equal to the old value.
guard !isEqual(newValue, value) else { return }
guard !isEqual(newValue, value.currentValue) else { return }
// If it's not equal then set it, as well as set the tracking to `.needsProcessed`.
value = newValue
tracking = .needsProcessed
value = .needsProcessed(newValue)
}
}
@@ -37,31 +33,42 @@ public struct TrackedChanges<Value: Sendable>: Sendable {
needsProcessed: Bool = false,
isEqual: @escaping @Sendable (Value, Value) -> Bool
) {
self.value = wrappedValue
self.tracking = needsProcessed ? .needsProcessed : .hasProcessed
self.value = .init(wrappedValue, needsProcessed: needsProcessed)
self.isEqual = isEqual
}
/// Represents whether a wrapped value has changed and needs processed or not.
enum TrackingState {
fileprivate enum TrackingState {
case hasProcessed(Value)
case needsProcessed(Value)
/// The state when nothing has changed and we've already processed the current value.
case hasProcessed
init(_ value: Value, needsProcessed: Bool) {
if needsProcessed {
self = .needsProcessed(value)
} else {
self = .hasProcessed(value)
}
}
/// The state when the value has changed and has not been processed yet.
case needsProcessed
var currentValue: Value {
switch self {
case let .hasProcessed(value):
return value
case let .needsProcessed(value):
return value
}
}
var needsProcessed: Bool {
guard case .needsProcessed = self else { return false }
return true
}
}
/// Whether the value needs processed.
public var needsProcessed: Bool {
get { tracking == .needsProcessed }
set {
if newValue {
tracking = .needsProcessed
} else {
tracking = .hasProcessed
}
}
var needsProcessed: Bool { value.needsProcessed }
mutating func setHasProcessed() {
value = .hasProcessed(value.currentValue)
}
public var projectedValue: Self {
@@ -95,6 +102,5 @@ extension TrackedChanges: Hashable where Value: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(wrappedValue)
hasher.combine(needsProcessed)
}
}

View File

@@ -172,7 +172,7 @@ private extension Array where Element == TemperatureAndHumiditySensor {
guard let index = firstIndex(where: { $0.id == sensor.id }) else {
throw SensorNotFoundError()
}
self[index].needsProcessed = false
self[index].setHasProcessed()
}
}