diff --git a/Package.resolved b/Package.resolved index 429c0af..3e7f54e 100644 --- a/Package.resolved +++ b/Package.resolved @@ -24,8 +24,8 @@ "repositoryURL": "https://github.com/SwiftRex/SwiftRex.git", "state": { "branch": null, - "revision": "660a3c805e7752e44674305174e637bd398c36ed", - "version": "0.8.0" + "revision": "c51328031f943d8f055dbcb738bc66915825b8cc", + "version": "0.8.8" } } ] diff --git a/Package.swift b/Package.swift index b9d24c9..a91d4b9 100644 --- a/Package.swift +++ b/Package.swift @@ -24,10 +24,7 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), - .package(url: "https://github.com/SwiftRex/SwiftRex.git", from: "0.8.0"), -// .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.46.3"), -// .package(url: "https://github.com/Realm/SwiftLint", from: "0.40.3"), -// .package(url: "https://github.com/orta/Komondor", from: "1.0.0"), + .package(url: "https://github.com/SwiftRex/SwiftRex.git", .upToNextMajor(from: "0.8.8")), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. @@ -42,20 +39,3 @@ let package = Package( ), ] ) - -// The settings for the git hooks for our repo -//#if canImport(PackageConfig) -// import PackageConfig -// -// PackageConfiguration([ -// "komondor": [ -// // When someone has run `git commit`, first run -// // SwiftFormat and the auto-correcter for SwiftLint -// "pre-commit": [ -// "swift run swiftformat .", -// "swift run swiftlint autocorrect", -// ], -// ], -// ]) -// .write() -//#endif diff --git a/Sources/AppLifecycleMiddleware/AppLifecycleMiddleware.swift b/Sources/AppLifecycleMiddleware/AppLifecycleMiddleware.swift index 2726e9d..6142bd5 100644 --- a/Sources/AppLifecycleMiddleware/AppLifecycleMiddleware.swift +++ b/Sources/AppLifecycleMiddleware/AppLifecycleMiddleware.swift @@ -7,6 +7,7 @@ import UIKit // sourcery: Prism public enum AppLifecycleAction { + case start case didEnterBackground case willEnterForeground case didBecomeActive @@ -27,30 +28,48 @@ public enum AppLifecycle: Equatable { // MARK: - REDUCER extension Reducer where ActionType == AppLifecycleAction, StateType == AppLifecycle { - public static let lifecycle = Reducer { action, state in + public static let lifecycle = Reducer.reduce { action, state in switch (state, action) { - case (.backgroundActive, .didEnterBackground): return state - case (.backgroundInactive, .didEnterBackground): return state - case (.foregroundActive, .didEnterBackground): return .backgroundActive - case (.foregroundInactive, .didEnterBackground): return .backgroundInactive - - case (.backgroundActive, .willEnterForeground): return .foregroundActive - case (.backgroundInactive, .willEnterForeground): return .foregroundInactive - case (.foregroundActive, .willEnterForeground): return state - case (.foregroundInactive, .willEnterForeground): return state - - case (.backgroundActive, .didBecomeActive): return state - case (.backgroundInactive, .didBecomeActive): return .backgroundActive - case (.foregroundActive, .didBecomeActive): return state - case (.foregroundInactive, .didBecomeActive): return .foregroundActive - - case (.backgroundActive, .willBecomeInactive): return .backgroundInactive - case (.backgroundInactive, .willBecomeInactive): return state - case (.foregroundActive, .willBecomeInactive): return .foregroundInactive - case (.foregroundInactive, .willBecomeInactive): return state - - case (_, .didFinishLaunchingWithOptions): return state - case (_, .willFinishLaunchingWithOptions): return state + case (_, .start): + return + + case (.backgroundActive, .didEnterBackground), + (.backgroundInactive, .didEnterBackground): + return + case (.foregroundActive, .didEnterBackground): + state = .backgroundActive + case (.foregroundInactive, .didEnterBackground): + state = .backgroundInactive + + case (.backgroundActive, .willEnterForeground): + state = .foregroundActive + case (.backgroundInactive, .willEnterForeground): + state = .foregroundInactive + case (.foregroundActive, .willEnterForeground), + (.foregroundInactive, .willEnterForeground): + return + + case (.backgroundActive, .didBecomeActive): + return + case (.backgroundInactive, .didBecomeActive): + state = .backgroundActive + case (.foregroundActive, .didBecomeActive): + return + case (.foregroundInactive, .didBecomeActive): + state = .foregroundActive + + case (.backgroundActive, .willBecomeInactive): + state = .backgroundInactive + case (.backgroundInactive, .willBecomeInactive): + return + case (.foregroundActive, .willBecomeInactive): + state = .foregroundInactive + case (.foregroundInactive, .willBecomeInactive): + return + + case (_, .didFinishLaunchingWithOptions), + (_, .willFinishLaunchingWithOptions): + return } } } @@ -59,16 +78,16 @@ extension Reducer where ActionType == AppLifecycleAction, StateType == AppLifecy // sourcery: AutoMockable, imports = ["Combine", "SwiftRex"] public protocol NotificationPublisher { - func receiveContext( - getState: @escaping GetState, + func start( + state: @escaping GetState, output: AnyActionHandler ) -> AnyCancellable } // MARK: - MIDDLEWARE -public final class AppLifecycleMiddleware: Middleware { - public typealias InputActionType = Never +public final class AppLifecycleMiddleware: MiddlewareProtocol { + public typealias InputActionType = AppLifecycleAction public typealias OutputActionType = AppLifecycleAction public typealias StateType = Void @@ -80,23 +99,19 @@ public final class AppLifecycleMiddleware: Middleware { notificationPublisher = publisher } - public func receiveContext( - getState: @escaping GetState, - output: AnyActionHandler - ) { - cancellable = notificationPublisher.receiveContext(getState: getState, output: output) - } + public func handle(action: AppLifecycleAction, from dispatcher: ActionSource, state: @escaping GetState) -> IO { + guard case .start = action else { return .identity } - public func handle( - action _: InputActionType, - from _: ActionSource, - afterReducer _: inout AfterReducer - ) {} + return IO { [weak self] output in + guard let self = self else { return } + self.cancellable = self.notificationPublisher.start(state: state, output: output) + } + } } extension NotificationCenter: NotificationPublisher { - public func receiveContext( - getState _: @escaping GetState, + public func start( + state _: @escaping GetState, output: AnyActionHandler ) -> AnyCancellable { let notificationCenter = NotificationCenter.default diff --git a/Sources/AppLifecycleMiddleware/AutoMockable.generated.swift b/Sources/AppLifecycleMiddleware/AutoMockable.generated.swift index dd50955..729aae3 100644 --- a/Sources/AppLifecycleMiddleware/AutoMockable.generated.swift +++ b/Sources/AppLifecycleMiddleware/AutoMockable.generated.swift @@ -16,20 +16,20 @@ import Combine import SwiftRex open class NotificationPublisherMock: NotificationPublisher { - //MARK: - receiveContext + //MARK: - start - open var receiveContextGetStateOutputCallsCount = 0 - open var receiveContextGetStateOutputCalled: Bool { - return receiveContextGetStateOutputCallsCount > 0 + open var startStateOutputCallsCount = 0 + open var startStateOutputCalled: Bool { + return startStateOutputCallsCount > 0 } - open var receiveContextGetStateOutputReceivedArguments: (getState: GetState, output: AnyActionHandler)? - open var receiveContextGetStateOutputReturnValue: AnyCancellable! - open var receiveContextGetStateOutputClosure: ((@escaping GetState, AnyActionHandler) -> AnyCancellable)? - - open func receiveContext( getState: @escaping GetState, output: AnyActionHandler ) -> AnyCancellable { - receiveContextGetStateOutputCallsCount += 1 - receiveContextGetStateOutputReceivedArguments = (getState: getState, output: output) - return receiveContextGetStateOutputClosure.map({ $0(getState, output) }) ?? receiveContextGetStateOutputReturnValue + open var startStateOutputReceivedArguments: (state: GetState, output: AnyActionHandler)? + open var startStateOutputReturnValue: AnyCancellable! + open var startStateOutputClosure: ((@escaping GetState, AnyActionHandler) -> AnyCancellable)? + + open func start(state: @escaping GetState, output: AnyActionHandler ) -> AnyCancellable { + startStateOutputCallsCount += 1 + startStateOutputReceivedArguments = (state: state, output: output) + return startStateOutputClosure.map({ $0(state, output) }) ?? startStateOutputReturnValue } } diff --git a/Tests/AppLifecycleMiddlewareTests/AppLifecycleMiddlewareTests.swift b/Tests/AppLifecycleMiddlewareTests/AppLifecycleMiddlewareTests.swift index fdac493..af819de 100644 --- a/Tests/AppLifecycleMiddlewareTests/AppLifecycleMiddlewareTests.swift +++ b/Tests/AppLifecycleMiddlewareTests/AppLifecycleMiddlewareTests.swift @@ -3,18 +3,6 @@ import XCTest final class AppLifecycleMiddlewareTests: XCTestCase { func testAppLifecycleActions() { - let sut = AppLifecycleMiddleware() - var getStateCount = 0 - var dispatchActionCount = 0 - - sut.receiveContext( - getState: { getStateCount += 1 }, - output: .init { _, _ in - dispatchActionCount += 1 - } - ) - - // XCTAssertEqual(AppLifecycleMiddleware().text, "Hello, World!") } static var allTests = [