Skip to content

Commit

Permalink
Initial
Browse files Browse the repository at this point in the history
  • Loading branch information
hip4yes committed Jan 22, 2020
1 parent c801aae commit b6465b1
Show file tree
Hide file tree
Showing 182 changed files with 21,034 additions and 15 deletions.
14 changes: 9 additions & 5 deletions Aurum.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Pod::Spec.new do |s|
s.name = 'Aurum'
s.version = '0.1.0'
s.summary = 'A short description of Aurum.'
s.summary = 'Evolution of Amber architecture'

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
Expand All @@ -21,14 +21,15 @@ Pod::Spec.new do |s|
TODO: Add long description of the pod here.
DESC

s.homepage = 'https://github.com/hip4yes/Aurum'
s.homepage = 'https://github.com/Anvics/Aurum'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'hip4yes' => 'narhipov92@gmail.com' }
s.source = { :git => 'https://github.com/hip4yes/Aurum.git', :tag => s.version.to_s }
s.author = { 'Nikita Arkhipov' => 'nikitarkhipov@gmail.com' }
s.source = { :git => 'https://github.com/Anvics/Aurum.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

s.ios.deployment_target = '8.0'
s.ios.deployment_target = '10.0'
s.swift_version = '5.0'

s.source_files = 'Aurum/Classes/**/*'

Expand All @@ -39,4 +40,7 @@ TODO: Add long description of the pod here.
# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
# s.dependency 'AFNetworking', '~> 2.3'
s.frameworks = 'UIKit'
s.dependency 'Bond'

end
51 changes: 51 additions & 0 deletions Aurum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Aurum.swift
// AmberPlayground
//
// Created by Nikita Arkhipov on 22.01.2020.
// Copyright © 2020 Anvics. All rights reserved.
//

import UIKit

public class Aurum{
public static var shouldLogActions = true

static func toggled(action: Any){
if !shouldLogActions { return }
print("-----------------------------")
print("\(type(of: action)).\(action)")
}

public static func setInitial(controller: UIViewController, window: UIWindow){
window.rootViewController = controller
window.makeKeyAndVisible()
}

public static func setInitial(controller: AurumLink, window: UIWindow!){
setInitial(controller: controller.instantiate(), window: window)
}

public static func setInitial<Module: AurumModuleConfigurator>(module: Module.Type, data: Module.RequiredData, window: UIWindow!){
setInitial(controller: Module().create(data: data).controller, window: window)
}

public static func setInitial<Module: AurumModuleConfigurator>(module: Module.Type, window: UIWindow!) where Module.RequiredData == Void{
setInitial(controller: Module().create().controller, window: window)
}


// private static var simulatedActions: [SimulatedActionType] = []
//
// public static func setInitial(){
//
// }
//
// public static func simulate(actions: [SimulatedActionType]){
// simulatedActions = actions
// }
//
// static func moduleInitialized<Module: AurumModule>(module: Module){
// simulatedActions = simulatedActions.filter { $0.isProcessed(module: module) }
// }
}
Empty file removed Aurum/Classes/ReplaceMe.swift
Empty file.
121 changes: 121 additions & 0 deletions AurumActor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// AurumActor.swift
// AmberPlayground
//
// Created by Nikita Arkhipov on 22.01.2020.
// Copyright © 2020 Anvics. All rights reserved.
//

import UIKit

public struct AurumLink{
let storyboard: String
let id: String

func instantiate() -> UIViewController{
return UIStoryboard(name: storyboard, bundle: nil).instantiateViewController(withIdentifier: id)
}
}

public enum AurumRouteType{
var isEmbedding: Bool{
switch self {
case .embed(_), .embedFullscreen, .cleanEmbed(_), .cleanEmbedFullscreen: return true
default: return false
}
}

var isCleanEmbedding: Bool{
switch self {
case .cleanEmbed(_), .cleanEmbedFullscreen: return true
default: return false
}
}

case present, push, show, baseReplace, replace(UIView.AnimationOptions), embed(UIView), embedFullscreen, cleanEmbed(UIView), cleanEmbedFullscreen
}

public enum AurumRouteCloseType{
case close, dismiss, pop, popToRoot, unembed
}

public class AurumModuleData<A: AurumAction>{
let controller: UIViewController
let inputActionListener: (A) -> Void

init(controller: UIViewController, inputActionListener: @escaping (A) -> Void) {
self.controller = controller
self.inputActionListener = inputActionListener
}
}

public class AurumActor<Action: AurumAction, InputAction: AurumAction, OutputAction: AurumAction> {

typealias Reducer = (Action) -> Void
typealias InputReducer = (InputAction) -> Void
typealias OutputReducer = (OutputAction) -> Void

private weak var rootController: UIViewController?
private weak var controller: UIViewController?

private let reducer: Reducer
private let inputReducer: InputReducer
private let outputReducer: OutputReducer

init(rootController: UIViewController?, controller: UIViewController?, reducer: @escaping Reducer, inputReducer: @escaping InputReducer, outputReducer: @escaping OutputReducer) {
self.rootController = rootController ?? controller
self.controller = controller
self.reducer = reducer
self.inputReducer = inputReducer
self.outputReducer = outputReducer
}

func act(_ action: Action){
reducer(action)
}

func output(_ action: OutputAction){
outputReducer(action)
}

func route(to toController: UIViewController, type: AurumRouteType = .show, animated: Bool = true){
switch type {
case .present: rootController?.present(toController, animated: animated, completion: nil)
case .push: rootController?.navigationController?.push(toController, animated: animated)
case .show: rootController?.show(toController, animated: animated)
case .baseReplace: rootController?.replaceWith(toController, animation: .transitionFlipFromLeft)
case .replace(let animation): rootController?.replaceWith(toController, animation: animation)
case .embedFullscreen, .cleanEmbedFullscreen:
if type.isCleanEmbedding { controller?.view.unembedAll() }
if let vc = controller { toController.embedIn(view: vc.view, container: vc) }
case .embed(let view), .cleanEmbed(let view):
if type.isCleanEmbedding { view.unembedAll() }
if let vc = controller { toController.embedIn(view: view, container: vc) }
}
}

func route(link: AurumLink, type: AurumRouteType = .show, animated: Bool = true){
route(to: link.instantiate(), type: type, animated: animated)
}

@discardableResult func route<Module: AurumModuleConfigurator>(module: Module.Type, data: Module.RequiredData, type: AurumRouteType = .show, animated: Bool = true, outputListener: ((Module.OutputAction) -> Void)? = nil) -> AurumModuleData<Module.InputAction>{
let config = Module()
let data = config.create(data: data, rootController: type.isEmbedding ? rootController : nil, outputListener: outputListener)
route(to: data.controller, type: type, animated: animated)
return data
}

@discardableResult func route<Module: AurumModuleConfigurator>(module: Module.Type, type: AurumRouteType = .show, animated: Bool = true, outputListener: ((Module.OutputAction) -> Void)? = nil) -> AurumModuleData<Module.InputAction> where Module.RequiredData == Void{
return route(module: module, data: (), type: type, animated: animated, outputListener: outputListener)
}

func close(type: AurumRouteCloseType = .close, animated: Bool = true){
switch type {
case .close: controller?.close(animated: animated)
case .dismiss: controller?.dismiss(animated: animated)
case .pop: controller?.pop(animated: animated)
case .popToRoot: controller?.popToRoot(animated: animated)
case .unembed: controller?.unembed()
}
}
}
96 changes: 96 additions & 0 deletions AurumController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// AurumController.swift
// AmberPlayground
//
// Created by Nikita Arkhipov on 22.01.2020.
// Copyright © 2020 Anvics. All rights reserved.
//

import UIKit

public protocol AurumStoreSetupable {
func set<S, A>(store: AurumStore<S, A>)
}

public protocol AurumController: class, AurumStoreSetupable {
associatedtype State: AurumState
associatedtype Action: AurumAction
var store: AurumStore<State, Action>! { get set }
}

extension AurumController{
func set<S, A>(store: AurumStore<S, A>){
guard let s = store as? AurumStore<State, Action> else { fatalError("\(type(of: self)) failed to set store: expected <\(State.self), \(Action.self)> got <\(S.self), \(A.self)>") }
self.store = s
}
}

private var UIView_Associated_Embeded: UInt8 = 0
extension UIView{
var embedded: [UIViewController]{
get {
return objc_getAssociatedObject(self, &UIView_Associated_Embeded) as? [UIViewController] ?? []
}
set {
objc_setAssociatedObject(self, &UIView_Associated_Embeded, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

func unembedAll(){
embedded.forEach { $0.unembed(shouldModifyEmbedArray: false) }
embedded = []
}
}

extension UIViewController{
public func push(_ viewController: UIViewController, animated: Bool){
navigationController?.pushViewController(viewController, animated: animated)
}

public func embedIn(view: UIView, container: UIViewController){
self.view.frame = view.bounds
container.addChild(self)
view.addSubview(self.view)
view.embedded.append(self)
didMove(toParent: container)
}

public func show(_ viewController: UIViewController, animated: Bool){
if navigationController != nil { push(viewController, animated: true) }
else { present(viewController, animated: true, completion: nil) }
}

public func close(animated: Bool){
if let nav = navigationController{ nav.popViewController(animated: animated) }
else if parent != nil { unembed() }
else{ dismiss(animated: animated, completion: nil) }
}

public func dismiss(animated: Bool) {
dismiss(animated: animated, completion: nil)
}

public func pop(animated: Bool){
navigationController?.popViewController(animated: animated)
}

public func popToRoot(animated: Bool){
navigationController?.popToRootViewController(animated: animated)
}

public func unembed(shouldModifyEmbedArray: Bool = true){
removeFromParent()
if let index = view.superview?.embedded.firstIndex(of: self), shouldModifyEmbedArray{
view.superview?.embedded.remove(at: index)
}
view.removeFromSuperview()
didMove(toParent: nil)
}

public func replaceWith(_ vc: UIViewController, animation: UIView.AnimationOptions){
guard let currentVC = UIApplication.shared.keyWindow?.rootViewController else { fatalError() }
UIView.transition(from: currentVC.view, to: vc.view, duration: 0.4, options: animation) { _ in
UIApplication.shared.keyWindow?.rootViewController = vc
}
}
}
65 changes: 65 additions & 0 deletions AurumMiddleware.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// AurumMiddleware.swift
// AmberPlayground
//
// Created by Nikita Arkhipov on 22.01.2020.
// Copyright © 2020 Anvics. All rights reserved.
//

import Foundation

public typealias EmptyClosure = () -> Void

public protocol AurumMiddleware {
func preprocess()

func process(complete: EmptyClosure)

func postprocess()
}

extension AurumMiddleware{
func preprocess(){}

func process(complete: EmptyClosure){ complete() }

func postprocess(){}
}

public protocol AurumMiddlwareProvider {
associatedtype State: AurumState
associatedtype Action: AurumAction
associatedtype InputAction: AurumAction
associatedtype OutputAction: AurumAction

func provide(forAction action: Action, state: State) -> [AurumMiddleware]

func provide(forInputAction action: InputAction, state: State) -> [AurumMiddleware]
func provide(forOutputAction action: OutputAction, state: State) -> [AurumMiddleware]
}

extension AurumMiddlwareProvider{
func provide(forInputAction action: InputAction, state: State) -> [AurumMiddleware] { return [] }
func provide(forOutputAction action: OutputAction, state: State) -> [AurumMiddleware] { return [] }

func wrapped() -> AurumMiddlewareProviderWrapper<State, Action, InputAction, OutputAction>{
return AurumMiddlewareProviderWrapper(provider: self)
}
}

public class AurumMiddlewareProviderWrapper<State: AurumState, Action: AurumAction, InputAction: AurumAction, OutputAction: AurumAction>{

typealias MiddlewareProvider = (Action, State) -> [AurumMiddleware]
typealias InputMiddlewareProvider = (InputAction, State) -> [AurumMiddleware]
typealias OutputMiddlewareProvider = (OutputAction, State) -> [AurumMiddleware]

let middleware: MiddlewareProvider
let inputMiddleware: InputMiddlewareProvider
let outputMiddleware: OutputMiddlewareProvider

init<Provider: AurumMiddlwareProvider>(provider: Provider) where Provider.State == State, Provider.Action == Action, Provider.InputAction == InputAction, Provider.OutputAction == OutputAction{
middleware = provider.provide
inputMiddleware = provider.provide
outputMiddleware = provider.provide
}
}
Loading

0 comments on commit b6465b1

Please sign in to comment.