Skip to content

Commit

Permalink
chore: refactor the repository by implementing generics
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammed Rokon Uddin committed Feb 9, 2024
1 parent 642c30c commit 5b7c573
Show file tree
Hide file tree
Showing 78 changed files with 2,643 additions and 4,874 deletions.
56 changes: 56 additions & 0 deletions {{cookiecutter.app_name}}/.swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"indentation" : {
"spaces" : 2
},
"indentConditionalCompilationBlocks" : true,
"indentSwitchCaseLabels" : false,
"lineBreakAroundMultilineExpressionChainComponents" : false,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : false,
"lineBreakBeforeEachGenericRequirement" : false,
"lineLength" : 80,
"tabWidth" : 8,
"maximumBlankLines" : 1,
"prioritizeKeepingFunctionOutputTogether" : false,
"respectsExistingLineBreaks" : true,
"version" : 1,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLowerCamelCase" : true,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : false,
"OrderedImports" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"UseEarlyExits" : false,
"UseLetInEveryBoundCaseVariable" : false,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : true,
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
}
}
5 changes: 0 additions & 5 deletions {{cookiecutter.app_name}}/.swiftformat

This file was deleted.

44 changes: 23 additions & 21 deletions {{cookiecutter.app_name}}/Common/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@
import PackageDescription

let package = Package(
name: "Common",
platforms: [.macOS(.v12), .iOS(.v15)],
products: [
.library(
name: "Common",
targets: ["Common"]),
],
dependencies: [
.package(
url: "https://github.com/pointfreeco/swift-composable-architecture",
exact: "1.5.1"
),
],
targets: [
.target(
name: "Common",
dependencies: [
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
]
name: "Common",
platforms: [.macOS(.v12), .iOS(.v15)],
products: [
.library(
name: "Common",
targets: ["Common"])
],
dependencies: [
.package(
url: "https://github.com/pointfreeco/swift-composable-architecture",
exact: "1.5.1"
)
],
targets: [
.target(
name: "Common",
dependencies: [
.product(
name: "ComposableArchitecture",
package: "swift-composable-architecture")
]
)
]
)
22 changes: 22 additions & 0 deletions {{cookiecutter.app_name}}/Common/Sources/Common/BaseAction.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// BaseAction.swift
// Common
//
// Created by {{ cookiecutter.creator }} on {% now 'utc', '%d/%m/%Y' %}.
// Copyright © {% now 'utc', '%Y' %} {{cookiecutter.company_name}}. All rights reserved.
//

import Foundation

// keep Actions organized and their intent explicit
// https://github.com/pointfreeco/swift-composable-architecture/discussions/1440

public protocol BaseAction {
associatedtype ViewAction
associatedtype DelegateAction
associatedtype InlyingAction

static func view(_: ViewAction) -> Self
static func delegate(_: DelegateAction) -> Self
static func inlying(_: InlyingAction) -> Self
}
195 changes: 109 additions & 86 deletions {{cookiecutter.app_name}}/Common/Sources/Common/FeatureReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,114 +10,137 @@ import ComposableArchitecture
import SwiftUI

// MARK: FeatureReducer
public protocol FeatureReducer: Reducer where State: Sendable & Hashable, Action == FeatureAction<Self> {
associatedtype ViewAction: Sendable & Equatable = Never
associatedtype InternalAction: Sendable & Equatable = Never
associatedtype ChildAction: Sendable & Equatable = Never
associatedtype DelegateAction: Sendable & Equatable = Never

func reduce(into state: inout State, viewAction: ViewAction) -> Effect<Action>
func reduce(into state: inout State, internalAction: InternalAction) -> Effect<Action>
func reduce(into state: inout State, childAction: ChildAction) -> Effect<Action>
func reduce(into state: inout State, presentedAction: Destination.Action) -> Effect<Action>
func reduceDismissDestination(into state: inout State) -> Effect<Action>

associatedtype Destination: DestinationReducer = EmptyDestination
associatedtype ViewState: Equatable = Never
public protocol FeatureReducer: Reducer
where State: Sendable & Hashable, Action == FeatureAction<Self> {
associatedtype ViewAction: Sendable & Equatable = Never
associatedtype InternalAction: Sendable & Equatable = Never
associatedtype ChildAction: Sendable & Equatable = Never
associatedtype DelegateAction: Sendable & Equatable = Never

func reduce(into state: inout State, viewAction: ViewAction) -> Effect<Action>
func reduce(into state: inout State, internalAction: InternalAction)
-> Effect<Action>
func reduce(into state: inout State, childAction: ChildAction) -> Effect<
Action
>
func reduce(into state: inout State, presentedAction: Destination.Action)
-> Effect<Action>
func reduceDismissDestination(into state: inout State) -> Effect<Action>

associatedtype Destination: DestinationReducer = EmptyDestination
associatedtype ViewState: Equatable = Never
}

extension Reducer where Self: FeatureReducer {
public typealias Action = FeatureAction<Self>

public var body: some ReducerOf<Self> {
Reduce(core)
}

public func core(into state: inout State, action: Action) -> Effect<Action> {
switch action {
case .destination(.dismiss):
reduceDismissDestination(into: &state)
case let .destination(.presented(presentedAction)):
reduce(into: &state, presentedAction: presentedAction)
case let .view(viewAction):
reduce(into: &state, viewAction: viewAction)
case let .internal(internalAction):
reduce(into: &state, internalAction: internalAction)
case let .child(childAction):
reduce(into: &state, childAction: childAction)
case .delegate:
.none
}
}

public func reduce(into state: inout State, viewAction: ViewAction) -> Effect<Action> {
.none
}

public func reduce(into state: inout State, internalAction: InternalAction) -> Effect<Action> {
.none
}

public func reduce(into state: inout State, childAction: ChildAction) -> Effect<Action> {
.none
}

public func reduce(into state: inout State, presentedAction: Destination.Action) -> Effect<Action> {
.none
}

public func reduceDismissDestination(into state: inout State) -> Effect<Action> {
.none
public typealias Action = FeatureAction<Self>

public var body: some ReducerOf<Self> {
Reduce(core)
}

public func core(into state: inout State, action: Action) -> Effect<Action> {
switch action {
case .destination(.dismiss):
reduceDismissDestination(into: &state)
case let .destination(.presented(presentedAction)):
reduce(into: &state, presentedAction: presentedAction)
case let .view(viewAction):
reduce(into: &state, viewAction: viewAction)
case let .internal(internalAction):
reduce(into: &state, internalAction: internalAction)
case let .child(childAction):
reduce(into: &state, childAction: childAction)
case .delegate:
.none
}

}

public func reduce(into state: inout State, viewAction: ViewAction) -> Effect<
Action
> {
.none
}

public func reduce(into state: inout State, internalAction: InternalAction)
-> Effect<Action>
{
.none
}

public func reduce(into state: inout State, childAction: ChildAction)
-> Effect<Action>
{
.none
}

public func reduce(
into state: inout State, presentedAction: Destination.Action
) -> Effect<Action> {
.none
}

public func reduceDismissDestination(into state: inout State) -> Effect<
Action
> {
.none
}

}

public typealias PresentationStoreOf<R: Reducer> = Store<PresentationState<R.State>, PresentationAction<R.Action>>
public typealias PresentationStoreOf<R: Reducer> = Store<
PresentationState<R.State>, PresentationAction<R.Action>
>

// MARK: FeatureAction
@CasePathable
public enum FeatureAction<Feature: FeatureReducer>: Sendable, Equatable {
case destination(PresentationAction<Feature.Destination.Action>)
case view(Feature.ViewAction)
case `internal`(Feature.InternalAction)
case child(Feature.ChildAction)
case delegate(Feature.DelegateAction)
case destination(PresentationAction<Feature.Destination.Action>)
case view(Feature.ViewAction)
case `internal`(Feature.InternalAction)
case child(Feature.ChildAction)
case delegate(Feature.DelegateAction)
}

// MARK: DestinationReducer
public protocol DestinationReducer: Reducer where State: Sendable & Hashable, Action: Sendable & Equatable & CasePathable { }
public protocol DestinationReducer: Reducer
where State: Sendable & Hashable, Action: Sendable & Equatable & CasePathable {}

// MARK: EmptyDestination

public enum EmptyDestination: DestinationReducer {
public struct State: Sendable, Hashable {}
public typealias Action = Never
public func reduce(into state: inout State, action: Never) -> Effect<Action> {}
public func reduceDismissDestination(into state: inout State) -> Effect<Action> { .none }
public struct State: Sendable, Hashable {}
public typealias Action = Never
public func reduce(into state: inout State, action: Never) -> Effect<Action> {
}
public func reduceDismissDestination(into state: inout State) -> Effect<
Action
> { .none }
}

//MARK: FeatureAction + Hashable
extension FeatureAction: Hashable where Feature.Destination.Action: Hashable,
Feature.ViewAction: Hashable,
Feature.ChildAction: Hashable,
Feature.InternalAction: Hashable,
Feature.DelegateAction: Hashable {
public func hash(into hasher: inout Hasher) {
switch self {
case let .destination(action):
hasher.combine(action)
case let .view(action):
hasher.combine(action)
case let .internal(action):
hasher.combine(action)
case let .child(action):
hasher.combine(action)
case let .delegate(action):
hasher.combine(action)
}
extension FeatureAction: Hashable
where
Feature.Destination.Action: Hashable,
Feature.ViewAction: Hashable,
Feature.ChildAction: Hashable,
Feature.InternalAction: Hashable,
Feature.DelegateAction: Hashable
{
public func hash(into hasher: inout Hasher) {
switch self {
case let .destination(action):
hasher.combine(action)
case let .view(action):
hasher.combine(action)
case let .internal(action):
hasher.combine(action)
case let .child(action):
hasher.combine(action)
case let .delegate(action):
hasher.combine(action)
}
}
}

/// For scoping to an actionless childstore
public func actionless<T>(never: Never) -> T {}

Loading

0 comments on commit 5b7c573

Please sign in to comment.