diff --git a/Sources/FuturedArchitecture/Architecture/Coordinator.swift b/Sources/FuturedArchitecture/Architecture/Coordinator.swift index fa581b5..e92435b 100644 --- a/Sources/FuturedArchitecture/Architecture/Coordinator.swift +++ b/Sources/FuturedArchitecture/Architecture/Coordinator.swift @@ -11,6 +11,7 @@ public protocol Coordinator: ObservableObject { @ViewBuilder static func rootView(with instance: Self) -> RootView + @MainActor var modalCover: ModalCoverModel? { get set } @ViewBuilder @@ -19,7 +20,7 @@ public protocol Coordinator: ObservableObject { } public extension Coordinator { - func present(modal destination: Destination, type: ModalCoverModel.Style) { + func present(modal destination: Destination, type: ModalCoverModelStyle) { switch type { case .sheet: Task { @MainActor in @@ -46,10 +47,12 @@ public extension Coordinator { public protocol TabCoordinator: Coordinator { associatedtype Tab: Hashable + @MainActor var selectedTab: Tab { get set } } public protocol NavigationStackCoordinator: Coordinator { + @MainActor var path: [Destination] { get set } } diff --git a/Sources/FuturedArchitecture/Architecture/ModalCoverModel.swift b/Sources/FuturedArchitecture/Architecture/ModalCoverModel.swift index 920e248..534791a 100644 --- a/Sources/FuturedArchitecture/Architecture/ModalCoverModel.swift +++ b/Sources/FuturedArchitecture/Architecture/ModalCoverModel.swift @@ -7,17 +7,17 @@ import Foundation -public struct ModalCoverModel: Identifiable { - let destination: Destination - let style: Style - - public enum Style { - case sheet - #if !os(macOS) - case fullscreenCover - #endif - } +public enum ModalCoverModelStyle { + case sheet + #if !os(macOS) + case fullscreenCover + #endif +} +public struct ModalCoverModel: Identifiable { + public let destination: Destination + public let style: ModalCoverModelStyle + public var id: Destination.ID { destination.id } diff --git a/Sources/FuturedHelpers/Helpers/AnyShape.swift b/Sources/FuturedHelpers/Helpers/AnyShape.swift deleted file mode 100644 index 46eaed3..0000000 --- a/Sources/FuturedHelpers/Helpers/AnyShape.swift +++ /dev/null @@ -1,35 +0,0 @@ -import SwiftUI - -/// A type-erased shape. -/// -/// ## Overview -/// -/// An `AnyShape` allows changing the type of shape used in a given view -/// hierarchy. You can use it when different shapes are presented in the same -/// place but using `AnyView` is too broad since it is not possible to apply -/// `Shape` related modifiers. -/// -/// ```swift -/// var body: some Shape { -/// (isCapsule ? AnyShape(Capsule()) : AnyShape(Rectangle())) -/// .stroke() -/// } -/// ``` -public struct AnyShape: Shape { - private let path: (CGRect) -> Path - - /// Create an instance that type-erases a shape. - /// - Parameter shape: Concrete type conforming to `Shape`. - public init(_ shape: S) where S: Shape { - self.path = shape.path - } - - /// Describes this shape as a path within a rectangular frame of reference. - /// - /// - Parameter rect: The frame of reference for describing this shape. - /// - /// - Returns: A path that describes this shape. - public func path(in rect: CGRect) -> Path { - self.path(rect) - } -} diff --git a/Sources/FuturedHelpers/Helpers/CoordinatorSceneFlowProvider.swift b/Sources/FuturedHelpers/Helpers/CoordinatorSceneFlowProvider.swift index 3ed823c..57bee75 100644 --- a/Sources/FuturedHelpers/Helpers/CoordinatorSceneFlowProvider.swift +++ b/Sources/FuturedHelpers/Helpers/CoordinatorSceneFlowProvider.swift @@ -60,7 +60,7 @@ public protocol CoordinatorSceneFlowProvider { var navigateTo: (Destination) -> Void { get } var pop: () -> Void { get } - var present: ((Destination, ModalCoverModel.Style) -> Void)? { get } + var present: ((Destination, ModalCoverModelStyle) -> Void)? { get } var dismissModal: (() -> Void)? { get } var onModalDismiss: (() -> Void)? { get } var popTo: ((Destination?) -> Void)? { get } diff --git a/Sources/FuturedHelpers/Helpers/FuturedLibraryContentProvider.swift b/Sources/FuturedHelpers/Helpers/FuturedLibraryContentProvider.swift deleted file mode 100644 index de58aa5..0000000 --- a/Sources/FuturedHelpers/Helpers/FuturedLibraryContentProvider.swift +++ /dev/null @@ -1,8 +0,0 @@ -import SwiftUI - -@available(macOS 11, iOS 14, watchOS 7, tvOS 14, *) -struct FuturedLibraryContentProvider: LibraryContentProvider { - var views: [LibraryItem] { - LibraryItem(AnyShape(Circle())) - } -} diff --git a/Sources/FuturedHelpers/Helpers/Publisher+Resource.swift b/Sources/FuturedHelpers/Helpers/Publisher+Resource.swift deleted file mode 100644 index 27e2ecc..0000000 --- a/Sources/FuturedHelpers/Helpers/Publisher+Resource.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Combine - -extension Publisher { - /// Transforms all elements and failures to ``Resource``. - /// - Returns: Upstream publisher wrapped using map and catch operators - /// with ``Resource`` as output type and `Never` as failure. - @inlinable - public func resource() -> Publishers.Catch< - Publishers.Map>, Just> - > { - map { output in - Resource(content: output) - } - .catch { error in - Just(Resource(error: error)) - } - } -} diff --git a/Sources/FuturedHelpers/Helpers/Publisher+Result.swift b/Sources/FuturedHelpers/Helpers/Publisher+Result.swift deleted file mode 100644 index b3eb329..0000000 --- a/Sources/FuturedHelpers/Helpers/Publisher+Result.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Combine - -extension Publisher { - /// Transforms all elements and failures to `Result`. - /// - Returns: Upstream publisher wrapped using map and catch operators - /// with `Result` as output type and `Never` as failure. - @inlinable - public func result() -> Publishers.Catch< - Publishers.Map>, Just> - > { - map { output in - Result.success(output) - } - .catch { error in - Just(Result.failure(error)) - } - } -} diff --git a/Sources/FuturedHelpers/Helpers/Resource.swift b/Sources/FuturedHelpers/Helpers/Resource.swift deleted file mode 100644 index 32c3cdb..0000000 --- a/Sources/FuturedHelpers/Helpers/Resource.swift +++ /dev/null @@ -1,49 +0,0 @@ -/// Represents asynchronously loaded data and their state -/// including loading, errors and even refreshing. -/// -/// ## Overview -/// -/// States are not exclusive, you can even have error and content -/// if its required to represent error which happened during -/// refreshing. -/// -/// This is ideal for modelling state for remotely loaded resource -/// in any app. -public struct Resource { - /// Content if it was loaded. - public var content: Content? - /// Flag representing if the resource is currently loading. - public var isLoading: Bool - /// Optional strongly-typed error which occured during the load or refresh. - public var error: Failure? - - /// Created a new resource. - /// - Parameters: - /// - content: Optional content. Default value is `nil`. - /// - isLoading: Loading flag. Default value is `false`. - /// - error: Optional error. Default value is `nil`. - public init(content: Content? = nil, isLoading: Bool = false, error: Failure? = nil) { - self.content = content - self.isLoading = isLoading - self.error = error - } - - /// Read-only flag representing if the content is refreshing. - /// - /// ## Discussion - /// - /// The flag is set to true when the resource is loading and has some content. - public var isRefreshing: Bool { - isLoading && hasContent - } - - /// Read-only flag representing if the content is present. - public var hasContent: Bool { - content != nil - } - - /// Read-only flag representing if some error occured. - public var hasFailed: Bool { - error != nil - } -} diff --git a/Sources/FuturedHelpers/Helpers/URL+ExpressibleByStringLiteral.swift b/Sources/FuturedHelpers/Helpers/URL+ExpressibleByStringLiteral.swift deleted file mode 100644 index 84bb73b..0000000 --- a/Sources/FuturedHelpers/Helpers/URL+ExpressibleByStringLiteral.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -extension URL: ExpressibleByStringLiteral { - public init(stringLiteral value: StaticString) { - if let url = URL(string: "\(value)") { - self = url - } else { - fatalError("\(value) is not valid URL!") - } - } -} diff --git a/Tests/FuturedKitTests/Mocks/MockError.swift b/Tests/FuturedKitTests/Mocks/MockError.swift deleted file mode 100644 index b56e465..0000000 --- a/Tests/FuturedKitTests/Mocks/MockError.swift +++ /dev/null @@ -1,3 +0,0 @@ -enum MockError: Error { - case failed -} diff --git a/Tests/FuturedKitTests/PlaceholderTest.swift b/Tests/FuturedKitTests/PlaceholderTest.swift new file mode 100644 index 0000000..0864f44 --- /dev/null +++ b/Tests/FuturedKitTests/PlaceholderTest.swift @@ -0,0 +1,7 @@ +import XCTest + +// We might want to write future test cases in SwiftTesting. +final class PlaceholderTests: XCTestCase { + func testNothing() { + } +} diff --git a/Tests/FuturedKitTests/PublisherResourceTests.swift b/Tests/FuturedKitTests/PublisherResourceTests.swift deleted file mode 100644 index 471dfd2..0000000 --- a/Tests/FuturedKitTests/PublisherResourceTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -import XCTest -import FuturedHelpers -import Combine - -final class PublisherResourceTests: XCTestCase { - func testOutputHasContent() { - _ = Just(Bool.random()).resource().sink { resource in - XCTAssertTrue(resource.hasContent) - } - } - - func testOutputContentEquals() { - let content = Bool.random() - _ = Just(content).resource().sink { resource in - XCTAssertEqual(content, resource.content) - } - } - - func testOutputContentDidNotFail() { - let content = Bool.random() - _ = Just(content).resource().sink { resource in - XCTAssertFalse(resource.hasFailed) - } - } - - func testOutputContentIsNotLoading() { - let content = Bool.random() - _ = Just(content).resource().sink { resource in - XCTAssertFalse(resource.isLoading) - } - } - - func testFailureHasFailed() { - _ = Fail(outputType: Bool.self, failure: MockError.failed) - .resource() - .sink { resource in - XCTAssertTrue(resource.hasFailed) - } - } - - func testFailureHasNoContent() { - _ = Fail(outputType: Bool.self, failure: MockError.failed) - .resource() - .sink { resource in - XCTAssertFalse(resource.hasContent) - } - } - - func testFailureContentIsNil() { - _ = Fail(outputType: Bool.self, failure: MockError.failed) - .resource() - .sink { resource in - XCTAssertEqual(nil, resource.content) - } - } - - func testFailureIsNotLoading() { - _ = Fail(outputType: Bool.self, failure: MockError.failed) - .resource() - .sink { resource in - XCTAssertFalse(resource.isLoading) - } - } -} diff --git a/Tests/FuturedKitTests/PublisherResultTests.swift b/Tests/FuturedKitTests/PublisherResultTests.swift deleted file mode 100644 index 9cf285b..0000000 --- a/Tests/FuturedKitTests/PublisherResultTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -import XCTest -import FuturedHelpers -import Combine - -final class PublisherResultTests: XCTestCase { - func testOutput() { - _ = Just(true).result().sink { result in - switch result { - case .success(let success): - XCTAssertTrue(success) - case .failure: - XCTFail("Result should be success") - } - } - } - - func testFailure() { - _ = Fail(error: MockError.failed).result().sink { result in - switch result { - case .success: - XCTFail("Result should be failure") - case .failure(let error): - XCTAssertEqual(error, MockError.failed) - } - } - } -} diff --git a/Tests/FuturedKitTests/ResourceTests.swift b/Tests/FuturedKitTests/ResourceTests.swift deleted file mode 100644 index 90ed5fb..0000000 --- a/Tests/FuturedKitTests/ResourceTests.swift +++ /dev/null @@ -1,31 +0,0 @@ -import XCTest -import FuturedHelpers - -final class ResourceTests: XCTestCase { - func testHasContent() { - let content = Bool.random() - let resource = Resource(content: content) - XCTAssertTrue(resource.hasContent) - } - - func testContentEquals() { - let content = Bool.random() - let resource = Resource(content: content) - XCTAssertEqual(content, resource.content) - } - - func testHasFailed() { - let resource = Resource(error: MockError.failed) - XCTAssertTrue(resource.hasFailed) - } - - func testIsLoading() { - let resource = Resource(isLoading: true) - XCTAssertTrue(resource.isLoading) - } - - func testIsRefreshing() { - let resource = Resource(content: Bool.random(), isLoading: true) - XCTAssertTrue(resource.isRefreshing) - } -} diff --git a/Tests/FuturedKitTests/URLTests.swift b/Tests/FuturedKitTests/URLTests.swift deleted file mode 100644 index c7d0b53..0000000 --- a/Tests/FuturedKitTests/URLTests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import XCTest -import FuturedHelpers - -final class URLExpressibleByStringLiteralTests: XCTestCase { - func testValidStaticStringInitialization() { - let url: URL = "http://example.org" - XCTAssertEqual(url.host, "example.org") - } -}