Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
.build/
.swiftpm/
.hg
.svn
CVS

.DS_Store
Desktop.ini
Thumbs.db
ehthumbs.db
*~
.#*
.*.swp
.*.swo
11 changes: 7 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ import PackageDescription

let package = Package(
name: "Incremental",
platforms: [.iOS(.v12)],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "Incremental",
targets: ["Incremental"]),
.library(name: "Resin",
targets: ["Resin"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
dependencies: [],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "Incremental",
dependencies: []),
.target(
name: "Resin",
dependencies: ["Incremental"]),
.testTarget(
name: "IncrementalTests",
dependencies: ["Incremental"]),
Expand Down
455 changes: 455 additions & 0 deletions SampleApp/SampleApp.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -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"
}
}
6 changes: 6 additions & 0 deletions SampleApp/SampleApp/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
25 changes: 25 additions & 0 deletions SampleApp/SampleApp/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
43 changes: 43 additions & 0 deletions SampleApp/SampleApp/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
67 changes: 67 additions & 0 deletions SampleApp/SampleApp/MainApp/AppCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Resin
import SafariServices
import UIKit

typealias AppEnvironment = (
userDefaults: UserDefaults,
loadStations: (@escaping (Result<StationsState, Error>) -> Void) -> Void
)

public final class AppCoordinator {
let presentationRouter: PresentationRouter<AppState>

let tabBarController: TabBarController

let store: Store<AppState>

public init() {
let store = RootStore(state: AppState())

let environment: AppEnvironment = (
userDefaults: .standard,
loadStations: dummyLoadStations
)

self.presentationRouter = PresentationRouter(store: store)

let parcels: [Parcel<AppState>] = [
mapAppStateParcel(),
makeUndergroundParcel(environment: environment).unfocused(by: \AppState.undergroundState),
]

for p in parcels {
let delivery = p.build(store)
store.integrate(delivery: delivery)
presentationRouter.register(delivery: delivery)
}

store.addImplicitNavigationMiddleware()
store.addPresentationReducers()

self.store = store

tabBarController = presentationRouter.makeViewController(identifier: TabBarController.PresentationIdentifier().typeErased) as! TabBarController
tabBarController.presentationRouter = presentationRouter.typeErased
tabBarController.actionHandler = store
}
}

func mapAppStateParcel() -> Parcel<AppState> {
Parcel { store in
var delivery = Parcel<AppState>.Delivery()

delivery.middlewares = [
ForegroundDaemon(state: store.state.map { _ in ArbitraryState() }).unfocused(),
]
delivery.reducers = [
SetTabReducer().typeErased,
]

delivery.presentationRoutes = [
SFSafariViewController.presentationRoute.typeErased.unfocused(),
TabBarController.presentationRoute.typeErased,
]

return delivery
}
}
22 changes: 22 additions & 0 deletions SampleApp/SampleApp/MainApp/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Foundation
import UIKit

public final class AppDelegate: NSObject {
@objc public var window: UIWindow?

let appCoordinator = AppCoordinator()

public override init() {
super.init()
}
}

extension AppDelegate: UIApplicationDelegate {
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = appCoordinator.tabBarController
window!.makeKeyAndVisible()

return true
}
}
19 changes: 19 additions & 0 deletions SampleApp/SampleApp/MainApp/AppState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation
import Resin

public struct AppState: Equatable {
enum Tab: Int, Equatable {
case underground = 0
case ticket = 1
}

var counter: Int = 0

var undergroundState: UndergroundState = UndergroundState()

var modalStack: [AnyPresentationIdentifier] = []

var selectedTab: Tab = .underground
}


22 changes: 22 additions & 0 deletions SampleApp/SampleApp/MainApp/ForegroundDaemon.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import Foundation
import Incremental
import Resin
import UIKit

final class ForegroundDaemon: Daemon<ArbitraryState> {
public override func observe(state: I<ArbitraryState>) -> Disposable? {
NotificationCenter.default.addObserver(
self,
selector: #selector(observe(note:)),
name: UIApplication.didBecomeActiveNotification,
object: nil
)

return nil
}

@objc
func observe(note: Notification) {
dispatch(LoadStationsAction())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Resin
import SafariServices

extension SFSafariViewController {
public struct PresentationIdentifier: Resin.PresentationIdentifier {
public var url: URL

public init(url: URL) {
self.url = url
}
}

static var presentationRoute: PresentationRoute<PresentationIdentifier, ArbitraryState, SFSafariViewController> {
return PresentationRoute { identifier, _ in
SFSafariViewController(url: identifier.url)
}
}
}
Loading