Skip to content

Instantly share code, notes, and snippets.

@albertogiunta
Created January 9, 2020 14:29
Show Gist options
  • Save albertogiunta/94698cc241db25cba4e9c3b365d17c8e to your computer and use it in GitHub Desktop.
Save albertogiunta/94698cc241db25cba4e9c3b365d17c8e to your computer and use it in GitHub Desktop.
import Foundation
// MARK: Katana
public protocol State {}
public protocol AnyStateUpdater {}
public protocol AnySideEffect {}
public protocol AnySideEffectContext {
func getAnyState() -> State
}
// MARK: StoreKit
public struct StoreProduct {}
public struct SKPaymentTransaction {}
// MARK: Ramen Legacy
protocol LegacyLibs_StateWithMonopoly {
var monopolyState: LegacyLibs.MonopolyState { get set }
var productIDs: [String]? { get set }
}
enum LegacyLibs {
struct MonopolyState {
var productsList: [String: StoreProduct]?
var purchasedProductIDs: Set<String>
var ongoingTransactions: [SKPaymentTransaction]
init() { fatalError() }
}
}
// MARK: Ramen New
public struct MonetizationState {
public internal(set) var productsList: [String: StoreProduct]?
public internal(set) var purchasedProductIDs: Set<String>
public var productIDs: [String]?
public init() {
self.productsList = [:]
self.purchasedProductIDs = []
self.productIDs = []
}
internal init(from monopolyState: LegacyLibs.MonopolyState, _ productIDs: [String]?) {
self.productsList = monopolyState.productsList
self.purchasedProductIDs = monopolyState.purchasedProductIDs
self.productIDs = productIDs
}
}
public protocol StateWithRamen: State {
var ramen: RamenState { get set }
}
internal protocol StateWithLegacyLibs: LegacyLibs_StateWithMonopoly {
var monopolyState: LegacyLibs.MonopolyState { get set }
// plus conformance to all the other legacy StateWith... protocols
}
public struct RamenState: StateWithLegacyLibs {
// public
public var monetization: MonetizationState { MonetizationState(from: self.monopolyState, self.productIDs) }
// and all the other ramen new states ...
// internal
var monopolyState: LegacyLibs.MonopolyState
var productIDs: [String]?
// and all the other legacy states ...
// Settings: proposal for retrieving the settings with the app-specific settingsModel
var rawSettings: Data?
private static var settingsCache: (rawSettings: Data?, typedSettings: Any?)
public func settings<S: Codable>() -> S? {
guard Self.settingsCache.rawSettings != rawSettings else {
return Self.settingsCache.typedSettings as? S
}
let settings = try? JSONDecoder().decode(S.self, from: self.rawSettings!)
Self.settingsCache.rawSettings = self.rawSettings
Self.settingsCache.typedSettings = settings
return settings
}
}
// MARK: Legacy Dispatchable Example
protocol LegacyLibs_MonopolyStateUpdater: AnyStateUpdater {
func updatedState(currentState: inout LegacyLibs_StateWithMonopoly)
}
extension LegacyLibs_MonopolyStateUpdater {
public func updatedState(currentState: State) -> State {
guard var stateWithRamen = currentState as? StateWithRamen
else {
fatalError()
}
var stateWithMonopoly = stateWithRamen.ramen as LegacyLibs_StateWithMonopoly
self.updatedState(currentState: &stateWithMonopoly)
stateWithRamen.ramen = stateWithMonopoly as! RamenState
return stateWithRamen
}
}
extension LegacyLibs {
struct ProcessTransactions: AnySideEffect {
func anySideEffect(_ context: AnySideEffectContext) throws {
guard let state = (context.getAnyState() as? StateWithRamen)?.ramen
else {
fatalError()
}
let ongoingTransactions = state.monopolyState.ongoingTransactions
// and so on...
fatalError()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment