diff --git a/0075-modular-state-management-wtp/PrimeTime/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/0075-modular-state-management-wtp/PrimeTime/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.h b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.h new file mode 100644 index 00000000..38201c51 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.h @@ -0,0 +1,19 @@ +// +// ComposableArchitecture.h +// ComposableArchitecture +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +#import + +//! Project version number for ComposableArchitecture. +FOUNDATION_EXPORT double ComposableArchitectureVersionNumber; + +//! Project version string for ComposableArchitecture. +FOUNDATION_EXPORT const unsigned char ComposableArchitectureVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.swift b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.swift new file mode 100644 index 00000000..fdd0f42f --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/ComposableArchitecture.swift @@ -0,0 +1,87 @@ +import Combine +import SwiftUI + +public final class Store: ObservableObject { + private let reducer: (inout Value, Action) -> Void + @Published public private(set) var value: Value + private var cancellable: Cancellable? + + public init(initialValue: Value, reducer: @escaping (inout Value, Action) -> Void) { +// self.objectWillChange +// self.$value.sink(receiveValue: <#T##((Value) -> Void)##((Value) -> Void)##(Value) -> Void#>) + self.reducer = reducer + self.value = initialValue + } + + public func send(_ action: Action) { + self.reducer(&self.value, action) + } + + // ((Value) -> LocalValue) -> (Store) -> Store + // ((A) -> B) -> (Store) -> Store + // map: ((A) -> B) -> (F) -> F + + public func view( + value toLocalValue: @escaping (Value) -> LocalValue, + action toGlobalAction: @escaping (LocalAction) -> Action + ) -> Store { + let localStore = Store( + initialValue: toLocalValue(self.value), + reducer: { localValue, localAction in + self.send(toGlobalAction(localAction)) + localValue = toLocalValue(self.value) + } + ) + localStore.cancellable = self.$value.sink { [weak localStore] newValue in + localStore?.value = toLocalValue(newValue) + } + return localStore + } + + // ((LocalAction) -> Action) -> (Store<_, Action>) -> Store<_, LocalAction> + // ((B) -> A) -> (Store<_, A>) -> Store<_, B> + // pullback: ((B) -> A) -> (F) -> F +} + + +func transform( + _ reducer: (A, Action) -> A, + _ f: (A) -> B +) -> (B, Action) -> B { + fatalError() +} + + +public func combine( + _ reducers: (inout Value, Action) -> Void... +) -> (inout Value, Action) -> Void { + return { value, action in + for reducer in reducers { + reducer(&value, action) + } + } +} + +public func pullback( + _ reducer: @escaping (inout LocalValue, LocalAction) -> Void, + value: WritableKeyPath, + action: WritableKeyPath +) -> (inout GlobalValue, GlobalAction) -> Void { + return { globalValue, globalAction in + guard let localAction = globalAction[keyPath: action] else { return } + reducer(&globalValue[keyPath: value], localAction) + } +} + +public func logging( + _ reducer: @escaping (inout Value, Action) -> Void +) -> (inout Value, Action) -> Void { + return { value, action in + reducer(&value, action) + print("Action: \(action)") + print("Value:") + dump(value) + print("---") + } +} + diff --git a/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/Info.plist b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitecture/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/ComposableArchitectureTests.swift b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/ComposableArchitectureTests.swift new file mode 100644 index 00000000..ea4b132f --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/ComposableArchitectureTests.swift @@ -0,0 +1,34 @@ +// +// ComposableArchitectureTests.swift +// ComposableArchitectureTests +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +import XCTest +@testable import ComposableArchitecture + +class ComposableArchitectureTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/Info.plist b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/ComposableArchitectureTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.h b/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.h new file mode 100644 index 00000000..ba74c646 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.h @@ -0,0 +1,19 @@ +// +// Counter.h +// Counter +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +#import + +//! Project version number for Counter. +FOUNDATION_EXPORT double CounterVersionNumber; + +//! Project version string for Counter. +FOUNDATION_EXPORT const unsigned char CounterVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.swift b/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.swift new file mode 100644 index 00000000..af64654e --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/Counter/Counter.swift @@ -0,0 +1,133 @@ +import ComposableArchitecture +import PrimeModal +import SwiftUI + +public enum CounterAction { + case decrTapped + case incrTapped +} + +public func counterReducer(state: inout Int, action: CounterAction) { + switch action { + case .decrTapped: + state -= 1 + + case .incrTapped: + state += 1 + } +} + +public let counterViewReducer = combine( + pullback(counterReducer, value: \CounterViewState.count, action: \CounterViewAction.counter), + pullback(primeModalReducer, value: \.self, action: \.primeModal) +) + +struct PrimeAlert: Identifiable { + let prime: Int + var id: Int { self.prime } +} + +public typealias CounterViewState = (count: Int, favoritePrimes: [Int]) + +public enum CounterViewAction { + case counter(CounterAction) + case primeModal(PrimeModalAction) + + var counter: CounterAction? { + get { + guard case let .counter(value) = self else { return nil } + return value + } + set { + guard case .counter = self, let newValue = newValue else { return } + self = .counter(newValue) + } + } + + var primeModal: PrimeModalAction? { + get { + guard case let .primeModal(value) = self else { return nil } + return value + } + set { + guard case .primeModal = self, let newValue = newValue else { return } + self = .primeModal(newValue) + } + } + +} + +public struct CounterView: View { + @ObservedObject var store: Store + @State var isPrimeModalShown = false + @State var alertNthPrime: PrimeAlert? + @State var isNthPrimeButtonDisabled = false + + public init(store: Store) { + self.store = store + } + + public var body: some View { + VStack { + HStack { + Button("-") { self.store.send(.counter(.decrTapped)) } + Text("\(self.store.value.count)") + Button("+") { self.store.send(.counter(.incrTapped)) } + } + Button("Is this prime?") { self.isPrimeModalShown = true } + Button( + "What is the \(ordinal(self.store.value.count)) prime?", + action: self.nthPrimeButtonAction + ) + .disabled(self.isNthPrimeButtonDisabled) + } + .font(.title) + .navigationBarTitle("Counter demo") + .sheet(isPresented: self.$isPrimeModalShown) { + IsPrimeModalView( + store: self.store + .view( + value: { ($0.count, $0.favoritePrimes) }, + action: { .primeModal($0) } + ) + ) + } + .alert(item: self.$alertNthPrime) { alert in + Alert( + title: Text("The \(ordinal(self.store.value.count)) prime is \(alert.prime)"), + dismissButton: .default(Text("Ok")) + ) + } + } + + func nthPrimeButtonAction() { + self.isNthPrimeButtonDisabled = true + nthPrime(self.store.value.count) { prime in + self.alertNthPrime = prime.map(PrimeAlert.init(prime:)) + self.isNthPrimeButtonDisabled = false + } + } +} + +func nthPrime(_ n: Int, callback: @escaping (Int?) -> Void) -> Void { + wolframAlpha(query: "prime \(n)") { result in + callback( + result + .flatMap { + $0.queryresult + .pods + .first(where: { $0.primary == .some(true) })? + .subpods + .first? + .plaintext + } + .flatMap(Int.init) + ) + } +} + +func ordinal(_ n: Int) -> String { + let formatter = NumberFormatter() + formatter.numberStyle = .ordinal + return formatter.string(for: n) ?? "" +} diff --git a/0075-modular-state-management-wtp/PrimeTime/Counter/Info.plist b/0075-modular-state-management-wtp/PrimeTime/Counter/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/Counter/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/0075-modular-state-management-wtp/PrimeTime/Counter/WolframAlpha.swift b/0075-modular-state-management-wtp/PrimeTime/Counter/WolframAlpha.swift new file mode 100644 index 00000000..01b43edd --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/Counter/WolframAlpha.swift @@ -0,0 +1,38 @@ +import Foundation + +private let wolframAlphaApiKey = "6H69Q3-828TKQJ4EP" + +struct WolframAlphaResult: Decodable { + let queryresult: QueryResult + + struct QueryResult: Decodable { + let pods: [Pod] + + struct Pod: Decodable { + let primary: Bool? + let subpods: [SubPod] + + struct SubPod: Decodable { + let plaintext: String + } + } + } +} + +func wolframAlpha(query: String, callback: @escaping (WolframAlphaResult?) -> Void) -> Void { + var components = URLComponents(string: "https://api.wolframalpha.com/v2/query")! + components.queryItems = [ + URLQueryItem(name: "input", value: query), + URLQueryItem(name: "format", value: "plaintext"), + URLQueryItem(name: "output", value: "JSON"), + URLQueryItem(name: "appid", value: wolframAlphaApiKey), + ] + + URLSession.shared.dataTask(with: components.url(relativeTo: nil)!) { data, response, error in + callback( + data + .flatMap { try? JSONDecoder().decode(WolframAlphaResult.self, from: $0) } + ) + } + .resume() +} diff --git a/0075-modular-state-management-wtp/PrimeTime/CounterTests/CounterTests.swift b/0075-modular-state-management-wtp/PrimeTime/CounterTests/CounterTests.swift new file mode 100644 index 00000000..5fb9df79 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/CounterTests/CounterTests.swift @@ -0,0 +1,34 @@ +// +// CounterTests.swift +// CounterTests +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +import XCTest +@testable import Counter + +class CounterTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/0075-modular-state-management-wtp/PrimeTime/CounterTests/Info.plist b/0075-modular-state-management-wtp/PrimeTime/CounterTests/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/CounterTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.h b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.h new file mode 100644 index 00000000..b0a43669 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.h @@ -0,0 +1,19 @@ +// +// FavoritePrimes.h +// FavoritePrimes +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +#import + +//! Project version number for FavoritePrimes. +FOUNDATION_EXPORT double FavoritePrimesVersionNumber; + +//! Project version string for FavoritePrimes. +FOUNDATION_EXPORT const unsigned char FavoritePrimesVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.swift b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.swift new file mode 100644 index 00000000..f6e8f536 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/FavoritePrimes.swift @@ -0,0 +1,37 @@ +import ComposableArchitecture +import SwiftUI + +public enum FavoritePrimesAction { + case deleteFavoritePrimes(IndexSet) +} + +public func favoritePrimesReducer(state: inout [Int], action: FavoritePrimesAction) { + switch action { + case let .deleteFavoritePrimes(indexSet): + for index in indexSet { + state.remove(at: index) + } + } +} + +public struct FavoritePrimesView: View { + @ObservedObject var store: Store<[Int], FavoritePrimesAction> + + public init(store: Store<[Int], FavoritePrimesAction>) { + self.store = store + } + + public var body: some View { + List { + ForEach(self.store.value, id: \.self) { prime in + Text("\(prime)") + } + .onDelete { indexSet in + self.store.send(.deleteFavoritePrimes(indexSet)) +// self.store.send(.counter(.incrTapped)) + } + } + .navigationBarTitle("Favorite primes") + } +} + diff --git a/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/Info.plist b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimes/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/FavoritePrimesTests.swift b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/FavoritePrimesTests.swift new file mode 100644 index 00000000..1fcd30d5 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/FavoritePrimesTests.swift @@ -0,0 +1,34 @@ +// +// FavoritePrimesTests.swift +// FavoritePrimesTests +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +import XCTest +@testable import FavoritePrimes + +class FavoritePrimesTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/Info.plist b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/FavoritePrimesTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/0075-modular-state-management-wtp/PrimeTime/Package.swift b/0075-modular-state-management-wtp/PrimeTime/Package.swift new file mode 100644 index 00000000..89f8b7a3 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/Package.swift @@ -0,0 +1,9 @@ +// swift-tools-version:4.2 +import PackageDescription + +let package = Package( + name: "ComposableArchitecture", + dependencies: [ + .package(url: "https://github.com/pointfreeco/swift-enum-properties.git", from: "0.1.0") + ] +) diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeModal/Info.plist b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/Info.plist new file mode 100644 index 00000000..9bcb2444 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.h b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.h new file mode 100644 index 00000000..5bdc9d8f --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.h @@ -0,0 +1,19 @@ +// +// PrimeModal.h +// PrimeModal +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +#import + +//! Project version number for PrimeModal. +FOUNDATION_EXPORT double PrimeModalVersionNumber; + +//! Project version string for PrimeModal. +FOUNDATION_EXPORT const unsigned char PrimeModalVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.swift new file mode 100644 index 00000000..ffac26b4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeModal/PrimeModal.swift @@ -0,0 +1,64 @@ +import ComposableArchitecture +import SwiftUI + +//public struct PrimeModalState { +// public var count: Int +// public var favoritePrimes: [Int] +// +// public init(count: Int, favoritePrimes: [Int]) { +// self.count = count +// self.favoritePrimes = favoritePrimes +// } +//} +public typealias PrimeModalState = (count: Int, favoritePrimes: [Int]) + +public enum PrimeModalAction { + case saveFavoritePrimeTapped + case removeFavoritePrimeTapped +} + +public func primeModalReducer(state: inout PrimeModalState, action: PrimeModalAction) { + switch action { + case .removeFavoritePrimeTapped: + state.favoritePrimes.removeAll(where: { $0 == state.count }) + + case .saveFavoritePrimeTapped: + state.favoritePrimes.append(state.count) + } +} + +public struct IsPrimeModalView: View { + @ObservedObject var store: Store + + public init(store: Store) { + self.store = store + } + + public var body: some View { + VStack { + if isPrime(self.store.value.count) { + Text("\(self.store.value.count) is prime 🎉") + if self.store.value.favoritePrimes.contains(self.store.value.count) { + Button("Remove from favorite primes") { + self.store.send(.removeFavoritePrimeTapped) + } + } else { + Button("Save to favorite primes") { + self.store.send(.saveFavoritePrimeTapped) + } + } + } else { + Text("\(self.store.value.count) is not prime :(") + } + } + } +} + +func isPrime(_ p: Int) -> Bool { + if p <= 1 { return false } + if p <= 3 { return true } + for i in 2...Int(sqrtf(Float(p))) { + if p % i == 0 { return false } + } + return true +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/Info.plist b/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/PrimeModalTests.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/PrimeModalTests.swift new file mode 100644 index 00000000..3d7655b3 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeModalTests/PrimeModalTests.swift @@ -0,0 +1,34 @@ +// +// PrimeModalTests.swift +// PrimeModalTests +// +// Created by Stephen Celis on 9/8/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +import XCTest +@testable import PrimeModal + +class PrimeModalTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/Contents.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/Contents.swift new file mode 100644 index 00000000..b46627fd --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/Contents.swift @@ -0,0 +1,76 @@ +import ComposableArchitecture +import Counter +import FavoritePrimes +import PrimeModal +import SwiftUI +import PlaygroundSupport + + +PlaygroundPage.current.liveView = UIHostingController( + rootView: CounterView( + store: Store( + initialValue: (1_000_000, []), + reducer: counterViewReducer + ) + ) +) + + +//PlaygroundPage.current.liveView = UIHostingController( +// rootView: IsPrimeModalView( +// store: Store( +// initialValue: (2, [2, 3, 5]), +// reducer: primeModalReducer +// ) +// ) +//) + + +// +//PlaygroundPage.current.liveView = UIHostingController( +// rootView: FavoritePrimesView( +// store: Store<[Int], FavoritePrimesAction>( +// initialValue: [2, 3, 5, 7, 11], +// reducer: favoritePrimesReducer +// ) +// ) +//) + + + + +//let store = Store(initialValue: 0, reducer: { count, _ in count += 1 }) +// +//store.send(()) +//store.send(()) +//store.send(()) +//store.send(()) +//store.send(()) +// +//store.value +// +//let newStore = store.view { $0 } +// +//newStore.value +//newStore.send(()) +//newStore.send(()) +//newStore.send(()) +//newStore.value +// +//store.value +// +//store.send(()) +//store.send(()) +//store.send(()) +// +//newStore.value +//store.value +// +//var xs = [1, 2, 3] +//var ys = xs.map { $0 } +// +//ys.append(4) +// +//xs +//ys +// diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/contents.xcplayground b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/contents.xcplayground new file mode 100644 index 00000000..5da2641c --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.pbxproj b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.pbxproj new file mode 100644 index 00000000..522b040a --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.pbxproj @@ -0,0 +1,1697 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + CAD67E2023329887000C7787 /* WolframAlpha.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC29217322FB231F006090DF /* WolframAlpha.swift */; }; + DC90717022FA102900B38B42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC90716F22FA102900B38B42 /* AppDelegate.swift */; }; + DC90717222FA102900B38B42 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC90717122FA102900B38B42 /* SceneDelegate.swift */; }; + DC90717422FA102900B38B42 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC90717322FA102900B38B42 /* ContentView.swift */; }; + DC90717622FA102A00B38B42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC90717522FA102A00B38B42 /* Assets.xcassets */; }; + DC90717922FA102A00B38B42 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC90717822FA102A00B38B42 /* Preview Assets.xcassets */; }; + DC90717C22FA102A00B38B42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC90717A22FA102A00B38B42 /* LaunchScreen.storyboard */; }; + DC90718722FA102B00B38B42 /* PrimeTimeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC90718622FA102B00B38B42 /* PrimeTimeTests.swift */; }; + DC90719222FA151D00B38B42 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC90719122FA151D00B38B42 /* Util.swift */; }; + DCF0C5A42326032B008B45A0 /* ComposableArchitecture.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */; }; + DCF0C5AB2326032B008B45A0 /* ComposableArchitectureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C5AA2326032B008B45A0 /* ComposableArchitectureTests.swift */; }; + DCF0C5AD2326032B008B45A0 /* ComposableArchitecture.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF0C59D2326032B008B45A0 /* ComposableArchitecture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCF0C5B02326032B008B45A0 /* ComposableArchitecture.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */; }; + DCF0C5B22326032B008B45A0 /* ComposableArchitecture.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DCF0C5C723260348008B45A0 /* Counter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5BE23260348008B45A0 /* Counter.framework */; }; + DCF0C5CE23260348008B45A0 /* CounterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C5CD23260348008B45A0 /* CounterTests.swift */; }; + DCF0C5D023260348008B45A0 /* Counter.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF0C5C023260348008B45A0 /* Counter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCF0C5D323260348008B45A0 /* Counter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5BE23260348008B45A0 /* Counter.framework */; }; + DCF0C5D423260348008B45A0 /* Counter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5BE23260348008B45A0 /* Counter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DCF0C5E92326035C008B45A0 /* PrimeModal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5E02326035C008B45A0 /* PrimeModal.framework */; }; + DCF0C5F02326035C008B45A0 /* PrimeModalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C5EF2326035C008B45A0 /* PrimeModalTests.swift */; }; + DCF0C5F22326035C008B45A0 /* PrimeModal.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF0C5E22326035C008B45A0 /* PrimeModal.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCF0C5F52326035C008B45A0 /* PrimeModal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5E02326035C008B45A0 /* PrimeModal.framework */; }; + DCF0C5F62326035C008B45A0 /* PrimeModal.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C5E02326035C008B45A0 /* PrimeModal.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DCF0C60B2326036F008B45A0 /* FavoritePrimes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */; }; + DCF0C6122326036F008B45A0 /* FavoritePrimesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C6112326036F008B45A0 /* FavoritePrimesTests.swift */; }; + DCF0C6142326036F008B45A0 /* FavoritePrimes.h in Headers */ = {isa = PBXBuildFile; fileRef = DCF0C6042326036F008B45A0 /* FavoritePrimes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DCF0C6172326036F008B45A0 /* FavoritePrimes.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */; }; + DCF0C6182326036F008B45A0 /* FavoritePrimes.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DCF0C628232603B7008B45A0 /* ComposableArchitecture.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C627232603B7008B45A0 /* ComposableArchitecture.swift */; }; + DCF0C62A23260405008B45A0 /* FavoritePrimes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C62923260405008B45A0 /* FavoritePrimes.swift */; }; + DCF0C62C2326040D008B45A0 /* PrimeModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C62B2326040D008B45A0 /* PrimeModal.swift */; }; + DCF0C62E23260414008B45A0 /* Counter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCF0C62D23260414008B45A0 /* Counter.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + CAD67E1C2332982E000C7787 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C5DF2326035C008B45A0; + remoteInfo = PrimeModal; + }; + DC90718322FA102B00B38B42 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC90716B22FA102900B38B42; + remoteInfo = PrimeTime; + }; + DCF0C5A52326032B008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C59A2326032B008B45A0; + remoteInfo = ComposableArchitecture; + }; + DCF0C5A72326032B008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC90716B22FA102900B38B42; + remoteInfo = PrimeTime; + }; + DCF0C5AE2326032B008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C59A2326032B008B45A0; + remoteInfo = ComposableArchitecture; + }; + DCF0C5C823260348008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C5BD23260348008B45A0; + remoteInfo = Counter; + }; + DCF0C5CA23260348008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC90716B22FA102900B38B42; + remoteInfo = PrimeTime; + }; + DCF0C5D123260348008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C5BD23260348008B45A0; + remoteInfo = Counter; + }; + DCF0C5EA2326035C008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C5DF2326035C008B45A0; + remoteInfo = PrimeModal; + }; + DCF0C5EC2326035C008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC90716B22FA102900B38B42; + remoteInfo = PrimeTime; + }; + DCF0C5F32326035C008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C5DF2326035C008B45A0; + remoteInfo = PrimeModal; + }; + DCF0C60C2326036F008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C6012326036F008B45A0; + remoteInfo = FavoritePrimes; + }; + DCF0C60E2326036F008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC90716B22FA102900B38B42; + remoteInfo = PrimeTime; + }; + DCF0C6152326036F008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C6012326036F008B45A0; + remoteInfo = FavoritePrimes; + }; + DCF0C61F23260383008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C59A2326032B008B45A0; + remoteInfo = ComposableArchitecture; + }; + DCF0C62123260387008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C59A2326032B008B45A0; + remoteInfo = ComposableArchitecture; + }; + DCF0C6232326038A008B45A0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC90716422FA102900B38B42 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DCF0C59A2326032B008B45A0; + remoteInfo = ComposableArchitecture; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + DCF0C5B12326032B008B45A0 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + DCF0C6182326036F008B45A0 /* FavoritePrimes.framework in Embed Frameworks */, + DCF0C5B22326032B008B45A0 /* ComposableArchitecture.framework in Embed Frameworks */, + DCF0C5D423260348008B45A0 /* Counter.framework in Embed Frameworks */, + DCF0C5F62326035C008B45A0 /* PrimeModal.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + DC29217322FB231F006090DF /* WolframAlpha.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WolframAlpha.swift; sourceTree = ""; }; + DC39325F230241AF005A0B0A /* PrimeTime.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = PrimeTime.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + DC90716C22FA102900B38B42 /* PrimeTime.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PrimeTime.app; sourceTree = BUILT_PRODUCTS_DIR; }; + DC90716F22FA102900B38B42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + DC90717122FA102900B38B42 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + DC90717322FA102900B38B42 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + DC90717522FA102A00B38B42 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DC90717822FA102A00B38B42 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + DC90717B22FA102A00B38B42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + DC90717D22FA102A00B38B42 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DC90718222FA102B00B38B42 /* PrimeTimeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrimeTimeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DC90718622FA102B00B38B42 /* PrimeTimeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimeTimeTests.swift; sourceTree = ""; }; + DC90718822FA102B00B38B42 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DC90719122FA151D00B38B42 /* Util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; + DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ComposableArchitecture.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C59D2326032B008B45A0 /* ComposableArchitecture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ComposableArchitecture.h; sourceTree = ""; }; + DCF0C59E2326032B008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C5A32326032B008B45A0 /* ComposableArchitectureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ComposableArchitectureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C5AA2326032B008B45A0 /* ComposableArchitectureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposableArchitectureTests.swift; sourceTree = ""; }; + DCF0C5AC2326032B008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C5BE23260348008B45A0 /* Counter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Counter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C5C023260348008B45A0 /* Counter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Counter.h; sourceTree = ""; }; + DCF0C5C123260348008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C5C623260348008B45A0 /* CounterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CounterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C5CD23260348008B45A0 /* CounterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CounterTests.swift; sourceTree = ""; }; + DCF0C5CF23260348008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C5E02326035C008B45A0 /* PrimeModal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PrimeModal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C5E22326035C008B45A0 /* PrimeModal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrimeModal.h; sourceTree = ""; }; + DCF0C5E32326035C008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C5E82326035C008B45A0 /* PrimeModalTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrimeModalTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C5EF2326035C008B45A0 /* PrimeModalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimeModalTests.swift; sourceTree = ""; }; + DCF0C5F12326035C008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FavoritePrimes.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C6042326036F008B45A0 /* FavoritePrimes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FavoritePrimes.h; sourceTree = ""; }; + DCF0C6052326036F008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C60A2326036F008B45A0 /* FavoritePrimesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FavoritePrimesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF0C6112326036F008B45A0 /* FavoritePrimesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritePrimesTests.swift; sourceTree = ""; }; + DCF0C6132326036F008B45A0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DCF0C627232603B7008B45A0 /* ComposableArchitecture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposableArchitecture.swift; sourceTree = ""; }; + DCF0C62923260405008B45A0 /* FavoritePrimes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritePrimes.swift; sourceTree = ""; }; + DCF0C62B2326040D008B45A0 /* PrimeModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimeModal.swift; sourceTree = ""; }; + DCF0C62D23260414008B45A0 /* Counter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Counter.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DC90716922FA102900B38B42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C6172326036F008B45A0 /* FavoritePrimes.framework in Frameworks */, + DCF0C5B02326032B008B45A0 /* ComposableArchitecture.framework in Frameworks */, + DCF0C5D323260348008B45A0 /* Counter.framework in Frameworks */, + DCF0C5F52326035C008B45A0 /* PrimeModal.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DC90717F22FA102B00B38B42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5982326032B008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5A02326032B008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5A42326032B008B45A0 /* ComposableArchitecture.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5BB23260348008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5C323260348008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5C723260348008B45A0 /* Counter.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5DD2326035C008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5E52326035C008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5E92326035C008B45A0 /* PrimeModal.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5FF2326036F008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C6072326036F008B45A0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C60B2326036F008B45A0 /* FavoritePrimes.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + DC90716322FA102900B38B42 = { + isa = PBXGroup; + children = ( + DC39325F230241AF005A0B0A /* PrimeTime.playground */, + DC90716E22FA102900B38B42 /* PrimeTime */, + DC90718522FA102B00B38B42 /* PrimeTimeTests */, + DCF0C59C2326032B008B45A0 /* ComposableArchitecture */, + DCF0C5A92326032B008B45A0 /* ComposableArchitectureTests */, + DCF0C5BF23260348008B45A0 /* Counter */, + DCF0C5CC23260348008B45A0 /* CounterTests */, + DCF0C5E12326035C008B45A0 /* PrimeModal */, + DCF0C5EE2326035C008B45A0 /* PrimeModalTests */, + DCF0C6032326036F008B45A0 /* FavoritePrimes */, + DCF0C6102326036F008B45A0 /* FavoritePrimesTests */, + DC90716D22FA102900B38B42 /* Products */, + ); + sourceTree = ""; + }; + DC90716D22FA102900B38B42 /* Products */ = { + isa = PBXGroup; + children = ( + DC90716C22FA102900B38B42 /* PrimeTime.app */, + DC90718222FA102B00B38B42 /* PrimeTimeTests.xctest */, + DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */, + DCF0C5A32326032B008B45A0 /* ComposableArchitectureTests.xctest */, + DCF0C5BE23260348008B45A0 /* Counter.framework */, + DCF0C5C623260348008B45A0 /* CounterTests.xctest */, + DCF0C5E02326035C008B45A0 /* PrimeModal.framework */, + DCF0C5E82326035C008B45A0 /* PrimeModalTests.xctest */, + DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */, + DCF0C60A2326036F008B45A0 /* FavoritePrimesTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + DC90716E22FA102900B38B42 /* PrimeTime */ = { + isa = PBXGroup; + children = ( + DC90716F22FA102900B38B42 /* AppDelegate.swift */, + DC90717122FA102900B38B42 /* SceneDelegate.swift */, + DC90717322FA102900B38B42 /* ContentView.swift */, + DC90719122FA151D00B38B42 /* Util.swift */, + DC90717522FA102A00B38B42 /* Assets.xcassets */, + DC90717A22FA102A00B38B42 /* LaunchScreen.storyboard */, + DC90717D22FA102A00B38B42 /* Info.plist */, + DC90717722FA102A00B38B42 /* Preview Content */, + ); + path = PrimeTime; + sourceTree = ""; + }; + DC90717722FA102A00B38B42 /* Preview Content */ = { + isa = PBXGroup; + children = ( + DC90717822FA102A00B38B42 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + DC90718522FA102B00B38B42 /* PrimeTimeTests */ = { + isa = PBXGroup; + children = ( + DC90718622FA102B00B38B42 /* PrimeTimeTests.swift */, + DC90718822FA102B00B38B42 /* Info.plist */, + ); + path = PrimeTimeTests; + sourceTree = ""; + }; + DCF0C59C2326032B008B45A0 /* ComposableArchitecture */ = { + isa = PBXGroup; + children = ( + DCF0C59D2326032B008B45A0 /* ComposableArchitecture.h */, + DCF0C627232603B7008B45A0 /* ComposableArchitecture.swift */, + DCF0C59E2326032B008B45A0 /* Info.plist */, + ); + path = ComposableArchitecture; + sourceTree = ""; + }; + DCF0C5A92326032B008B45A0 /* ComposableArchitectureTests */ = { + isa = PBXGroup; + children = ( + DCF0C5AA2326032B008B45A0 /* ComposableArchitectureTests.swift */, + DCF0C5AC2326032B008B45A0 /* Info.plist */, + ); + path = ComposableArchitectureTests; + sourceTree = ""; + }; + DCF0C5BF23260348008B45A0 /* Counter */ = { + isa = PBXGroup; + children = ( + DCF0C5C023260348008B45A0 /* Counter.h */, + DC29217322FB231F006090DF /* WolframAlpha.swift */, + DCF0C62D23260414008B45A0 /* Counter.swift */, + DCF0C5C123260348008B45A0 /* Info.plist */, + ); + path = Counter; + sourceTree = ""; + }; + DCF0C5CC23260348008B45A0 /* CounterTests */ = { + isa = PBXGroup; + children = ( + DCF0C5CD23260348008B45A0 /* CounterTests.swift */, + DCF0C5CF23260348008B45A0 /* Info.plist */, + ); + path = CounterTests; + sourceTree = ""; + }; + DCF0C5E12326035C008B45A0 /* PrimeModal */ = { + isa = PBXGroup; + children = ( + DCF0C5E22326035C008B45A0 /* PrimeModal.h */, + DCF0C62B2326040D008B45A0 /* PrimeModal.swift */, + DCF0C5E32326035C008B45A0 /* Info.plist */, + ); + path = PrimeModal; + sourceTree = ""; + }; + DCF0C5EE2326035C008B45A0 /* PrimeModalTests */ = { + isa = PBXGroup; + children = ( + DCF0C5EF2326035C008B45A0 /* PrimeModalTests.swift */, + DCF0C5F12326035C008B45A0 /* Info.plist */, + ); + path = PrimeModalTests; + sourceTree = ""; + }; + DCF0C6032326036F008B45A0 /* FavoritePrimes */ = { + isa = PBXGroup; + children = ( + DCF0C6042326036F008B45A0 /* FavoritePrimes.h */, + DCF0C62923260405008B45A0 /* FavoritePrimes.swift */, + DCF0C6052326036F008B45A0 /* Info.plist */, + ); + path = FavoritePrimes; + sourceTree = ""; + }; + DCF0C6102326036F008B45A0 /* FavoritePrimesTests */ = { + isa = PBXGroup; + children = ( + DCF0C6112326036F008B45A0 /* FavoritePrimesTests.swift */, + DCF0C6132326036F008B45A0 /* Info.plist */, + ); + path = FavoritePrimesTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + DCF0C5962326032B008B45A0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5AD2326032B008B45A0 /* ComposableArchitecture.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5B923260348008B45A0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5D023260348008B45A0 /* Counter.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5DB2326035C008B45A0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5F22326035C008B45A0 /* PrimeModal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5FD2326036F008B45A0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C6142326036F008B45A0 /* FavoritePrimes.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + DC90716B22FA102900B38B42 /* PrimeTime */ = { + isa = PBXNativeTarget; + buildConfigurationList = DC90718B22FA102B00B38B42 /* Build configuration list for PBXNativeTarget "PrimeTime" */; + buildPhases = ( + DC90716822FA102900B38B42 /* Sources */, + DC90716922FA102900B38B42 /* Frameworks */, + DC90716A22FA102900B38B42 /* Resources */, + DCF0C5B12326032B008B45A0 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C5AF2326032B008B45A0 /* PBXTargetDependency */, + DCF0C5D223260348008B45A0 /* PBXTargetDependency */, + DCF0C5F42326035C008B45A0 /* PBXTargetDependency */, + DCF0C6162326036F008B45A0 /* PBXTargetDependency */, + ); + name = PrimeTime; + productName = PrimeTime; + productReference = DC90716C22FA102900B38B42 /* PrimeTime.app */; + productType = "com.apple.product-type.application"; + }; + DC90718122FA102B00B38B42 /* PrimeTimeTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DC90718E22FA102B00B38B42 /* Build configuration list for PBXNativeTarget "PrimeTimeTests" */; + buildPhases = ( + DC90717E22FA102B00B38B42 /* Sources */, + DC90717F22FA102B00B38B42 /* Frameworks */, + DC90718022FA102B00B38B42 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DC90718422FA102B00B38B42 /* PBXTargetDependency */, + ); + name = PrimeTimeTests; + productName = PrimeTimeTests; + productReference = DC90718222FA102B00B38B42 /* PrimeTimeTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DCF0C59A2326032B008B45A0 /* ComposableArchitecture */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5B72326032B008B45A0 /* Build configuration list for PBXNativeTarget "ComposableArchitecture" */; + buildPhases = ( + DCF0C5962326032B008B45A0 /* Headers */, + DCF0C5972326032B008B45A0 /* Sources */, + DCF0C5982326032B008B45A0 /* Frameworks */, + DCF0C5992326032B008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ComposableArchitecture; + productName = ComposableArchitecture; + productReference = DCF0C59B2326032B008B45A0 /* ComposableArchitecture.framework */; + productType = "com.apple.product-type.framework"; + }; + DCF0C5A22326032B008B45A0 /* ComposableArchitectureTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5B82326032B008B45A0 /* Build configuration list for PBXNativeTarget "ComposableArchitectureTests" */; + buildPhases = ( + DCF0C59F2326032B008B45A0 /* Sources */, + DCF0C5A02326032B008B45A0 /* Frameworks */, + DCF0C5A12326032B008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C5A62326032B008B45A0 /* PBXTargetDependency */, + DCF0C5A82326032B008B45A0 /* PBXTargetDependency */, + ); + name = ComposableArchitectureTests; + productName = ComposableArchitectureTests; + productReference = DCF0C5A32326032B008B45A0 /* ComposableArchitectureTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DCF0C5BD23260348008B45A0 /* Counter */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5D523260348008B45A0 /* Build configuration list for PBXNativeTarget "Counter" */; + buildPhases = ( + DCF0C5B923260348008B45A0 /* Headers */, + DCF0C5BA23260348008B45A0 /* Sources */, + DCF0C5BB23260348008B45A0 /* Frameworks */, + DCF0C5BC23260348008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CAD67E1D2332982E000C7787 /* PBXTargetDependency */, + DCF0C6242326038A008B45A0 /* PBXTargetDependency */, + ); + name = Counter; + productName = Counter; + productReference = DCF0C5BE23260348008B45A0 /* Counter.framework */; + productType = "com.apple.product-type.framework"; + }; + DCF0C5C523260348008B45A0 /* CounterTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5D823260348008B45A0 /* Build configuration list for PBXNativeTarget "CounterTests" */; + buildPhases = ( + DCF0C5C223260348008B45A0 /* Sources */, + DCF0C5C323260348008B45A0 /* Frameworks */, + DCF0C5C423260348008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C5C923260348008B45A0 /* PBXTargetDependency */, + DCF0C5CB23260348008B45A0 /* PBXTargetDependency */, + ); + name = CounterTests; + productName = CounterTests; + productReference = DCF0C5C623260348008B45A0 /* CounterTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DCF0C5DF2326035C008B45A0 /* PrimeModal */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5F72326035C008B45A0 /* Build configuration list for PBXNativeTarget "PrimeModal" */; + buildPhases = ( + DCF0C5DB2326035C008B45A0 /* Headers */, + DCF0C5DC2326035C008B45A0 /* Sources */, + DCF0C5DD2326035C008B45A0 /* Frameworks */, + DCF0C5DE2326035C008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C62223260387008B45A0 /* PBXTargetDependency */, + ); + name = PrimeModal; + productName = PrimeModal; + productReference = DCF0C5E02326035C008B45A0 /* PrimeModal.framework */; + productType = "com.apple.product-type.framework"; + }; + DCF0C5E72326035C008B45A0 /* PrimeModalTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C5FA2326035C008B45A0 /* Build configuration list for PBXNativeTarget "PrimeModalTests" */; + buildPhases = ( + DCF0C5E42326035C008B45A0 /* Sources */, + DCF0C5E52326035C008B45A0 /* Frameworks */, + DCF0C5E62326035C008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C5EB2326035C008B45A0 /* PBXTargetDependency */, + DCF0C5ED2326035C008B45A0 /* PBXTargetDependency */, + ); + name = PrimeModalTests; + productName = PrimeModalTests; + productReference = DCF0C5E82326035C008B45A0 /* PrimeModalTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DCF0C6012326036F008B45A0 /* FavoritePrimes */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C6192326036F008B45A0 /* Build configuration list for PBXNativeTarget "FavoritePrimes" */; + buildPhases = ( + DCF0C5FD2326036F008B45A0 /* Headers */, + DCF0C5FE2326036F008B45A0 /* Sources */, + DCF0C5FF2326036F008B45A0 /* Frameworks */, + DCF0C6002326036F008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C62023260383008B45A0 /* PBXTargetDependency */, + ); + name = FavoritePrimes; + productName = FavoritePrimes; + productReference = DCF0C6022326036F008B45A0 /* FavoritePrimes.framework */; + productType = "com.apple.product-type.framework"; + }; + DCF0C6092326036F008B45A0 /* FavoritePrimesTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DCF0C61C2326036F008B45A0 /* Build configuration list for PBXNativeTarget "FavoritePrimesTests" */; + buildPhases = ( + DCF0C6062326036F008B45A0 /* Sources */, + DCF0C6072326036F008B45A0 /* Frameworks */, + DCF0C6082326036F008B45A0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DCF0C60D2326036F008B45A0 /* PBXTargetDependency */, + DCF0C60F2326036F008B45A0 /* PBXTargetDependency */, + ); + name = FavoritePrimesTests; + productName = FavoritePrimesTests; + productReference = DCF0C60A2326036F008B45A0 /* FavoritePrimesTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DC90716422FA102900B38B42 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = "Point-Free"; + TargetAttributes = { + DC90716B22FA102900B38B42 = { + CreatedOnToolsVersion = 11.0; + }; + DC90718122FA102B00B38B42 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = DC90716B22FA102900B38B42; + }; + DCF0C59A2326032B008B45A0 = { + CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; + }; + DCF0C5A22326032B008B45A0 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = DC90716B22FA102900B38B42; + }; + DCF0C5BD23260348008B45A0 = { + CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; + }; + DCF0C5C523260348008B45A0 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = DC90716B22FA102900B38B42; + }; + DCF0C5DF2326035C008B45A0 = { + CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; + }; + DCF0C5E72326035C008B45A0 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = DC90716B22FA102900B38B42; + }; + DCF0C6012326036F008B45A0 = { + CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; + }; + DCF0C6092326036F008B45A0 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = DC90716B22FA102900B38B42; + }; + }; + }; + buildConfigurationList = DC90716722FA102900B38B42 /* Build configuration list for PBXProject "PrimeTime" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = DC90716322FA102900B38B42; + productRefGroup = DC90716D22FA102900B38B42 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DC90716B22FA102900B38B42 /* PrimeTime */, + DC90718122FA102B00B38B42 /* PrimeTimeTests */, + DCF0C59A2326032B008B45A0 /* ComposableArchitecture */, + DCF0C5A22326032B008B45A0 /* ComposableArchitectureTests */, + DCF0C5BD23260348008B45A0 /* Counter */, + DCF0C5C523260348008B45A0 /* CounterTests */, + DCF0C5DF2326035C008B45A0 /* PrimeModal */, + DCF0C5E72326035C008B45A0 /* PrimeModalTests */, + DCF0C6012326036F008B45A0 /* FavoritePrimes */, + DCF0C6092326036F008B45A0 /* FavoritePrimesTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DC90716A22FA102900B38B42 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC90717C22FA102A00B38B42 /* LaunchScreen.storyboard in Resources */, + DC90717922FA102A00B38B42 /* Preview Assets.xcassets in Resources */, + DC90717622FA102A00B38B42 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DC90718022FA102B00B38B42 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5992326032B008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5A12326032B008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5BC23260348008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5C423260348008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5DE2326035C008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5E62326035C008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C6002326036F008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C6082326036F008B45A0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DC90716822FA102900B38B42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC90717022FA102900B38B42 /* AppDelegate.swift in Sources */, + DC90717222FA102900B38B42 /* SceneDelegate.swift in Sources */, + DC90717422FA102900B38B42 /* ContentView.swift in Sources */, + DC90719222FA151D00B38B42 /* Util.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DC90717E22FA102B00B38B42 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC90718722FA102B00B38B42 /* PrimeTimeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5972326032B008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C628232603B7008B45A0 /* ComposableArchitecture.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C59F2326032B008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5AB2326032B008B45A0 /* ComposableArchitectureTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5BA23260348008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C62E23260414008B45A0 /* Counter.swift in Sources */, + CAD67E2023329887000C7787 /* WolframAlpha.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5C223260348008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5CE23260348008B45A0 /* CounterTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5DC2326035C008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C62C2326040D008B45A0 /* PrimeModal.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5E42326035C008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C5F02326035C008B45A0 /* PrimeModalTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C5FE2326036F008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C62A23260405008B45A0 /* FavoritePrimes.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DCF0C6062326036F008B45A0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DCF0C6122326036F008B45A0 /* FavoritePrimesTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + CAD67E1D2332982E000C7787 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C5DF2326035C008B45A0 /* PrimeModal */; + targetProxy = CAD67E1C2332982E000C7787 /* PBXContainerItemProxy */; + }; + DC90718422FA102B00B38B42 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC90716B22FA102900B38B42 /* PrimeTime */; + targetProxy = DC90718322FA102B00B38B42 /* PBXContainerItemProxy */; + }; + DCF0C5A62326032B008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C59A2326032B008B45A0 /* ComposableArchitecture */; + targetProxy = DCF0C5A52326032B008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5A82326032B008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC90716B22FA102900B38B42 /* PrimeTime */; + targetProxy = DCF0C5A72326032B008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5AF2326032B008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C59A2326032B008B45A0 /* ComposableArchitecture */; + targetProxy = DCF0C5AE2326032B008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5C923260348008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C5BD23260348008B45A0 /* Counter */; + targetProxy = DCF0C5C823260348008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5CB23260348008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC90716B22FA102900B38B42 /* PrimeTime */; + targetProxy = DCF0C5CA23260348008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5D223260348008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C5BD23260348008B45A0 /* Counter */; + targetProxy = DCF0C5D123260348008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5EB2326035C008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C5DF2326035C008B45A0 /* PrimeModal */; + targetProxy = DCF0C5EA2326035C008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5ED2326035C008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC90716B22FA102900B38B42 /* PrimeTime */; + targetProxy = DCF0C5EC2326035C008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C5F42326035C008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C5DF2326035C008B45A0 /* PrimeModal */; + targetProxy = DCF0C5F32326035C008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C60D2326036F008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C6012326036F008B45A0 /* FavoritePrimes */; + targetProxy = DCF0C60C2326036F008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C60F2326036F008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC90716B22FA102900B38B42 /* PrimeTime */; + targetProxy = DCF0C60E2326036F008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C6162326036F008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C6012326036F008B45A0 /* FavoritePrimes */; + targetProxy = DCF0C6152326036F008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C62023260383008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C59A2326032B008B45A0 /* ComposableArchitecture */; + targetProxy = DCF0C61F23260383008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C62223260387008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C59A2326032B008B45A0 /* ComposableArchitecture */; + targetProxy = DCF0C62123260387008B45A0 /* PBXContainerItemProxy */; + }; + DCF0C6242326038A008B45A0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DCF0C59A2326032B008B45A0 /* ComposableArchitecture */; + targetProxy = DCF0C6232326038A008B45A0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + DC90717A22FA102A00B38B42 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + DC90717B22FA102A00B38B42 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DC90718922FA102B00B38B42 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + DC90718A22FA102B00B38B42 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DC90718C22FA102B00B38B42 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "PrimeTime/Preview\\ Content"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = PrimeTime/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeTime; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + DC90718D22FA102B00B38B42 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "PrimeTime/Preview\\ Content"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = PrimeTime/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeTime; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + DC90718F22FA102B00B38B42 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = PrimeTimeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeTimeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Debug; + }; + DC90719022FA102B00B38B42 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = PrimeTimeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeTimeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Release; + }; + DCF0C5B32326032B008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = ComposableArchitecture/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.ComposableArchitecture; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DCF0C5B42326032B008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = ComposableArchitecture/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.ComposableArchitecture; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DCF0C5B52326032B008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = ComposableArchitectureTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.ComposableArchitectureTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Debug; + }; + DCF0C5B62326032B008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = ComposableArchitectureTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.ComposableArchitectureTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Release; + }; + DCF0C5D623260348008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Counter/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.Counter; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DCF0C5D723260348008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Counter/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.Counter; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DCF0C5D923260348008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = CounterTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.CounterTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Debug; + }; + DCF0C5DA23260348008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = CounterTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.CounterTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Release; + }; + DCF0C5F82326035C008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = PrimeModal/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeModal; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DCF0C5F92326035C008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = PrimeModal/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeModal; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DCF0C5FB2326035C008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = PrimeModalTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeModalTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Debug; + }; + DCF0C5FC2326035C008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = PrimeModalTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.PrimeModalTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Release; + }; + DCF0C61A2326036F008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = FavoritePrimes/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.FavoritePrimes; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DCF0C61B2326036F008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = FavoritePrimes/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.FavoritePrimes; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DCF0C61D2326036F008B45A0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = FavoritePrimesTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.FavoritePrimesTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Debug; + }; + DCF0C61E2326036F008B45A0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = FavoritePrimesTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = co.pointfree.FavoritePrimesTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrimeTime.app/PrimeTime"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DC90716722FA102900B38B42 /* Build configuration list for PBXProject "PrimeTime" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC90718922FA102B00B38B42 /* Debug */, + DC90718A22FA102B00B38B42 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DC90718B22FA102B00B38B42 /* Build configuration list for PBXNativeTarget "PrimeTime" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC90718C22FA102B00B38B42 /* Debug */, + DC90718D22FA102B00B38B42 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DC90718E22FA102B00B38B42 /* Build configuration list for PBXNativeTarget "PrimeTimeTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC90718F22FA102B00B38B42 /* Debug */, + DC90719022FA102B00B38B42 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5B72326032B008B45A0 /* Build configuration list for PBXNativeTarget "ComposableArchitecture" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5B32326032B008B45A0 /* Debug */, + DCF0C5B42326032B008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5B82326032B008B45A0 /* Build configuration list for PBXNativeTarget "ComposableArchitectureTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5B52326032B008B45A0 /* Debug */, + DCF0C5B62326032B008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5D523260348008B45A0 /* Build configuration list for PBXNativeTarget "Counter" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5D623260348008B45A0 /* Debug */, + DCF0C5D723260348008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5D823260348008B45A0 /* Build configuration list for PBXNativeTarget "CounterTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5D923260348008B45A0 /* Debug */, + DCF0C5DA23260348008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5F72326035C008B45A0 /* Build configuration list for PBXNativeTarget "PrimeModal" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5F82326035C008B45A0 /* Debug */, + DCF0C5F92326035C008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C5FA2326035C008B45A0 /* Build configuration list for PBXNativeTarget "PrimeModalTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C5FB2326035C008B45A0 /* Debug */, + DCF0C5FC2326035C008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C6192326036F008B45A0 /* Build configuration list for PBXNativeTarget "FavoritePrimes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C61A2326036F008B45A0 /* Debug */, + DCF0C61B2326036F008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DCF0C61C2326036F008B45A0 /* Build configuration list for PBXNativeTarget "FavoritePrimesTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DCF0C61D2326036F008B45A0 /* Debug */, + DCF0C61E2326036F008B45A0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DC90716422FA102900B38B42 /* Project object */; +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..d6a81a64 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/AppDelegate.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/AppDelegate.swift new file mode 100644 index 00000000..c9606eeb --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/AppDelegate.swift @@ -0,0 +1,17 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + } +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/AppIcon.appiconset/Contents.json b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d8db8d65 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/Contents.json b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Base.lproj/LaunchScreen.storyboard b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/ContentView.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/ContentView.swift new file mode 100644 index 00000000..31ab8fdb --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/ContentView.swift @@ -0,0 +1,132 @@ +import Combine +import ComposableArchitecture +import Counter +import FavoritePrimes +import SwiftUI + +struct AppState { + var count = 0 + var favoritePrimes: [Int] = [] + var loggedInUser: User? = nil + var activityFeed: [Activity] = [] + + struct Activity { + let timestamp: Date + let type: ActivityType + + enum ActivityType { + case addedFavoritePrime(Int) + case removedFavoritePrime(Int) + } + } + + struct User { + let id: Int + let name: String + let bio: String + } +} + +enum AppAction { +// case counter(CounterAction) +// case primeModal(PrimeModalAction) + case counterView(CounterViewAction) + case favoritePrimes(FavoritePrimesAction) + + var favoritePrimes: FavoritePrimesAction? { + get { + guard case let .favoritePrimes(value) = self else { return nil } + return value + } + set { + guard case .favoritePrimes = self, let newValue = newValue else { return } + self = .favoritePrimes(newValue) + } + } + + var counterView: CounterViewAction? { + get { + guard case let .counterView(value) = self else { return nil } + return value + } + set { + guard case .counterView = self, let newValue = newValue else { return } + self = .counterView(newValue) + } + } +} + +extension AppState { + var counterView: CounterViewState { + get { + CounterViewState( + count: self.count, + favoritePrimes: self.favoritePrimes + ) + } + set { + self.count = newValue.count + self.favoritePrimes = newValue.favoritePrimes + } + } +} + +let appReducer: (inout AppState, AppAction) -> Void = combine( + pullback(counterViewReducer, value: \.counterView, action: \.counterView), + pullback(favoritePrimesReducer, value: \.favoritePrimes, action: \.favoritePrimes) +) + +func activityFeed( + _ reducer: @escaping (inout AppState, AppAction) -> Void +) -> (inout AppState, AppAction) -> Void { + + return { state, action in + switch action { + case .counterView(.counter): + break + case .counterView(.primeModal(.removeFavoritePrimeTapped)): + state.activityFeed.append(.init(timestamp: Date(), type: .removedFavoritePrime(state.count))) + + case .counterView(.primeModal(.saveFavoritePrimeTapped)): + state.activityFeed.append(.init(timestamp: Date(), type: .addedFavoritePrime(state.count))) + + case let .favoritePrimes(.deleteFavoritePrimes(indexSet)): + for index in indexSet { + state.activityFeed.append(.init(timestamp: Date(), type: .removedFavoritePrime(state.favoritePrimes[index]))) + } + } + + reducer(&state, action) + } +} + +struct ContentView: View { + @ObservedObject var store: Store + + var body: some View { + NavigationView { + List { + NavigationLink( + "Counter demo", + destination: CounterView( + store: self.store + .view( + value: { $0.counterView }, + action: { .counterView($0) } + ) + ) + ) + NavigationLink( + "Favorite primes", + destination: FavoritePrimesView( + store: self.store.view( + value: { $0.favoritePrimes }, + action: { .favoritePrimes($0) } + ) + ) + ) + } + .navigationBarTitle("State management") + } + } +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Info.plist b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Info.plist new file mode 100644 index 00000000..9742bf0f --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Preview Content/Preview Assets.xcassets/Contents.json b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/SceneDelegate.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/SceneDelegate.swift new file mode 100644 index 00000000..a32410f9 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/SceneDelegate.swift @@ -0,0 +1,29 @@ +import ComposableArchitecture +import SwiftUI +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + if let windowScene = scene as? UIWindowScene { + let window = UIWindow(windowScene: windowScene) + window.rootViewController = UIHostingController( + rootView: ContentView( + store: Store( + initialValue: AppState(), + reducer: with( + appReducer, + compose( + logging, + activityFeed + ) + ) + ) + ) + ) + self.window = window + window.makeKeyAndVisible() + } + } +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Util.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Util.swift new file mode 100644 index 00000000..b9509ff8 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTime/Util.swift @@ -0,0 +1,14 @@ +func compose( + _ f: @escaping (B) -> C, + _ g: @escaping (A) -> B + ) + -> (A) -> C { + + return { (a: A) -> C in + f(g(a)) + } +} + +func with(_ a: A, _ f: (A) throws -> B) rethrows -> B { + return try f(a) +} diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/Info.plist b/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/Info.plist new file mode 100644 index 00000000..64d65ca4 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/PrimeTimeTests.swift b/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/PrimeTimeTests.swift new file mode 100644 index 00000000..08d240f1 --- /dev/null +++ b/0075-modular-state-management-wtp/PrimeTime/PrimeTimeTests/PrimeTimeTests.swift @@ -0,0 +1,34 @@ +// +// PrimeTimeTests.swift +// PrimeTimeTests +// +// Created by Stephen Celis on 8/6/19. +// Copyright © 2019 Point-Free. All rights reserved. +// + +import XCTest +@testable import PrimeTime + +class PrimeTimeTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/0075-modular-state-management-wtp/README.md b/0075-modular-state-management-wtp/README.md new file mode 100644 index 00000000..e57bc535 --- /dev/null +++ b/0075-modular-state-management-wtp/README.md @@ -0,0 +1,5 @@ +## [Point-Free](https://www.pointfree.co) + +> #### This directory contains code from Point-Free Episode: [Modular State Management: The Point](https://www.pointfree.co/episodes/ep75-modular-state-management-the-point) +> +> We’ve now fully modularized our app by extracting its reducers and views into their own modules. Each screen of our app can be run as a little app on its own so that we can test its functionality, all without needing to know how it’s plugged into the app as a whole. And _this_ is the point of modular state management! diff --git a/README.md b/README.md index 69d3c642..d89d6e29 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,4 @@ This repository is the home of code written on episodes of 1. [Modular State Management: Reducers](0072-modular-state-management-reducers) 1. [Modular State Management: View State](0073-modular-state-management-view-state) 1. [Modular State Management: View Actions](0074-modular-state-management-view-actions) +1. [Modular State Management: The Point](0075-modular-state-management-wtp)