diff --git a/Loop/Public/FeedbackLoop.swift b/Loop/Public/FeedbackLoop.swift index 3763807..b16e243 100644 --- a/Loop/Public/FeedbackLoop.swift +++ b/Loop/Public/FeedbackLoop.swift @@ -453,6 +453,17 @@ extension Loop { } } + public func autoconnect(followingChangesIn predicate: @escaping (State) -> Bool) -> Feedback { + return Feedback { state, consumer in + self.events( + state + .skipRepeats { predicate($0.0) == predicate($1.0) } + .flatMap(.latest) { predicate($0.0) ? state.filter { predicate($0.0) } : .empty }, + consumer + ) + } + } + public static func combine(_ feedbacks: Loop.Feedback...) -> Feedback { return Feedback { state, consumer in feedbacks.map { feedback in diff --git a/LoopTests/FeedbackVariantTests.swift b/LoopTests/FeedbackVariantTests.swift index 62ed2cb..f5f5389 100644 --- a/LoopTests/FeedbackVariantTests.swift +++ b/LoopTests/FeedbackVariantTests.swift @@ -174,4 +174,39 @@ class FeedbackVariantTests: XCTestCase { loop.send("world") expect(hasCancelled) == true } + + func test_autoconnect_disposes_and_restores_flows_according_to_predicate() { + + let loop = Loop( + initial: "", + reducer: { content, string in + content = string + }, + feedbacks: [ + Loop.Feedback + .init( + lensing: { $0.hasPrefix("hello") ? $0 : nil }, + effects: { SignalProducer(value: $0.uppercased()) } + ) + .autoconnect(followingChangesIn: { $0.contains("disconnect") == false }) + ] + ) + + expect(loop.box._current) == "" + + // This should trigger an uppercased event + loop.send("hello1") + expect(loop.box._current) == "HELLO1" + + loop.send("hello2") + expect(loop.box._current) == "HELLO2" + + // This should lead to feedabck "disconnection", which in turn should cancel and disable the uppercasing effect. + loop.send("hello disconnect") + expect(loop.box._current) == "hello disconnect" + + // This should lead feedback "connection", which in turn should reestablish the uppercasing effect. + loop.send("hello3") + expect(loop.box._current) == "HELLO3" + } }