Add Throbber host component (#71)

This component is rendered to `UIActivityViewIndicator` in `TokamakUIKit`. This component would be a great helper for future examples that demonstrate asynchronous effects, e.g. networking.

* Add Throbber host component
* Make .gray Throbber variety the default
This commit is contained in:
Max Desiatov 2019-03-20 13:01:41 +00:00 committed by GitHub
parent 901e0f792a
commit 25fa624d7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 145 additions and 10 deletions

View File

@ -1,10 +1,10 @@
PODS:
- Tokamak (0.1.0)
- TokamakAppKit (0.1.0):
- Tokamak (0.1.2)
- TokamakAppKit (0.1.2):
- Tokamak (~> 0.1)
- TokamakDemo (0.1.0):
- TokamakDemo (0.1.2):
- Tokamak (~> 0.1)
- TokamakUIKit (0.1.0):
- TokamakUIKit (0.1.2):
- Tokamak (~> 0.1)
DEPENDENCIES:
@ -24,10 +24,10 @@ EXTERNAL SOURCES:
:path: ".."
SPEC CHECKSUMS:
Tokamak: 20e3e854a9ebf3d8a65211f3f45b7c40d2519e89
TokamakAppKit: 5b5cdeab9b51091dbc696e0c891d025dc298e6e2
TokamakDemo: c848bba790d0c5adbabbcc8378fd480ee7d2af7a
TokamakUIKit: cfed01e60c62a5aff7f8440eb57c9641dadb7709
Tokamak: 595fe4fb92b23d92289e2387526b10405a2eb144
TokamakAppKit: c7fb2d9d32e08209536b3719b9303e6c90e3f830
TokamakDemo: 08c1c8cf8263311775ebe794df90ed9d7e7a3ed2
TokamakUIKit: fa9b5bcb2f0f0c4fd5c4c20473ff01cc6b20f32d
PODFILE CHECKSUM: c2d722f96b8e3bcf25d99c2246c9a11ba5223765

View File

@ -26,6 +26,7 @@
A6FEF7952227C1CC008BB292 /* Scroll.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6FEF7942227C1CC008BB292 /* Scroll.swift */; };
A75611AA848D0C595B661357 /* libPods-TokamakDemo-iOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0EAAE47EB8E7CE32883E7C /* libPods-TokamakDemo-iOS.a */; };
D11DB6432219C03000013FC3 /* Timer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11DB6422219C03000013FC3 /* Timer.swift */; };
D1B90570224258AC0077CD5E /* Throbber.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B9056F224258AC0077CD5E /* Throbber.swift */; };
D1BB3D302223F6B400C30062 /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BB3D2F2223F6B400C30062 /* Animation.swift */; };
D1BFAF772215795900845EA0 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF762215795900845EA0 /* Router.swift */; };
D1BFAF7B22158B4000845EA0 /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BFAF7A22158B4000845EA0 /* List.swift */; };
@ -76,6 +77,7 @@
BA8336497AD51B80F43A0A8C /* Pods-TokamakDemo-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TokamakDemo-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TokamakDemo-iOS/Pods-TokamakDemo-iOS.debug.xcconfig"; sourceTree = "<group>"; };
C6DA99382B6892EAB361742F /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
D11DB6422219C03000013FC3 /* Timer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timer.swift; sourceTree = "<group>"; };
D1B9056F224258AC0077CD5E /* Throbber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throbber.swift; sourceTree = "<group>"; };
D1BB3D2F2223F6B400C30062 /* Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = "<group>"; };
D1BFAF762215795900845EA0 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
D1BFAF7A22158B4000845EA0 /* List.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = List.swift; sourceTree = "<group>"; };
@ -230,6 +232,7 @@
D1BB3D2F2223F6B400C30062 /* Animation.swift */,
A6FEF7942227C1CC008BB292 /* Scroll.swift */,
A6D6538022312263007FA886 /* CollectionExample.swift */,
D1B9056F224258AC0077CD5E /* Throbber.swift */,
);
path = Components;
sourceTree = "<group>";
@ -397,6 +400,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D1B90570224258AC0077CD5E /* Throbber.swift in Sources */,
D1BFAF7B22158B4000845EA0 /* List.swift in Sources */,
D1F2C3272214407B008358DC /* TableModal.swift in Sources */,
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */,

View File

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>COPYRIGHT</key>
<string>Copyright © 2019 Tokamak contributors. Tokamak is available under the Apache 2.0
license. See the LICENSE file for more info.</string>
<string>Copyright © 2019 Tokamak contributors. Tokamak is available under the
// Apache 2.0 license. See the LICENSE file for more info.</string>
</dict>
</plist>

View File

@ -0,0 +1,29 @@
//
// Throbber.swift
// TokamakDemo-iOS
//
// Created by Max Desiatov on 20/03/2019.
// Copyright © 2019 Tokamak contributors. Tokamak is available under the
// Apache 2.0 license. See the LICENSE file for more info.
//
import Tokamak
struct ThrobberExample: PureLeafComponent {
typealias Props = Null
static func render(props: Null) -> AnyNode {
return
View.node(
.init(Style(
Edges.equal(to: .parent),
backgroundColor: .black
)),
Throbber.node(.init(
Style(Edges.equal(to: .parent)),
isAnimating: true,
variety: .whiteLarge
))
)
}
}

View File

@ -25,6 +25,7 @@ enum AppRoute: String, CaseIterable {
case snakeGame = "Snake Game"
case scrollView = "Scroll"
case collection = "Collection View"
case throbber
}
extension AppRoute: CustomStringConvertible {
@ -76,6 +77,8 @@ struct Router: NavigationRouter {
result = ScrollViewExample.node()
case .collection:
result = CollectionExample.node()
case .throbber:
result = ThrobberExample.node()
}
return NavigationItem.node(

View File

@ -0,0 +1,39 @@
//
// Throbber.swift
// Tokamak
//
// Created by Max Desiatov on 20/03/2019.
//
public struct Throbber: HostComponent {
public struct Props: Equatable, StyleProps {
public enum Variety {
case whiteLarge
case white
case gray
}
/// Value of this property overrides the value of `variety`
public let color: Color?
public let isAnimating: Bool
public let hidesWhenStopped: Bool
public let style: Style?
public let variety: Variety
public init(
_ style: Style? = nil,
color: Color? = nil,
isAnimating: Bool = false,
hidesWhenStopped: Bool = true,
variety: Variety = .gray
) {
self.style = style
self.color = color
self.isAnimating = isAnimating
self.hidesWhenStopped = hidesWhenStopped
self.variety = variety
}
}
public typealias Children = Null
}

View File

@ -0,0 +1,51 @@
//
// Throbber.swift
// TokamakUIKit
//
// Created by Max Desiatov on 20/03/2019.
//
import Tokamak
import UIKit
extension UIActivityIndicatorView.Style {
init(_ variety: Throbber.Props.Variety) {
switch variety {
case .gray:
self = .gray
case .white:
self = .white
case .whiteLarge:
self = .whiteLarge
}
}
}
final class TokamakActivityIndicatorView: UIActivityIndicatorView, Default {
public static var defaultValue: TokamakActivityIndicatorView {
return TokamakActivityIndicatorView()
}
}
extension Throbber: UIViewComponent {
public typealias RefTarget = UIActivityIndicatorView
static func update(view box: ViewBox<TokamakActivityIndicatorView>,
_ props: Throbber.Props,
_: Null) {
let view = box.view
view.style = UIActivityIndicatorView.Style(props.variety)
view.color = props.color.flatMap { UIColor($0) }
view.hidesWhenStopped = props.hidesWhenStopped
switch (view.isAnimating, props.isAnimating) {
case (true, false):
view.stopAnimating()
case (false, true):
view.startAnimating()
default:
()
}
}
}

View File

@ -40,6 +40,8 @@
D15E0456223582FD00BB0571 /* Left.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15E0444223582EE00BB0571 /* Left.swift */; };
D15E0457223582FD00BB0571 /* XAxisConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15E0445223582EE00BB0571 /* XAxisConstraint.swift */; };
D15E0458223582FD00BB0571 /* YAxisConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15E0446223582EE00BB0571 /* YAxisConstraint.swift */; };
D1B90572224259FA0077CD5E /* Throbber.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B90571224259FA0077CD5E /* Throbber.swift */; };
D1B9057422425CED0077CD5E /* Throbber.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1B9057322425CED0077CD5E /* Throbber.swift */; };
OBJ_193 /* AnyEquatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* AnyEquatable.swift */; };
OBJ_194 /* AnyNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* AnyNode.swift */; };
OBJ_195 /* Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Components.swift */; };
@ -266,6 +268,8 @@
D15E0444223582EE00BB0571 /* Left.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Left.swift; sourceTree = "<group>"; };
D15E0445223582EE00BB0571 /* XAxisConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XAxisConstraint.swift; sourceTree = "<group>"; };
D15E0446223582EE00BB0571 /* YAxisConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YAxisConstraint.swift; sourceTree = "<group>"; };
D1B90571224259FA0077CD5E /* Throbber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throbber.swift; sourceTree = "<group>"; };
D1B9057322425CED0077CD5E /* Throbber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Throbber.swift; sourceTree = "<group>"; };
OBJ_10 /* AnyNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyNode.swift; sourceTree = "<group>"; };
OBJ_100 /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
OBJ_101 /* NavigationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItem.swift; sourceTree = "<group>"; };
@ -563,6 +567,7 @@
OBJ_28 /* Switch.swift */,
OBJ_29 /* TextField.swift */,
OBJ_30 /* View.swift */,
D1B90571224259FA0077CD5E /* Throbber.swift */,
);
path = Host;
sourceTree = "<group>";
@ -875,6 +880,7 @@
OBJ_107 /* Switch.swift */,
OBJ_108 /* TextField.swift */,
OBJ_109 /* View.swift */,
D1B9057322425CED0077CD5E /* Throbber.swift */,
);
path = Host;
sourceTree = "<group>";
@ -1058,6 +1064,7 @@
OBJ_213 /* ModalPresenter.swift in Sources */,
OBJ_214 /* NavigationItem.swift in Sources */,
OBJ_215 /* NavigationPresenter.swift in Sources */,
D1B90572224259FA0077CD5E /* Throbber.swift in Sources */,
OBJ_217 /* TabItem.swift in Sources */,
OBJ_219 /* Accessibility.swift in Sources */,
OBJ_220 /* Color.swift in Sources */,
@ -1207,6 +1214,7 @@
OBJ_354 /* Stepper.swift in Sources */,
OBJ_355 /* Switch.swift in Sources */,
OBJ_356 /* TextField.swift in Sources */,
D1B9057422425CED0077CD5E /* Throbber.swift in Sources */,
OBJ_357 /* View.swift in Sources */,
OBJ_358 /* Color.swift in Sources */,
OBJ_359 /* BaselineConstraint.swift in Sources */,

View File

@ -15,6 +15,7 @@
| [`Stepper`](https://github.com/MaxDesiatov/Tokamak/blob/master/Sources/Tokamak/Components/Host/Stepper.swift) | [`UIStepper`](https://developer.apple.com/documentation/uikit/uistepper) | not available yet |
| [`Switch`](https://github.com/MaxDesiatov/Tokamak/blob/master/Sources/Tokamak/Components/Host/Switch.swift) | [`UISwitch`](https://developer.apple.com/documentation/uikit/uiswitch) | not available yet |
| [`TextField`](https://github.com/MaxDesiatov/Tokamak/blob/master/Sources/Tokamak/Components/Host/TextField.swift) | [`UITextField`](https://developer.apple.com/documentation/uikit/uitextfield) | not available yet |
| [`Throbber`](https://github.com/MaxDesiatov/Tokamak/blob/master/Sources/Tokamak/Components/Host/Throbber.swift) | [`UIActivityIndicatorView`](https://developer.apple.com/documentation/uikit/uiactivityindicatorview) | not available yet |
| [`View`](https://github.com/MaxDesiatov/Tokamak/blob/master/Sources/Tokamak/Components/Host/View.swift) | [`UIView`](https://developer.apple.com/documentation/uikit/uiview) | [`NSView`](https://developer.apple.com/documentation/appkit/nsview) |
## Standard Presenter Components