portico/Sources/Portico/Presentation/DialogPropertySource.swift

71 lines
2.7 KiB
Swift

import Adw
/// The source of a dialog property, either a fixed value or a live binding.
public enum DialogPropertyValue<Value> {
/// A fixed property value applied once when the dialog mounts.
case constant(Value)
/// A live property binding reapplied when its value changes.
case binding(Binding<Value>)
}
/// Supplies a dialog property as a fixed value or a live binding.
public protocol DialogPropertySource<Value> {
/// The value type accepted by this property source.
associatedtype Value
/// Returns the fixed value or binding represented by this source.
var _dialogPropertyValue: DialogPropertyValue<Value> { get }
}
/// Provides a fixed string dialog property value.
extension String: DialogPropertySource {
/// Returns this string as a fixed dialog property value.
public var _dialogPropertyValue: DialogPropertyValue<String> { .constant(self) }
}
/// Provides a fixed Boolean dialog property value.
extension Bool: DialogPropertySource {
/// Returns this Boolean as a fixed dialog property value.
public var _dialogPropertyValue: DialogPropertyValue<Bool> { .constant(self) }
}
/// Provides an integer literal as an `Int32` dialog property value.
extension Int: DialogPropertySource {
/// Returns this integer as a fixed `Int32` value, clamped to the `Int32`
/// range rather than trapping on an out-of-range argument.
public var _dialogPropertyValue: DialogPropertyValue<Int32> {
.constant(Int32(clamping: self))
}
}
/// Provides a fixed `Int32` dialog property value.
extension Int32: DialogPropertySource {
/// Returns this value as a fixed dialog property value.
public var _dialogPropertyValue: DialogPropertyValue<Int32> { .constant(self) }
}
/// Provides a fixed dialog presentation mode.
extension DialogPresentationMode: DialogPropertySource {
/// Returns this mode as a fixed dialog property value.
public var _dialogPropertyValue: DialogPropertyValue<DialogPresentationMode> { .constant(self) }
}
/// Provides a live dialog property value through a Portico binding.
extension Binding: DialogPropertySource {
/// Returns this binding as a live dialog property value.
public var _dialogPropertyValue: DialogPropertyValue<Value> { .binding(self) }
}
/// Applies a static or binding dialog property source using the matching applier.
@MainActor
func appliedDialogProperty<Value>(
_ source: (any DialogPropertySource<Value>)?,
to view: Dialog,
constant: (Dialog, Value) -> Dialog,
binding: (Dialog, Binding<Value>) -> Dialog
) -> Dialog {
guard let source else { return view }
switch source._dialogPropertyValue {
case .constant(let value): return constant(view, value)
case .binding(let bound): return binding(view, bound)
}
}