diff --git a/src/Cord.Button.swift b/src/Cord.Button.swift new file mode 100644 index 0000000..5668e5b --- /dev/null +++ b/src/Cord.Button.swift @@ -0,0 +1,16 @@ +import Combine + +extension Cord { + final class Button: ObservableObject { + let press = PassthroughSubject() + var subscriptions = [AnyCancellable]() + + init(_ key: String) { + Bus.send( + key, + press.eraseToAnyPublisher(), + sub: &subscriptions + ) + } + } +} diff --git a/src/Cord.ReadOnly.swift b/src/Cord.ReadOnly.swift new file mode 100644 index 0000000..ccb7560 --- /dev/null +++ b/src/Cord.ReadOnly.swift @@ -0,0 +1,20 @@ +import Combine + +extension Cord { + final class ReadOnly: ObservableObject { + @Published var value: T + var subscriptions = [AnyCancellable]() + + init( + _ key: String, + _ defaultValue: T + ) { + value = defaultValue + Bus.receive( + [key], + { [weak self] (_, v: T) in self?.value = v }, + sub: &subscriptions + ) + } + } +} diff --git a/src/Cord.TextField.swift b/src/Cord.TextField.swift index 27ec368..ce5c5cf 100644 --- a/src/Cord.TextField.swift +++ b/src/Cord.TextField.swift @@ -12,7 +12,7 @@ extension Cord { ) { Bus.send( textUI, - $value.compactMap(onlyUIText).eraseToAnyPublisher(), + $value.removeDuplicates().compactMap(onlyUIText).eraseToAnyPublisher(), sub: &subscriptions ) diff --git a/src/MeetupId.swift b/src/MeetupId.swift index 4db3661..f0a609c 100644 --- a/src/MeetupId.swift +++ b/src/MeetupId.swift @@ -7,6 +7,10 @@ enum MeetupId { case meetupIdTextUI } + static func onlyAllowJoin(_ s: String) -> Bool? { + s.hasPrefix("123") + } + static func onlyFormat(_ s: String) -> String? { let digits = s.components(separatedBy: NSCharacterSet.decimalDigits.inverted).reduce("") { $0 + $1 } var r = "" diff --git a/src/V.swift b/src/V.swift index f45e3a2..3b3e4d5 100644 --- a/src/V.swift +++ b/src/V.swift @@ -1,27 +1,32 @@ import SwiftUI struct V: View { - @StateObject var tf = Cord.TextField("text.app", "text.ui") - @StateObject var vm = VM() + @StateObject var isJoinAvailable = Cord.ReadOnly("joinAvailable", false) + @StateObject var join = Cord.Button("join") + @StateObject var textF = Cord.TextField("text.app", "text.ui") + let test = Bus.Processor("text.ui", "joinAvailable", MeetupId.onlyAllowJoin) var body: some View { VStack { HStack { Text("Check text field:") - Text("'\(tf.value)'") + Text("'\(textF.value)'") .fontWeight(.bold) } - TextField("Binding-3", value: $tf.value, formatter: TextFieldValueOwner()) + TextField("Binding-3", value: $textF.value, formatter: TextFieldValueOwner()) .padding(8) .border(Color.blue, width: 2) - Button(action: vm.join.send) { + Button(action: join.press.send) { Text("Join") .padding(8) - .border(vm.isJoinAvailable ? Color.green : Color.red, width: 4) + .border( + isJoinAvailable.value ? Color.green : Color.gray, + width: isJoinAvailable.value ? 4 : 1 + ) } - + .disabled(!isJoinAvailable.value) } .frame(width: 320) .padding() diff --git a/src/VM.swift b/src/VM.swift index fb5849e..9b28a01 100644 --- a/src/VM.swift +++ b/src/VM.swift @@ -10,8 +10,7 @@ final class VM: ObservableObject { MeetupId.onlyFormat ) */ - var isJoinAvailable = true - let join = PassthroughSubject() + var isJoinAvailable = false var subscriptions = [AnyCancellable]() init() {