2021-11-09 17:25:40 -08:00
|
|
|
import SwiftUI
|
|
|
|
import CasePaths
|
|
|
|
|
|
|
|
/// taken largely from: https://github.com/pointfreeco/episode-code-samples/blob/main/0167-navigation-pt8/SwiftUINavigation/SwiftUINavigation/SwiftUIHelpers.swift
|
|
|
|
extension Binding {
|
|
|
|
func isPresent<Wrapped>() -> Binding<Bool>
|
|
|
|
where Value == Wrapped? {
|
|
|
|
.init(
|
|
|
|
get: { self.wrappedValue != nil },
|
|
|
|
set: { isPresented in
|
|
|
|
if !isPresented {
|
|
|
|
self.wrappedValue = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func isPresent<Enum, Case>(_ casePath: CasePath<Enum, Case>) -> Binding<Bool>
|
|
|
|
where Value == Enum? {
|
|
|
|
Binding<Bool>(
|
|
|
|
get: {
|
|
|
|
if let wrappedValue = self.wrappedValue, casePath.extract(from: wrappedValue) != nil {
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
set: { isPresented in
|
|
|
|
if !isPresented {
|
|
|
|
self.wrappedValue = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func `case`<Enum, Case>(_ casePath: CasePath<Enum, Case>) -> Binding<Case?>
|
|
|
|
where Value == Enum? {
|
|
|
|
Binding<Case?>(
|
|
|
|
get: {
|
|
|
|
guard
|
|
|
|
let wrappedValue = self.wrappedValue,
|
|
|
|
let `case` = casePath.extract(from: wrappedValue)
|
|
|
|
else { return nil }
|
|
|
|
return `case`
|
|
|
|
},
|
2023-02-15 14:27:52 -08:00
|
|
|
|
2021-11-09 17:25:40 -08:00
|
|
|
set: { `case` in
|
|
|
|
if let `case` = `case` {
|
|
|
|
self.wrappedValue = casePath.embed(`case`)
|
|
|
|
} else {
|
|
|
|
self.wrappedValue = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func didSet(_ callback: @escaping (Value) -> Void) -> Self {
|
|
|
|
.init(
|
|
|
|
get: { self.wrappedValue },
|
|
|
|
set: {
|
|
|
|
self.wrappedValue = $0
|
|
|
|
callback($0)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
init?(unwrap binding: Binding<Value?>) {
|
|
|
|
guard let wrappedValue = binding.wrappedValue
|
|
|
|
else { return nil }
|
|
|
|
|
|
|
|
self.init(
|
|
|
|
get: { wrappedValue },
|
|
|
|
set: { binding.wrappedValue = $0 }
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-11-21 06:28:08 -08:00
|
|
|
func map<T>(extract: @escaping (Value) -> T, embed: @escaping (T) -> Value) -> Binding<T> {
|
|
|
|
Binding<T>(
|
|
|
|
get: { extract(wrappedValue) },
|
|
|
|
set: { wrappedValue = embed($0) }
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func compactMap<T>(extract: @escaping (Value) -> T, embed: @escaping (T) -> Value?) -> Binding<T> {
|
2021-11-09 17:25:40 -08:00
|
|
|
Binding<T>(
|
|
|
|
get: { extract(wrappedValue) },
|
|
|
|
set: {
|
|
|
|
guard let value = embed($0) else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
wrappedValue = value
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|