Skip to content

Commit

Permalink
Merge branch 'release/1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Shinichiro Oba committed Nov 3, 2017
2 parents c5dc48f + baedb32 commit a9de190
Show file tree
Hide file tree
Showing 25 changed files with 308 additions and 154 deletions.
8 changes: 8 additions & 0 deletions BoostRemote.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
CB0BF7E51F8BD873004CCD4F /* VerticalSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0BF7E41F8BD873004CCD4F /* VerticalSlider.swift */; };
CB0BF7E71F8BDD30004CCD4F /* StickView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB0BF7E61F8BDD30004CCD4F /* StickView.swift */; };
CB385A4A1F4E35210061EBE4 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CB385A491F4E35210061EBE4 /* Settings.bundle */; };
CB3BE8B11F2FF2F4000561F7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB3BE8B01F2FF2F4000561F7 /* AppDelegate.swift */; };
CB3BE8B31F2FF2F4000561F7 /* ControllerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB3BE8B21F2FF2F4000561F7 /* ControllerViewController.swift */; };
Expand Down Expand Up @@ -45,6 +47,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
CB0BF7E41F8BD873004CCD4F /* VerticalSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalSlider.swift; sourceTree = "<group>"; };
CB0BF7E61F8BDD30004CCD4F /* StickView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickView.swift; sourceTree = "<group>"; };
CB385A491F4E35210061EBE4 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
CB3BE8AD1F2FF2F4000561F7 /* BoostRemote.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BoostRemote.app; sourceTree = BUILT_PRODUCTS_DIR; };
CB3BE8B01F2FF2F4000561F7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -110,6 +114,8 @@
CB3BE8B41F2FF2F4000561F7 /* Main.storyboard */,
CB3BE8B21F2FF2F4000561F7 /* ControllerViewController.swift */,
CBF9D2B81F3CACA800B97E11 /* MoveHubManager.swift */,
CB0BF7E41F8BD873004CCD4F /* VerticalSlider.swift */,
CB0BF7E61F8BDD30004CCD4F /* StickView.swift */,
CBF9D2F51F3CDAC700B97E11 /* Data+HexString.swift */,
CBF9D2D81F3CB63300B97E11 /* Redux */,
CBF9D2D71F3CB62700B97E11 /* MoveHub */,
Expand Down Expand Up @@ -259,6 +265,8 @@
files = (
CBF9D2B91F3CACA800B97E11 /* MoveHubManager.swift in Sources */,
CB3BE8B31F2FF2F4000561F7 /* ControllerViewController.swift in Sources */,
CB0BF7E51F8BD873004CCD4F /* VerticalSlider.swift in Sources */,
CB0BF7E71F8BDD30004CCD4F /* StickView.swift in Sources */,
CBD94E8A1F392C310037ED71 /* Motor.swift in Sources */,
CBD94E861F391D7F0037ED71 /* Action.swift in Sources */,
CB3BE8B11F2FF2F4000561F7 /* AppDelegate.swift in Sources */,
Expand Down
Binary file modified BoostRemote/Assets.xcassets/connected.imageset/connected.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/connecting1.imageset/connecting1.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/connecting2.imageset/connecting2.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/connecting3.imageset/connecting3.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/connecting4.imageset/connecting4.pdf
Binary file not shown.
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/left.imageset/left.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/offline.imageset/offline.pdf
Binary file not shown.
12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/portA.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "portA.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/portB.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "portB.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/portC.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "portC.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
12 changes: 12 additions & 0 deletions BoostRemote/Assets.xcassets/portD.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "portD.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/right.imageset/right.pdf
Binary file not shown.
Binary file modified BoostRemote/Assets.xcassets/thumb.imageset/thumb.pdf
Binary file not shown.
164 changes: 77 additions & 87 deletions BoostRemote/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

116 changes: 52 additions & 64 deletions BoostRemote/ControllerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,57 +12,48 @@ import ReactiveSwift
import Result
import ReSwift

class ControllerViewController: UIViewController, StoreSubscriber {
class ControllerViewController: UIViewController {

@IBOutlet weak var leftSlider: UISlider!
@IBOutlet weak var rightSlider: UISlider!
@IBOutlet private weak var stickA: StickView!
@IBOutlet private weak var stickB: StickView!
@IBOutlet private weak var stickC: StickView!
@IBOutlet private weak var stickD: StickView!

@IBOutlet weak var centerSlider: UISlider!
@IBOutlet weak var centerLabel: UILabel!
@IBOutlet private weak var connectButtonImageView: UIImageView!

@IBOutlet weak var connectButtonImageView: UIImageView!
private let connectionState = MutableProperty(ConnectionState.disconnected)

let connectionState = MutableProperty(ConnectionState.disconnected)

var leftMotor: Motor? = Motor(port: .A)
var rightMotor: Motor? = Motor(port: .B)
var centerMotor: Motor? {
private var motors: [Port: Motor] = [:] {
didSet {
let alpha: CGFloat
if let motor = centerMotor {
centerLabel.text = motor.port.description
alpha = 1.0
} else {
alpha = 0.0
}

UIView.animate(withDuration: 0.2) {
self.centerSlider.alpha = alpha
self.centerLabel.alpha = alpha
}
stickC?.isHidden = !motors.keys.contains(.C)
stickD?.isHidden = !motors.keys.contains(.D)
}
}

override func viewDidLoad() {
super.viewDidLoad()

setup(slider: leftSlider)
setup(slider: rightSlider)
setup(slider: centerSlider)

centerSlider.alpha = 0.0
centerLabel.alpha = 0.0

setupConnectButtonImageView()

signal(for: leftSlider).observeValues { [weak self] (value) in
self?.sendCommand(motor: self?.leftMotor, power: value)
stickA.port = .A
stickB.port = .B
stickC.port = .C
stickD.port = .D

stickC.isHidden = true
stickD.isHidden = true

signal(for: stickA.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .A, power: value)
}
signal(for: stickB.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .B, power: value)
}
signal(for: rightSlider).observeValues { [weak self] (value) in
self?.sendCommand(motor: self?.rightMotor, power: value)
signal(for: stickC.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .C, power: value)
}
signal(for: centerSlider).observeValues { [weak self] (value) in
self?.sendCommand(motor: self?.centerMotor, power: value)
signal(for: stickD.slider).observeValues { [weak self] (value) in
self?.sendCommand(port: .D, power: value)
}
}

Expand All @@ -76,33 +67,10 @@ class ControllerViewController: UIViewController, StoreSubscriber {
StoreCenter.store.unsubscribe(self)
}

func newState(state: State) {
connectionState.value = state.connectionState

if state.connectionState == .connected {
centerMotor = state.portState
.flatMap { (port, type) -> Motor? in
return type == .interactiveMotor ? Motor(port: port) : nil
}
.first
} else {
centerMotor = nil
}
}

private func setup(slider: UISlider) {
slider.setThumbImage(UIImage(named: "thumb")?.withRenderingMode(.alwaysTemplate), for: .normal)
slider.setMinimumTrackImage(UIImage(named: "left")?.withRenderingMode(.alwaysTemplate), for: .normal)
slider.setMaximumTrackImage(UIImage(named: "right")?.withRenderingMode(.alwaysTemplate), for: .normal)

slider.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi * -0.5))
}

private func setupConnectButtonImageView() {
connectButtonImageView.animationDuration = 1
connectButtonImageView.animationRepeatCount = -1
connectButtonImageView.animationImages = (1...4).map { "connecting\($0)" }
.flatMap { UIImage(named: $0)?.withRenderingMode(.alwaysTemplate) }
connectButtonImageView.animationImages = (1...4).map { "connecting\($0)" }.flatMap { UIImage(named: $0) }

connectionState.producer.startWithValues { [weak self] (state) in
if state == .connecting {
Expand All @@ -122,7 +90,7 @@ class ControllerViewController: UIViewController, StoreSubscriber {
case .offline, .unsupported:
imageName = "offline"
}
self?.connectButtonImageView.image = UIImage(named: imageName)?.withRenderingMode(.alwaysTemplate)
self?.connectButtonImageView.image = UIImage(named: imageName)
}
}

Expand All @@ -138,8 +106,8 @@ class ControllerViewController: UIViewController, StoreSubscriber {
return Signal<Int8, NoError>.merge(valueSignal, touchUpSignal).skipRepeats()
}

private func sendCommand(motor: Motor?, power: Int8) {
if let command = motor?.powerCommand(power: power) {
private func sendCommand(port: Port, power: Int8) {
if let command = motors[port]?.powerCommand(power: power) {
ActionCenter.send(command: command)
}
}
Expand All @@ -150,7 +118,7 @@ class ControllerViewController: UIViewController, StoreSubscriber {
present(alert, animated: true, completion: nil)
}

@IBAction func connectButtonPushed(_ sender: Any) {
@IBAction private func connectButtonPushed(_ sender: Any) {
switch connectionState.value {
case .disconnected:
ActionCenter.startScan()
Expand All @@ -165,3 +133,23 @@ class ControllerViewController: UIViewController, StoreSubscriber {
}
}
}

extension ControllerViewController: StoreSubscriber {

func newState(state: State) {
connectionState.value = state.connectionState

let ports: [Port] = [.A, .B, .C, .D]
for port in ports {
motors[port] = state.portState[port].flatMap { type -> Motor? in
guard state.connectionState == .connected else { return nil }
switch type {
case .builtInMotor, .interactiveMotor:
return Motor(port: port)
default:
return nil
}
}
}
}
}
4 changes: 2 additions & 2 deletions BoostRemote/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.3</string>
<string>1.1.0</string>
<key>CFBundleVersion</key>
<string>14</string>
<string>15</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSBluetoothPeripheralUsageDescription</key>
Expand Down
2 changes: 1 addition & 1 deletion BoostRemote/Settings.bundle/Root.plist
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>DefaultValue</key>
<string>1.0.3</string>
<string>1.1.0</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
Expand Down
76 changes: 76 additions & 0 deletions BoostRemote/StickView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// StickView.swift
// BoostRemote
//
// Created by ooba on 09/10/2017.
// Copyright © 2017 bricklife.com. All rights reserved.
//

import UIKit

@IBDesignable
class StickView: UIView {

var slider: UISlider {
return verticalSlider.slider
}

var port: Port? {
didSet {
imageView.image = port.flatMap { UIImage(named: "port\($0)") }
}
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)

initialize()
}

required override init(frame: CGRect) {
super.init(frame: frame)

initialize()
}

private func initialize() {
addSubview(verticalSlider)
addSubview(imageView)

NSLayoutConstraint.activate([
verticalSlider.topAnchor.constraint(equalTo: topAnchor),
verticalSlider.leftAnchor.constraint(equalTo: leftAnchor),
verticalSlider.rightAnchor.constraint(equalTo: rightAnchor),
])

NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 16),
imageView.bottomAnchor.constraint(equalTo: bottomAnchor),
imageView.centerXAnchor.constraint(equalTo: centerXAnchor),
imageView.heightAnchor.constraint(equalToConstant: 32),
])
}

private let verticalSlider: VerticalSlider = {
let verticalSlider = VerticalSlider()
verticalSlider.translatesAutoresizingMaskIntoConstraints = false

verticalSlider.slider.setThumbImage(UIImage(named: "thumb"), for: .normal)
verticalSlider.slider.setMinimumTrackImage(UIImage(named: "left"), for: .normal)
verticalSlider.slider.setMaximumTrackImage(UIImage(named: "right"), for: .normal)

verticalSlider.slider.maximumValue = 10
verticalSlider.slider.minimumValue = -10
verticalSlider.slider.value = 0

return verticalSlider
}()

private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false

imageView.contentMode = .center
return imageView
}()
}
Loading

0 comments on commit a9de190

Please sign in to comment.