From f0cf5218f6a30c8692c781098fcbc97436436195 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Fri, 6 Oct 2017 23:02:19 +0100 Subject: [PATCH 01/12] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2dbe93d..7a336ac 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ Remote Control iOS app for LEGO® Boost ## Requirements -- Xcode 8.3 -- Swift 3.1 +- Xcode 9 +- Swift 4 - iOS 9 or higher - iOS device supporting Bluetooth Low Energy (BLE) - LEGO® Boost Move Hub From 0ba8a2bc9d6ee2d2bc5a94e954f79fb9bd5b7585 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Fri, 6 Oct 2017 23:17:46 +0100 Subject: [PATCH 02/12] Cleanup --- BoostRemote/ControllerViewController.swift | 53 ++++++++++++---------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/BoostRemote/ControllerViewController.swift b/BoostRemote/ControllerViewController.swift index 35f3774..ed05ebd 100644 --- a/BoostRemote/ControllerViewController.swift +++ b/BoostRemote/ControllerViewController.swift @@ -12,21 +12,21 @@ 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 leftSlider: UISlider! + @IBOutlet private weak var rightSlider: UISlider! - @IBOutlet weak var centerSlider: UISlider! - @IBOutlet weak var centerLabel: UILabel! + @IBOutlet private weak var centerSlider: UISlider! + @IBOutlet private weak var centerLabel: UILabel! - @IBOutlet weak var connectButtonImageView: UIImageView! + @IBOutlet private weak var connectButtonImageView: UIImageView! - let connectionState = MutableProperty(ConnectionState.disconnected) + private let connectionState = MutableProperty(ConnectionState.disconnected) - var leftMotor: Motor? = Motor(port: .A) - var rightMotor: Motor? = Motor(port: .B) - var centerMotor: Motor? { + private var leftMotor: Motor? = Motor(port: .A) + private var rightMotor: Motor? = Motor(port: .B) + private var centerMotor: Motor? { didSet { let alpha: CGFloat if let motor = centerMotor { @@ -76,20 +76,6 @@ 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) @@ -150,7 +136,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() @@ -165,3 +151,20 @@ class ControllerViewController: UIViewController, StoreSubscriber { } } } + +extension ControllerViewController: StoreSubscriber { + + 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 + } + } +} From 5c482f5d5d6dfa0474de9595412a08dba80a115f Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Mon, 9 Oct 2017 18:37:53 +0100 Subject: [PATCH 03/12] Introduce VerticalSlider class and StickView class --- BoostRemote.xcodeproj/project.pbxproj | 8 ++ BoostRemote/Base.lproj/Main.storyboard | 157 ++++++++++----------- BoostRemote/ControllerViewController.swift | 34 ++--- BoostRemote/StickView.swift | 77 ++++++++++ BoostRemote/VerticalSlider.swift | 44 ++++++ 5 files changed, 209 insertions(+), 111 deletions(-) create mode 100644 BoostRemote/StickView.swift create mode 100644 BoostRemote/VerticalSlider.swift diff --git a/BoostRemote.xcodeproj/project.pbxproj b/BoostRemote.xcodeproj/project.pbxproj index ef47433..aa351ef 100644 --- a/BoostRemote.xcodeproj/project.pbxproj +++ b/BoostRemote.xcodeproj/project.pbxproj @@ -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 */; }; @@ -45,6 +47,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + CB0BF7E41F8BD873004CCD4F /* VerticalSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalSlider.swift; sourceTree = ""; }; + CB0BF7E61F8BDD30004CCD4F /* StickView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickView.swift; sourceTree = ""; }; CB385A491F4E35210061EBE4 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 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 = ""; }; @@ -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 */, @@ -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 */, diff --git a/BoostRemote/Base.lproj/Main.storyboard b/BoostRemote/Base.lproj/Main.storyboard index 678a35e..b2c7e44 100644 --- a/BoostRemote/Base.lproj/Main.storyboard +++ b/BoostRemote/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -7,141 +7,126 @@ + - + - - + + - + - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - + - - - - - - + + + + + + + - + - + - - - - + + + + - - - - - + + + + - + - + diff --git a/BoostRemote/ControllerViewController.swift b/BoostRemote/ControllerViewController.swift index ed05ebd..62f5f75 100644 --- a/BoostRemote/ControllerViewController.swift +++ b/BoostRemote/ControllerViewController.swift @@ -14,11 +14,9 @@ import ReSwift class ControllerViewController: UIViewController { - @IBOutlet private weak var leftSlider: UISlider! - @IBOutlet private weak var rightSlider: UISlider! - - @IBOutlet private weak var centerSlider: UISlider! - @IBOutlet private weak var centerLabel: UILabel! + @IBOutlet private weak var leftStick: StickView! + @IBOutlet private weak var rightStick: StickView! + @IBOutlet private weak var centerStick: StickView! @IBOutlet private weak var connectButtonImageView: UIImageView! @@ -30,15 +28,14 @@ class ControllerViewController: UIViewController { didSet { let alpha: CGFloat if let motor = centerMotor { - centerLabel.text = motor.port.description + centerStick.text = motor.port.description alpha = 1.0 } else { alpha = 0.0 } UIView.animate(withDuration: 0.2) { - self.centerSlider.alpha = alpha - self.centerLabel.alpha = alpha + self.centerStick.alpha = alpha } } } @@ -46,22 +43,17 @@ class ControllerViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - setup(slider: leftSlider) - setup(slider: rightSlider) - setup(slider: centerSlider) - - centerSlider.alpha = 0.0 - centerLabel.alpha = 0.0 + centerStick.alpha = 0.0 setupConnectButtonImageView() - signal(for: leftSlider).observeValues { [weak self] (value) in + signal(for: leftStick.slider).observeValues { [weak self] (value) in self?.sendCommand(motor: self?.leftMotor, power: value) } - signal(for: rightSlider).observeValues { [weak self] (value) in + signal(for: rightStick.slider).observeValues { [weak self] (value) in self?.sendCommand(motor: self?.rightMotor, power: value) } - signal(for: centerSlider).observeValues { [weak self] (value) in + signal(for: centerStick.slider).observeValues { [weak self] (value) in self?.sendCommand(motor: self?.centerMotor, power: value) } } @@ -76,14 +68,6 @@ class ControllerViewController: UIViewController { StoreCenter.store.unsubscribe(self) } - 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 diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift new file mode 100644 index 0000000..2d43d27 --- /dev/null +++ b/BoostRemote/StickView.swift @@ -0,0 +1,77 @@ +// +// StickView.swift +// BoostRemote +// +// Created by ooba on 09/10/2017. +// Copyright © 2017 bricklife.com. All rights reserved. +// + +import UIKit + +@IBDesignable +class StickView: UIView { + + private let verticalSlider = VerticalSlider() + private let label = UILabel() + + var slider: UISlider { + return verticalSlider.slider + } + + @IBInspectable var text: String? { + didSet { + label.text = text + } + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + required override init(frame: CGRect) { + super.init(frame: frame) + + initialize() + } + + private func initialize() { + setupSlider() + setupLabel() + + verticalSlider.translatesAutoresizingMaskIntoConstraints = false + label.translatesAutoresizingMaskIntoConstraints = false + + addSubview(verticalSlider) + addSubview(label) + + NSLayoutConstraint.activate([ + verticalSlider.topAnchor.constraint(equalTo: topAnchor), + verticalSlider.leftAnchor.constraint(equalTo: leftAnchor), + verticalSlider.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + NSLayoutConstraint.activate([ + label.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 8), + label.bottomAnchor.constraint(equalTo: bottomAnchor), + label.centerXAnchor.constraint(equalTo: centerXAnchor), + label.heightAnchor.constraint(equalToConstant: 30), + ]) + } + + private func setupSlider() { + 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.maximumValue = 10 + slider.minimumValue = -10 + slider.value = 0 + } + + private func setupLabel() { + label.font = UIFont.systemFont(ofSize: 24) + label.textColor = .black + } +} diff --git a/BoostRemote/VerticalSlider.swift b/BoostRemote/VerticalSlider.swift new file mode 100644 index 0000000..7bd9f99 --- /dev/null +++ b/BoostRemote/VerticalSlider.swift @@ -0,0 +1,44 @@ +// +// VerticalSlider.swift +// BoostRemote +// +// Created by ooba on 09/10/2017. +// Copyright © 2017 bricklife.com. All rights reserved. +// + +import UIKit + +@IBDesignable +class VerticalSlider: UIView { + + let slider = UISlider() + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + initialize() + } + + required override init(frame: CGRect) { + super.init(frame: frame) + + initialize() + } + + private func initialize() { + addSubview(slider) + slider.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi * -0.5)) + } + + override func layoutSubviews() { + super.layoutSubviews() + + slider.bounds.size.width = bounds.height + slider.center.x = bounds.midX + slider.center.y = bounds.midY + } + + override var intrinsicContentSize: CGSize { + return CGSize(width: slider.intrinsicContentSize.height, height: slider.intrinsicContentSize.width) + } +} From fd8abca21ac67bcf131724eeaf6f329ccf9c710a Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 00:58:22 +0100 Subject: [PATCH 04/12] Update icons --- .../connected.imageset/connected.pdf | Bin 4695 -> 6541 bytes .../connecting1.imageset/connecting1.pdf | Bin 4333 -> 6674 bytes .../connecting2.imageset/connecting2.pdf | Bin 4329 -> 6672 bytes .../connecting3.imageset/connecting3.pdf | Bin 4327 -> 6674 bytes .../connecting4.imageset/connecting4.pdf | Bin 4336 -> 6674 bytes .../disconnected.imageset/disconnected.pdf | Bin 4330 -> 6670 bytes .../Assets.xcassets/left.imageset/left.pdf | Bin 3981 -> 4000 bytes .../offline.imageset/offline.pdf | Bin 9528 -> 6747 bytes .../portA.imageset/Contents.json | 12 ++++++++++++ .../Assets.xcassets/portA.imageset/portA.pdf | Bin 0 -> 4047 bytes .../portB.imageset/Contents.json | 12 ++++++++++++ .../Assets.xcassets/portB.imageset/portB.pdf | Bin 0 -> 6015 bytes .../portC.imageset/Contents.json | 12 ++++++++++++ .../Assets.xcassets/portC.imageset/portC.pdf | Bin 0 -> 3988 bytes .../portD.imageset/Contents.json | 12 ++++++++++++ .../Assets.xcassets/portD.imageset/portD.pdf | Bin 0 -> 4042 bytes .../Assets.xcassets/right.imageset/right.pdf | Bin 4005 -> 4019 bytes .../Assets.xcassets/thumb.imageset/thumb.pdf | Bin 3910 -> 3999 bytes 18 files changed, 48 insertions(+) create mode 100644 BoostRemote/Assets.xcassets/portA.imageset/Contents.json create mode 100644 BoostRemote/Assets.xcassets/portA.imageset/portA.pdf create mode 100644 BoostRemote/Assets.xcassets/portB.imageset/Contents.json create mode 100644 BoostRemote/Assets.xcassets/portB.imageset/portB.pdf create mode 100644 BoostRemote/Assets.xcassets/portC.imageset/Contents.json create mode 100644 BoostRemote/Assets.xcassets/portC.imageset/portC.pdf create mode 100644 BoostRemote/Assets.xcassets/portD.imageset/Contents.json create mode 100644 BoostRemote/Assets.xcassets/portD.imageset/portD.pdf diff --git a/BoostRemote/Assets.xcassets/connected.imageset/connected.pdf b/BoostRemote/Assets.xcassets/connected.imageset/connected.pdf index fae321ed2fc94422757dc559aceac11a90867232..8e5618485b5fe4441f25cd9b912222d0187de363 100644 GIT binary patch delta 3119 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 b=>JLp%DcYOml3fFnn1?mk!ZA)lQr^xOWD+s delta 1494 zcmeA*zOFJMp#JJK-#is_p4RVHt=AaWbO?Rj{*9AK{~3cD8{Y#?gO5tr&%1|(mLJVj zf4fHLi<4_;XH8XA&8znxm;bP}`?5keb!PF={Ea6~tG2#yeDm~#>AqXbpMOvd>uh#i zx@2pYmqd+ag1}%(Kq|epMT;pztfU!@J~19z~1K5Y<>m%cgg%;y(aU| z-!pd}Up{x|va+p;oK464Nm2VfxX<5@xnIm3c<6)PNtxG%?I~uq1>cOX_9&cCnRTsx z#uvGM%d?T2+R~dQE}44iO@=Xd@oM3flNk+rB;|{=YPa1}dvy1fLUrz3-Tbp3lekf*j*{kqG&pm^%#+SJq zcE1A`8vjp!x=3m9K9^swG(@9%uWH?NSh!0xrT&|Sqk7Mt-#4Gt2Kg)gUjDTFeY5U9 zTcziRjG`DtcgXejM#^3_v8?Vsv#qGpYxb^{sWsRBnfuJ5Tl1zA~j>>ZT0Gf9C}{z)?K_U((jKQb5(9&`a4s`I$kJiV%;a*;w)p+ zm2U*M$~Y*rXQ;D(>O52W>x0athhGgYygpYR@_|l9rz8I(aZsq97zgPXqpYw5^ z@k41JzLmRg{(QN+`&NznuG_!8)9(m9U3)v?>)h%#YgMQFO>9dej?YZElm7GbhJK&+ zy9w`)C7F3%IwY%{lDcH&jVwO9eKB|E?$15_Z&Hqc-b7`=clPzq+y3j_y6$*G{oqA` zL-+mtYxd%Bf8Y*#Wlnw?$l&BX^lzEFPbn}lZ9t;w3svx!em3k$rHqk zr3{UrdNf?Dj0_CT4J?dIjEqbyjLatA6;ri0Gz3ZqDd;;Fr6!hS=I6O2mZU0x^#BEZ z^HY%d2(v4SQq#B$6by|gJBmx|m>3xtD;R))LY@K_m|s=0-!sfDpoQlg20aiU4G pQIfH_S!znMr5zVxB?_^i=r1lwEGhv9qluBZ1(&L-E3>~F7XX+>Xczzh diff --git a/BoostRemote/Assets.xcassets/connecting1.imageset/connecting1.pdf b/BoostRemote/Assets.xcassets/connecting1.imageset/connecting1.pdf index 73cd96fc1dda768142899dab3fa46fdf96353022..2843d7436e15fca5e7d6950bfc0499c59fdbc7bb 100644 GIT binary patch delta 3328 zcmb_edpMM7A8tu938|=YdZmd5&HK)I$XKUpsK}uvry7i6nPJd4Hc<}oiOf11N=j`h zg-AJNwJgKRA(oa(yE)`s4w0R)bXZ;2cU|B0y??y#^WM+zxu4(jJoj}!zqhIh*mw(0 zVtf_sF(_j^G80V-I$4m8^=yh}o1gyv&?eif?-#0gt!I+A$<~@hJm*ndGr%j9lc1`M z+U30F)&_+}|GDdK3C=eYhi|oanQkx`EA9JpmM9_BVRVKI)5#qs>=u57;rr=~6TT+_ z;zcB!gR&0rqJL&XS@}8nE+TuFEKdQm;4O@RK>*6okm(QDq0s;iz~KQj!2v*7(tVhI zEN8k8Kw6v8^IFWw3P4%2Xbc}O8jH?w4ggR_Rse+kCrJw6%kmSK==AbZCJdn2>U ztFh)yBbc;0u{$Mz>!yt3qO?xnR6s2reImlUEX7I1Vubip8arDp&95r*B`vQl;o8`( z-wo``y*+9q+@7U3cstr$-~=Vt)Ww>fd=S_U_zJVE@L{z8Dn?W$8B?O78Yo6S?Fn zg_x<7_BAK+TCCF7W+v*LyIO^hrAP&0k=Sg<;OZujEvdxF}PAWn`e<~){vYv4clzjA;=AZUAu%|>+Pn2JJnXhuj))PT> ztG`^)na~FkvI$f?(t7aXU6=hy+{)Ro+s7HD zJmEr&bL`pwEj?KBsQFXc?nADrP_10Q|Bv<98V!VJ=@joy#pSv*R#EzYZYAn zA}l>-I*h3!kPKC7BoO49tsQ`(7#SJTeCRF!BxJD!96kko!?++K*ICqn6K-P{ zrC_t=BbQVMd)V0Wdz*HSQJL?~hi3OTKfhX-X2&i30e-KuP0pZz%XMiO+TOVT>ADbP z*vpuk*L+c&cAXhb!Pfi;W>xkTGtQjCGZ<%PaA69p0BXek2eR8 zs1JLL9AQ3C&|;Y(#-EFqA1-V~^lmf`EpUHccz#VpmAOjsph%2j#DVQ==dvqb<0E1t zOCc8QE8r_(A{cnGP&)CcGI**C8MARoX7`z z0|+HK1dD=+u28?)pBj~(_(>L3SZe(&mbu#T(7N-a-o0n;;EKZci}&2_YE~R|HvY(q z9SC0SPw@K5ML9z}LZ#xUTTbaT&nj`Qptm@5;R&@tv469pjtkUMIsM?^Rx@ ztYGQwoQy)u+Z7k^6sfhpVYcmZx=Sq12z(J4K4eN3Q}#|}q|Y=u-nV}$bxn8H9O-I0 z>NHYRI^3YaS~tz#bFlRSHMA})b)QJ}37|eUpxHb$y|7nPCKs;lWK(zPfF(y`FD3e= zt@_3!S+|_CFY;NSBHMv~uAnI!=^vYRf&Vzo@5i@1hde`i{u&2%A+p9$<&bD5a#Fk_ zdeG|fmSK4BuM4kodG)auvfv6d+I{(j4;@-vP1ialcMk1*kJYVwdHh5N`59X-sC4uB zUIC*V>PgSZl_*ndN|igjLNr3NL=>j&_A(#Yx@VTP(7i3;2MgPCy8`7LY*r@@G&Ul9 z4UG7Ya{oN6@u`TXitQcVDPfb2t%4sz<{0 zB^P#;X@?*~5WHk^@-FT+hxlEl$IN<6Rm_f+%s%AD2fg2pmiIx7%eA!S<5Dw+0@`hMjz{fACCIetjX6J*?u2<{-VA-+H7x56z!Q$S;dd( zAc#)XQm?!kb<6H?`a@Djg5x>DeRd-%yknCYGj-SvnsDf;G6t3Z6EEAXlp%3YOj@El zB`}*TELA$WRN@nTGMT6WN zDGVIF?5P^YI%p6gKp;p$V{kYOjyooW;Gq90*HA`+>c>~WVodX;1B+uU0n`De%a{M3 zx&2vmR~QJO(J=7S1K@?EfGefljF~JpaRhKhAdZL?TvuNY#*x4ktHY7-AlE`hfg|8W zSu&Zv0JKyZQy8vHK&S-4sZxvqJ76~nO@wI9Bs%0mb0yKxF0K&Cm5#yCTp=uuNOYl* dVgEe@aQLTkrm=h%6@do{1Q-HgB5J+|_BTpEBy#`& delta 1157 zcmbPa@>X#|K>gB?(|OW{JbPYiSMUjhE{VHxGd|$Q1pWvW4@T>T*UokOo!_l1pDfba zeSke`$~5P5JtYh0mn^)s;=;^Lt&>?_cATiHS*l+3Ip^rYpd_!oe3QD2U6Td#xRW7h>Vf_D6>DECI2o>5wC+rpY_;aHJG;amPHTyJ6XSBR-mNeB%c+HrtwlDK z&6B&}dT71qDX0DO_pWt%KP72#{FlcCsa7(7Jr+G?EVkXW{>FhQnJzw6pY%s=YYYq1 zXRl!P_F5IqCv)VMDRF}0`U47N%`Kn1?Gd8@KxZ10M&-ugI|uZlgpWDb8{f8?^Mb?kohYl&PY$c3GP2bjJIQ&Hk3^-zU9}t?=yE3sY8n?Y1e_*kDJHG6j#+1I>g0d? z^ufoeadUJ7XRw^&6Q6w7FeY8pJU&s*TvjJ@vt!_P<&-T~v#w5Fd*_H{bGUd>u|+-S zlOoANW;Lb__gU0$9GmVk>9Fm$Id?fHOU1jZyqH<`I_kIQWz`Gp1|S`VGNW1PC z?CgMuD>W}AKPijL0w@HcZEO_ueNyw%OEMHJCm#@W+^oay!lh{ml{GRmG=k{>83NJ~ zt)TDe?Cg|SoSLFwF}Xx6fze>{RWUUlgxQ9MlSRdir3{UrIy79Yj0_CT4J?dIjEqby zjLaq{iL0s`8Um$*6!e{oQWHxu^YdI1OHviUdVqqy`6*ET6| zs*t7t6*IOl0U8AY3VARw12c1=dr`%V%?wQ^^Gc}Jo0$TAk1A(iZVvP_s+h5Ws}S&CvB4o11{e>X994Y;K8UaY<2PW=?7mI97r)tAOEQte_v1pI@S2 z2($teTAq1n`3lgG^K?;&RRyM g(ZixfAr_Q2ic1oUN-By{)3}U*8o5+eUH#p-0Axp?!2kdN diff --git a/BoostRemote/Assets.xcassets/connecting2.imageset/connecting2.pdf b/BoostRemote/Assets.xcassets/connecting2.imageset/connecting2.pdf index 2836de92d1d16248f847166b6759cdd06df5b23f..653ca3b3163bc3515a9b4870591cd752cdc9e182 100644 GIT binary patch delta 3284 zcmb_edpMM78!xgl2|1-1hc}sG9Oiw;91I$p<052G4mr#)BgzbeoEzj6pRzmaoI_}} z*{pSloTV%YMM?)bMVo|Z*D2WUPH9lebG3g=}oln0pjB*ot@VH@gb3?#hio+ zx-|k-j*a|OrX{mmuoiUbSbS2EadxGrWx^(E#v8`uJaIkG3Fm|JLs~>mCSM*J(gZ+& z43J0w+TM!lO>++bbaer=u@44-K;9CJ8$$qLgTjGs*wcJ_Jsa~!%M>CVeUSEEofLM{*cO#^QYE?VZRix`qK=DS zyvKIC4KxvE8jA{Uy!{WV^5da-Jo_557S8)M&4@NzX> z_W*1A{MIT2=Tw=5y6wX!F^?@n&tx4p{iDfqP>Q{8;UuCv<(5EpHcimb3EQWmbbYy{ zwSwKZ9M4vD6^PLexjH8Pyfb{f6SMVBI-M^8pYc`%xstS{8a=DWSF=jBRsK1WuW^gR zxiln<#_-slm+9ynrVZjs!na`7aT1o3O#+DdrPtLoizZ zlU^_oS1>r-KLtbNDFOID=_QqH>U|3otA8yOD01st$23~rYV>fc?$=6MZlZ@Lz#*&D zY8i39mVEE3&}(x$f3CS?*`7hk1m(m^e(?FJu!pbqcWSwTp+lJscE->ITS869Y|HgF z?GKjz9k3i4m~Ihz^?i1}4Dt1!KOWW>oE_gP+-Qk^UO~-a8JL4ao=uplnK!5# zS&VTLCb>IGTzr#x$qvemCB}Hg7s7MYDv@`vZC6{1`d;Z$MGa_`^SR-(0yb+$>yvaanx8~L1UN$cXw<*y1;T9> z41}+6<&T9Of$$q^7(9gelxsZ+Phm~~+SI^6pW;vR0M@gR0q4)8e~}@i#c}07#E!Ld zNpGd>ddc84PLIya^h5;gqJ_=mp)X%;dtDgQtCe3yCVV> zJ(^U~XnLr=L4A94Z)nRy!4>k4M~())R#YZc1|L#>XH@-GhvTu|!8@DQ6F$E>w8VUw zx2GVgO246WMXCVViudohGWYDh`yF<(_R_1p@FHut+LfaRzw7E2KclZ&y4vKVmtqAT zJ1~7}<{0w^LXBmPoEsEuJX-kxIV@oqRpC8YdG4#Y7AuA7*L+E`aTZG3-xoBGJF{c5*dTcB`N6Itz+K<+jd>mBEa!zPhG+gy_gHPvYuDxIzTjhXNb z8LN}S<-Uq^=oC80N-;B%x7u=nzlrT~O-`EFT>LJx|Dr^FyXPBQ-psNm$R^IbQy0>6Kg<9tn@R`!*1P$lZNzJfJ>F6y1& zK;mngOES~&;X7+%#W|hH=kwqQ3g!ClwUq(2r#(MB7FL;3`2(xdJnH5-KzbA;9abxK zE}Q|FJ?-gCXqOx0^KMFj`=H#|s{)B|htl}QQnd^CHr>uW^8ywPb8SNh8+ywsCQ^v-SQqxq5HmX!~SpN2|1+igpo?CwSe z95U#tFP=E(qL6OMUdrF?lbRFuVe;PPKBRld19zj{izS&(d$cvDe;H9|WwYaswa&!q z39o51s7Ih8kU8n3bPbN8bBczUtNDAwDJWz~-|?1?C5 zxj#%H%AVnZYMf3>w0rbjr+>Y!WOg^8ZRk7ch#$QB)pYJ1Sg%C?>hQAZ^7wWm*_D2>~GN@6!P=J z?KV$4=+n4^Kmzge_~H4LO*3lUOmTLJ9N$XhFhusl(MM@4e=jBjKtmc>o{!mhLNOpG zUqlnmeE>fuQ8v`ZfDi!!K_W&IhttGy-iRReFzYsrYmd0zCxDy9kP<)x*7tCqM+>IM z-@pIL9n7N9VIY9PaI8fUYIqRjX5sw+1^`X^LxTNx a3gG#fIw1RM;BG~%~1hW!csSQuUa delta 1171 zcmbPW@=|d^K>gB?(^<-nJbS)}zmV~8588kJU(*9;yM!APSgjxYm~h|U)A;d5^V5%1 zZ!E|w?f24}`pe~f$)X^Q%M&NfY?jR3@L^Z&V)3f-{DVv9C>3irZ+YOCXSn)GU+k5* zSuILSgxsfwaAs$2ynct>ci-v2Ai<3ZOinxH=s!KXLq0 zWu=2yPyE>_Q|#(0qh{K5CNI7JWs5cU+i!KPnfsk%`yW{wZjf?!Z?`^d?-2asGQS7{jE{CVI1sdIZ zV3uv$UTyd+HmY`E>fBqt#5eB??b&;OG{4t;ubcgj>w3%1m+%&)kGo6V{wb2CaYo0?io)?l2kZmwXU5Tsyd2Si+{ zc`5lxSzH!CArNh2qoD7TnwMUZp^Ar?_89cSdy8a=aN{GssPpl6!gtcLFOaOt|&@P<1$b%H0CmZ0|hfvQ)5$w zGzF-bv4t_vu^^z32NN?eGdD&NV+Tqbn*p85EumU(W@>^W3DRqBZi+5uY-(hHz{05FcE*8l(j diff --git a/BoostRemote/Assets.xcassets/connecting3.imageset/connecting3.pdf b/BoostRemote/Assets.xcassets/connecting3.imageset/connecting3.pdf index 8413dde694b0622bd9c5f59f9ea2386eb1f0cc57..d8e244defd2a591a5dac348464e63b56292ff3f7 100644 GIT binary patch delta 3268 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 JT80PVe*sNE5_JFo delta 1151 zcmbPa@?3F3K>gg1(|NZYc=o&x{}7{aTlM?O&HER8P?T3N@nGED@Y=a4)bPrg|$WEvjocYL!*aNgba3~x2vGF`L!St33&s;*x6SpUG; zYJL0xrH9wMQYOdWpBpxj-*e+h{-0GlR>}1J^P2RSv3l={`BM^f{g`=l&!k^evr4+O z?#>G4(_X8p`K6BBayLuXR}W&kE418BE4}Hb#5AuNg)ahEOJ1>hI3ame<&;igw`0FQ zO`TqW41I zyY2kR_3ck=y5@zZ-(9=TiKWG3&83iXCJ z_jkJr+aF;%#~ZSvAmsU{GtHu36%>N<&e`fMIiaJN=~wP8d8YN)EC+$ZCpXVD-u>md zT#O;x>~}}bamapoBD*U;p-rpJ@7oQ>b^DLydCDGg-?Qu4o5VMV=4&|Ze4fN!$Dbtr zProdpq+7Pv|KwJdej(8%0&nuC3P$UHpKS77FW+1tc)rq8H=`5&I$dXHu4r+n*1i3G z`op^u5B+*u{bVsu>4WP}l{+i`uyH;$mzm7RD8+1QYBpJ$alX2_f`LMif}I@@ai!*^ zc3Fj+Q$ zi&Ik+EGCzTB`_LHzAC21gD~6BaI&blv6P_^RELI(m63s=xq*d|iII_sg^}6hBym-B zLqni+kb=H*QEFmIW`3SaVo9n3SPxLpH$Mf+pS(_7%+t`A%K#1(%uG#7&;AoE<=?wFgG_w7c(|BH$fLOurR?i*VGh4 zow1pv0lHpea}%&wJ&L2uEs-oPDN4-DNi71$N^oWsFg%PE^n>#AOB4)&T0x=ZnU|KY z01Y`$7lmjA8%s+=V8|LJrCL~|nj4v?q$HY{CK?;1S(+v%nx`6>+Hs*N(ZixfAr_Q2 Zic1oUN-By{)3}U*hH|N@y863u0RZgLo5}zH diff --git a/BoostRemote/Assets.xcassets/connecting4.imageset/connecting4.pdf b/BoostRemote/Assets.xcassets/connecting4.imageset/connecting4.pdf index e8288dd227e141164299c5e4c889b4bb8e8d2402..7a99255fa95020bcaf714c75a3b2153d2d9c7a66 100644 GIT binary patch delta 3353 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 delta 1160 zcmbPa@ge)-hI-BJTBj@Sg$j>34VRQ)!*Pl5??}!0plBnb2>$TZ8rUNPGI+Y zz^c1ysZw{S)v47oOGQ@}O-M@2SL9cU?3e$fW^Z%*$BHbU%q^}(k7wUXI(tif^^A0B zDJ^TM>Fbtq|1Ujq^L0$h^VL#YO+u|t#&xay@^E^Fe`J+R)aNJl30C;7u=dazanXv4PTy1k~y7!iPcf;$YH%?ERXk#tn_C!}=rX8R194j6B9ocv9b1UyT zeUG)3OgI=krL~%%{%aaRF7!s1RKt3ZXWrc zOCEf5zBhO6q7&y995kvFEZw+b`iq~tA224ynwFe)anrm|koc%)Y3fm>brF4>(=OF7 zNR0ZYH?8xB;*Y8-f3dmmLz6r9D|Xu7ZCEbxcJ0y_kD1#q zZRp9_Jvl>QiT}et|7KOL_jvf_o9(5*R@phb?IzuLY`*)Tx&LHdMk!`fGtFn&3Se%-oU@^HwEP>Hr@>MZ49)#J3hLc6bjin5YpgJ^Mtc(l{%?&J! zOpJ_7ER4)1CyA@78yW(ogB0|gi&7IyGV}9X5=&AQzFjmkH z%Fi!RFa%l)3N6pPw0s3<$a%UbL@U^&7^aw*85x-+B^jESq$MUAB_}5v873QAS{NCc oC#M+MaiJ;E!=gqZ7L+!MOA?DpDvDCmxQs0gExA-xUH#p-0B)hIg8%>k diff --git a/BoostRemote/Assets.xcassets/disconnected.imageset/disconnected.pdf b/BoostRemote/Assets.xcassets/disconnected.imageset/disconnected.pdf index 6f6d8439754471f5ebfff6f2b70ee03b3fb9123b..0169c328d8dacca2542965a358013004375ede29 100644 GIT binary patch delta 3339 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 delta 1149 zcmeA(d8IfZpnmBT-#lqUp4RVHtk)SAbxc_?f2)5$#YAQaPN4*u10NS%f3KW=OwOdN zYny>Up9HV`&o7yNUz+_?dZlDLt7V+Ik_`o?uUMPDP)b_-<-ndrD&2?E^lDonn$t#G>s6y~ihp?^v1@`)osVWmwe$^~Y|HaW- z7t}TN-pkDLv|DdAf9CIZKL4h_e+7qSZ>RKPr8bAfwUKfwf4X=cRy7Zt$1Z$(`eff} zYc5{g6%}~q#_lCe--Pa^i(YJ!6OQwlRV~RVY7qMR%Zx==)`eO-UVh%>oUydTH;pGN z{<`qn#O;#zI_?(mb-a_9RX<;6FU#qDcekZxpM2P}?M=BI%bDb2f$pE*t>krNOcg)h z^m^3KdEm2Z#kcZ>2EXgwPn_d$a!Potw4|4-WD~2!o)ekes~OH+-_+&Hx_s&^D<Yn{6)dW5H`?3~e0*U7{|xJ0Gmo`M z=Uo(>yZBL%eoxGu=yxw{-MscYF8(T<=dkImI{$)~)oW&ps-(!O{C|IoXHQh$C;zh| zIWE4A4!-K*4{gY7dygzV5}sKc zyC!YkR)KWg%Uk|PeZIe&PxnR6k~+p?(q=uA`5C2{O-(H)>oCq&H&-xF2vV@K10t@} zyp;T;EG`S65Qw(1QPB5E%}X!IP_Uf5N6>Mz2D=NFrX^I?$js0PrUPUMNJq4SzNfRZ zQ(|#yih{-D0gzEXmBzb4e^oRRHS&3i{@!AoCGsR}`hDaTzEW8gm)Ifr6Q-sj;a- zngUeJ*uog-JrGdHgNYfKnVX=9u>+-zf!>?UDWO^qGyp{sq}SZs3|-9F)EpQJAb@1B zg$b&`Kv`o`Qw(*+W|qe2dX3FZz+(K!1{#}NPA-s?sW&uM&=1PbFHtZwfCQ9hURu5a zG|)U<6rvSuQcY4UO%hYm3{6c_Q!R{=jSW)MQp`+El9J7g%neM9?YIalQHTYlisF*Q Uq7rb}8e0OxR#nxN+24%|08YS`pa1{> diff --git a/BoostRemote/Assets.xcassets/left.imageset/left.pdf b/BoostRemote/Assets.xcassets/left.imageset/left.pdf index 11e9cb10156a91c5c8efcfce645ee04601f1d895..a5838b4b14c6d3f6b6b9129653d2a2b2f7b7c4b9 100644 GIT binary patch delta 528 zcmeB`Um!mrpgwe>civ$G9+&S{N7ry4xp;i(qpkh|6%&~y7=;e-PAI$hy1Z>A3p?A9 z{x*@He~w7{OL!d8lSNCLztu&qY z=1ux^*S6gbwlgOe3~WML*A6?nqT*j{9hRV#8%GsV{Rn`Pb=g+i?4JZfs+L+>=KRyK*0Y z_v+O@=jbEB(KY*T)9$^jM|Q3-7OxG=To4_2q1WR6h7Z%{{b%rKh-I0qz$ndRWVzXv z(Tj)6(7?db$k^1>*mUwl-Ue+`0}BNM5Kzcd-~uxY42(@o(8Y|6EQ}`G@TpB!;}fbk zFflR1RA6F`E@ohAh{Yfy40XoFX2$4xjZF-(h?#-xo&1^4+S$O!FvZfy!pzjdBrVy* p+}Oe*F)7i=#L_4=%_7a*+`^8_hLDoUh5W*t7RFqvs;>TSTma`7vp@g< delta 526 zcmZ1=-zz^Mpx!rdH(#>>&z+xLv$dyMsXQ|L%-Ye&?=W=*%hZhae|6{8ICXa3u)JM< zu8+~0siu{;boq|7oR~<@=Wn)t{2=6fZ?%|lN8=Y}t|sl-ez$HZhIg3>7crkVoi|g> zC$7n1-iFeRQWNx_UpTYaCD;2F=HsEf#s7CLlJ8ZLsIDp% zyCZrd^PbP-%J9Zz)22--4lK{y5*5Wqy|Ofb|LTSCP6kt_zPGoQ@NZx?T7Y?zv2nq&ghnPQfb zYMNq@W|o+2U~ZC@W@2KQmSV?cLr{rAtb&~#S8+*VQAtHnY8scZshJ6vs;aBM8y5g~ Cov@(* diff --git a/BoostRemote/Assets.xcassets/offline.imageset/offline.pdf b/BoostRemote/Assets.xcassets/offline.imageset/offline.pdf index d25069d39289a4b2e623c34ecbafae13dffc74b4..6bd9c00ea4797188371d1e8a16bfce53959d0a76 100644 GIT binary patch delta 1886 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 H3psxQ4Sc7f diff --git a/BoostRemote/Assets.xcassets/portA.imageset/Contents.json b/BoostRemote/Assets.xcassets/portA.imageset/Contents.json new file mode 100644 index 0000000..c4d7e45 --- /dev/null +++ b/BoostRemote/Assets.xcassets/portA.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "portA.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BoostRemote/Assets.xcassets/portA.imageset/portA.pdf b/BoostRemote/Assets.xcassets/portA.imageset/portA.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e33a308662d59e4e369a9fd1dbf0eb4bb79eecd4 GIT binary patch literal 4047 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 literal 0 HcmV?d00001 diff --git a/BoostRemote/Assets.xcassets/portB.imageset/Contents.json b/BoostRemote/Assets.xcassets/portB.imageset/Contents.json new file mode 100644 index 0000000..39fc391 --- /dev/null +++ b/BoostRemote/Assets.xcassets/portB.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "portB.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BoostRemote/Assets.xcassets/portB.imageset/portB.pdf b/BoostRemote/Assets.xcassets/portB.imageset/portB.pdf new file mode 100644 index 0000000000000000000000000000000000000000..12d87029bcff9fb8bfbec1eb636c9a1c517e6f24 GIT binary patch literal 6015 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 Ck1Lk| literal 0 HcmV?d00001 diff --git a/BoostRemote/Assets.xcassets/portC.imageset/Contents.json b/BoostRemote/Assets.xcassets/portC.imageset/Contents.json new file mode 100644 index 0000000..0cfafc9 --- /dev/null +++ b/BoostRemote/Assets.xcassets/portC.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "portC.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BoostRemote/Assets.xcassets/portC.imageset/portC.pdf b/BoostRemote/Assets.xcassets/portC.imageset/portC.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ae69becc3559ce277f90b70c2ed82b38dcf41f27 GIT binary patch literal 3988 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 literal 0 HcmV?d00001 diff --git a/BoostRemote/Assets.xcassets/portD.imageset/Contents.json b/BoostRemote/Assets.xcassets/portD.imageset/Contents.json new file mode 100644 index 0000000..d4ed93d --- /dev/null +++ b/BoostRemote/Assets.xcassets/portD.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "portD.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BoostRemote/Assets.xcassets/portD.imageset/portD.pdf b/BoostRemote/Assets.xcassets/portD.imageset/portD.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2d0073090c5b12ba3fe3fa67005a5c2cfded4004 GIT binary patch literal 4042 zcmai%c{r4P7soAA7_yWlq9%_eC1$f##xjX2xJ_Q)9A~ELpN8>!6S&LYATk zL-xdLk}VYyL$al08}iPm-lyK@y{`AZ?rZMf{k_lcoZp;t{`eeOV?BeT5G5E;wuSzM zK2z}Z?#q@oARGh+5wWho6DL5*MtDzWvI|IsDVc(l4G8XJJc;>q$B^-QcpT9Y4?-Y- zUStv;;{o(#4>Lh|HiP-Q#c&-H2x);c&5C z5dwD>gTmsfoBbL|?_Y9>ojv=#Mrg#GqKZyAf~pBQxQdAFK<_U#w<0*DxveGp`{?W& zioZs=dH79ap>2YlzV5D-f;dx>=^Jr18^q^aY8bL*K}78P4d15aj;rHdc2bjJnN*MzFw_Km|yNCxV8)KZe ze@S>xG6?n~@1}S!;$;#J?*&r*As~sKWaf7-5UWMGYi1}t1CT998A)^}lFTk*aCi`_P^8Pao>P z`S{rt8rxRNXPL)T)?syqC$lX;%6fQj0uFC#sQdpLCL_h?oY|0Q1dXajeYsm2B)cTx z&jWgO{G>mk@do-cyNZH*>+`t;!# zH=czOm9Hb|o9&jPLsM0QL(U5UgEef%8zF!uvITn(JljHeex}i8_nyv{6^^}v?EDt& z&&Hgb0EVl29DN&9&9t=pC)+BP=aqsSYu_q17|VGLYz4+kt084}vH|t`RZm=#6Qgq^ znN_rkL$?4gmXZ~q;Si{3Hc!q2>G75__vM1gBefl=6uF6P3CnKrI(TMGt?@{@>{xCL zAloKY_PulNRW3aB94eiSzH+FyclC}D8(28azH3S@+dUGhFDyPE`GtdxJE=vZj>I3m zrs0yw=9}+45e0}uVe^FsQwj8s&z;s6E6mogkRwUWXU1;$8qt<2`EG*6g35>~`s}in z9%(M|b0v~E^7@#qx-L!ZE8OEXP7U_&C)V;Vlpj9-De*tQ$^X9Wvp&XRn#Y& zvsHTR)TWO;KrevUzU*MD9J%v#f4I9{Ldyp}dEV&RS$8k?EH|YiAJrIHA;cFA;TkJx zo%4+I$MeOsg8xE^!0`I?{DS<`dR<+7{1lqw=8E9f_%jW{zdD)~?_@m_TMYYXZt^jS zCp6NfHta;O#VsXAU}#|fSm0h&c`os58E(QZm+jdC!ZeJlQC!c7nrz6wIAuJw{5b+< ztOX&!=k;|iCGllmaZvy7Q|kwKZK6EKjC7>UCYSl*97(b{isHGWq3(?wyKixk?*ie$ zN?;B}hh36Eu#21{Ahyt;lY*QnoJuD-2-<*0I*8Y7Kpn_ycJJ%17uouP{a*skhNxcL zX#=?MY}Z9zz92(wV0hzcF#AX_fji{0ph%8R(Jj$Dfi&F#!F^WTen=f-bz#m{WaKTu z1nsq#a`*QhzFw4#G}c`Di!4#YZF_zFF4s#CeCH;6K&VhEM=xgAYqlprL*>UMxec2- z-|P8`+~E>?_IB)4wJ3tWs!42Y-)A<(F#D!NZtdsXoIM5>-1`>wbZ=S6unQe@iW z%+Zjv*HYUKT`H3WvX>P|&@xUsBqxkMC8@7FbXMckQ*A$OKjb~rUH3ivEQ(TVGOW;4 zy?|2z%7%$B%2&#GM@eFFyj$`N<%%piX^`SWu~*8Hw?7zo>U;i1HHS%~cB5HvZu$9a zgR#mc%`lXHdQLL-1~wfViM{?orPV~XE+IIfYB#!2d%FCU?7f2$y1n=OUR76~sXX=u z{{}2&sFug*O`L9BI`EOY#DkZ`ThkBGCFv6MiWjCko4^jMFjMh+F^Ms?F>znvlTT^m zw705d1iP&|h2*uvo`dPB3+_hLR`XJf&y<-5l{C_??|VoPr=(OU95N? z1FYy)Q;+Sy$!YUl=bU6KqBXKhO6LlW_8{_xi#1Dd_bV)%bI(?E@3Bo#vR2cnvZ*rj z(M6wDwotY&Gg-(+m}He?KSO>m%_7e2QAzJ5l;_CGCU*??S5bU%&*5CF z+~aNPxF?sQ77^pta^;a3s037O#~HKNeIw@_YG{=-KDS91Ie4*3ZF^4nJ4?$41_O6B znom5xn(KFa?Fg@Cv_*7==&-20;+&${(HX@9mI{_TEIcYdm9ICyX-Rjp#Ras7yN=^3 zy7Px8AD0v!9rbRQ3pk!`TRtpWd$yLg%)cznkYhl&G$VW?sQfFh$=-)*Lj(GSWlwF9wP*#<&f?aT3C_o%T zL?U7ld+NRGivyHbF`FEl-s{6(2R~1(4>HgIb-)9jkH9>D0pL6rf)~oOd&gx!b0d3W zZO8%TSN1YCeWDz?8%Xc46Fe$>wj%3ZdzBR759DV3s?B|``T78kV)gZqEwv}(p1*o- z7#%BmTGYp&!?0Dq-|&q76@7~SX^MrSWyOR+j8zOMUsLqJK9MUj-lW2nSHq_x#%DhO z$LEz`HYpXeZ%B{ng`Kq0TlS5Xmk#gWcR*@Xa4T|8Qz6}`bjkjy4;?U=SR27em})yR z6}xD=ir%G5+Z#1gRyYZKV4V2oveR|f%wy|dH zTm4L&2gu{((C1Er&RG1uQO~H6K9jp9<@F9O6$_JXx=(dY#;8ZTt@+(s-9_BzhMg)( zT;Ecp?RvgpJ3mByK+C>Mm>IPUxUe?dwH!J}y|;Xi;q%^`+vnZzbj??bG_0lF(96>I zwk7ngFF9YTYA?*zpT}5Vau6WIImT5&??0lRDswgLFZh)ADOe&deUkd=O4VG(oA$SZ z4Wk}`z3j1^tz3xx!jg4?&sU7yN_0G0G4IA6G}C5sKGifh2igbf&7E9~rx}JB-fM4) zyWD@gZ&2;NT9Rs0Y(m?^@k{N*&G+AsSN0T78^dy+t^(8#YAk+eUp=sp$#-JNFDjsD zT7ENY`N>PGD68y&cLR}6@>B^|jINAM2lZx1bxR%9y1jLEDP}n>z2b%QXYbA4W^{>ql! zJI(2Uk}eK@m7t7Nl(b~-2Gtqc(el}? zXC_VS)X4pMjrDYx-<>1Y125zZ6etH(YicZdo)$+N@v+>1O z&ckVPbS3mF*j3JTzK}T4-_FCNe#gr==Ipi|lQ}UUnIjvSK=jmOA^WyZ))+x_{Qdp!llqeIPC({h z0Rw{nbAeP@K|xNSpBnQF%nYzDkmoNA3{z*$9)D^u7?e4+{HcM#Q0CwIFAb*3EaQJ^ zaCK%G|I}bmb!H3vsex5g{uvjl`VTu89LyZb{@e?LtNc?_0sj`4Ou`V{@uckm*^J=N z%pY?AG9?n3{lV%1W+G9ZPDEz2{8;NT+vNlfgLA^+;Ep(mIu?pohpFN<)G$~u^IZ+B it`1j20RO)Ub68`R#EZ;qjqQTKRG}(BSy_Fw0r20K#NC(x literal 0 HcmV?d00001 diff --git a/BoostRemote/Assets.xcassets/right.imageset/right.pdf b/BoostRemote/Assets.xcassets/right.imageset/right.pdf index f927cdc20685a8cd99ab33fea20e1c5ae8cbee28..6d845eaa9cb336a9a5e5fe93827ade253980f38d 100644 GIT binary patch delta 595 zcmZ1~zgd1lK)q{_W7ZJ^o;}Y+t;8pt3JU8xUwLqnv%CP8?i;afwqJf*C#%QtNZ!2U zVXVZz^OSRv*wo!UtOd$D7(YgR^tOBAuIIh_V_30+&paFLBIXRUqe5Xlx=v+HuCH%w z3~`&ZG1xGrr0a{Vsc)Qms;-?U&%lVGN-D+n z%IcJQU3SB*>GH3FW-Q`-^m4uNOY7}-Ss3?9mn^Qh;@5I}mw1HB%b#zz+9t4V+Blil z{=iqx)cmw;uGGAg;*z3N(ZpO3Ge0Sd%T&QY0Yn>_SZoeu^y1+%G%&C4rPF=Jx`!^t6hYV{^2=u!qIWt?0*OQe!<3XH(=-c;|}1rS>VL9(p5|5huyrKg3ir7={f1g zS*?>A5}eJ2!dTyT?(wZSF6!@c(sX%DaKekZJ=Z2@cx?V_aLO_&S8#*Ij^cL_7rm2M zN_t<(?h@XiXLZE-@Wn2zgHyBSh4`r!pKn{kKWFk3u?#M)%O3S%`x?ynzAQA`GWGE5 zX+5kp3bjX=kH5?{JiF4xz~5)t=9ei`mC|ln_)YGzT*=g|tHs*`-USzM+H1`6yThLN$!=43`M9xek5BNHPdV?$%}$=i7wwG53F3_w63Pk{@} zFfcGSu|yX$HnK3EoW!SAZ)|`rWnf}zh%RPqWNL&iW?*WF#aLqub;ibK7U+77O$;Go z{7CLJHZeDxEXHpaZ=Ph4W@%=Sm}YEdoMvWjo|s~4VVP)YWS(MaWM-OVYR6?mP>DjU df}I^#aYn7XWmqyng@y diff --git a/BoostRemote/Assets.xcassets/thumb.imageset/thumb.pdf b/BoostRemote/Assets.xcassets/thumb.imageset/thumb.pdf index 1fec97f136ae3e7eb946fb771101475338695b61..1aefa8a9ab08c3839698d86bee93a64e0f6ca78d 100644 GIT binary patch delta 576 zcmX>mH(!22Kz;87N3KH#0dFlvsH~EFHJi+Y1@nc8NOe9bFBUq6s4+m&Qe_@u{zi*u4~DxY3Ckz z%&P5i(LFb#E=~1_PGWP_N59WJ@_z1{EB|j~*{@R=uUpBOQkd`0m714QTvC*pmuK3!mScBlRcO@0GT-5sr0{xvp9=eMpybf(3IAs=KHqba&G2#O>Agz>W*u(|E7%wHRXxkK=->}lj?2d8 zT&Z~}#U(|liMb$Feo_{fse*w5h&D8~-0aWj#lvM_VPs-tWNc_`K6x>3gSLsGg@OSH zDC8+{ff)t{My4j{V#bD+Mw9*cRO^k5fhMAVJjKY&Fg4L6F)`VW j%Z8v5g;)hUJFeoA#G;alqSQ1lV-rhbE>%@me>W}w_>h!4 From ee94da4e65c2ed44303482fd9917222c281c27bb Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 01:01:55 +0100 Subject: [PATCH 05/12] Don't use tint color --- BoostRemote/Base.lproj/Main.storyboard | 1 - BoostRemote/ControllerViewController.swift | 5 ++--- BoostRemote/StickView.swift | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/BoostRemote/Base.lproj/Main.storyboard b/BoostRemote/Base.lproj/Main.storyboard index b2c7e44..0739c11 100644 --- a/BoostRemote/Base.lproj/Main.storyboard +++ b/BoostRemote/Base.lproj/Main.storyboard @@ -129,5 +129,4 @@ - diff --git a/BoostRemote/ControllerViewController.swift b/BoostRemote/ControllerViewController.swift index 62f5f75..70c4781 100644 --- a/BoostRemote/ControllerViewController.swift +++ b/BoostRemote/ControllerViewController.swift @@ -71,8 +71,7 @@ class ControllerViewController: UIViewController { 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 { @@ -92,7 +91,7 @@ class ControllerViewController: UIViewController { case .offline, .unsupported: imageName = "offline" } - self?.connectButtonImageView.image = UIImage(named: imageName)?.withRenderingMode(.alwaysTemplate) + self?.connectButtonImageView.image = UIImage(named: imageName) } } diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift index 2d43d27..7b71e38 100644 --- a/BoostRemote/StickView.swift +++ b/BoostRemote/StickView.swift @@ -61,9 +61,9 @@ class StickView: UIView { } private func setupSlider() { - 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.setThumbImage(UIImage(named: "thumb"), for: .normal) + slider.setMinimumTrackImage(UIImage(named: "left"), for: .normal) + slider.setMaximumTrackImage(UIImage(named: "right"), for: .normal) slider.maximumValue = 10 slider.minimumValue = -10 From b4f58748147ee4ec43d9a37734dd760978d564d9 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 01:38:37 +0100 Subject: [PATCH 06/12] Use images for Port label --- BoostRemote/Base.lproj/Main.storyboard | 21 ++++++------------- BoostRemote/ControllerViewController.swift | 4 +++- BoostRemote/StickView.swift | 24 ++++++++-------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/BoostRemote/Base.lproj/Main.storyboard b/BoostRemote/Base.lproj/Main.storyboard index 0739c11..bcaa9cc 100644 --- a/BoostRemote/Base.lproj/Main.storyboard +++ b/BoostRemote/Base.lproj/Main.storyboard @@ -37,25 +37,16 @@ - + - - - - + - - - - + - - - @@ -63,7 +54,7 @@ - + @@ -73,9 +64,9 @@ - + - + diff --git a/BoostRemote/ControllerViewController.swift b/BoostRemote/ControllerViewController.swift index 70c4781..c3797b3 100644 --- a/BoostRemote/ControllerViewController.swift +++ b/BoostRemote/ControllerViewController.swift @@ -28,7 +28,7 @@ class ControllerViewController: UIViewController { didSet { let alpha: CGFloat if let motor = centerMotor { - centerStick.text = motor.port.description + centerStick.port = motor.port alpha = 1.0 } else { alpha = 0.0 @@ -43,6 +43,8 @@ class ControllerViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + leftStick.port = .A + rightStick.port = .B centerStick.alpha = 0.0 setupConnectButtonImageView() diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift index 7b71e38..8b987c8 100644 --- a/BoostRemote/StickView.swift +++ b/BoostRemote/StickView.swift @@ -12,15 +12,15 @@ import UIKit class StickView: UIView { private let verticalSlider = VerticalSlider() - private let label = UILabel() + private let imageView = UIImageView() var slider: UISlider { return verticalSlider.slider } - @IBInspectable var text: String? { + var port: Port? { didSet { - label.text = text + imageView.image = port.flatMap { UIImage(named: "port\($0)") } } } @@ -38,13 +38,12 @@ class StickView: UIView { private func initialize() { setupSlider() - setupLabel() verticalSlider.translatesAutoresizingMaskIntoConstraints = false - label.translatesAutoresizingMaskIntoConstraints = false + imageView.translatesAutoresizingMaskIntoConstraints = false addSubview(verticalSlider) - addSubview(label) + addSubview(imageView) NSLayoutConstraint.activate([ verticalSlider.topAnchor.constraint(equalTo: topAnchor), @@ -53,10 +52,10 @@ class StickView: UIView { ]) NSLayoutConstraint.activate([ - label.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 8), - label.bottomAnchor.constraint(equalTo: bottomAnchor), - label.centerXAnchor.constraint(equalTo: centerXAnchor), - label.heightAnchor.constraint(equalToConstant: 30), + imageView.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 8), + imageView.bottomAnchor.constraint(equalTo: bottomAnchor), + imageView.centerXAnchor.constraint(equalTo: centerXAnchor), + imageView.heightAnchor.constraint(equalToConstant: 24), ]) } @@ -69,9 +68,4 @@ class StickView: UIView { slider.minimumValue = -10 slider.value = 0 } - - private func setupLabel() { - label.font = UIFont.systemFont(ofSize: 24) - label.textColor = .black - } } From 254a0f2160b13640231a6954a850444a6bb9f6fb Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 01:46:27 +0100 Subject: [PATCH 07/12] Update thumb image --- .../Assets.xcassets/thumb.imageset/thumb.pdf | Bin 3999 -> 3925 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/BoostRemote/Assets.xcassets/thumb.imageset/thumb.pdf b/BoostRemote/Assets.xcassets/thumb.imageset/thumb.pdf index 1aefa8a9ab08c3839698d86bee93a64e0f6ca78d..eda0929057bdab235cb52a03ee9ef475587953fd 100644 GIT binary patch delta 500 zcmbO)e^qWmK)r9@L9W9J0xs|Cj?UrsExl@L`JKDy6uXBv_qGYo{x94tH|fBp&71Aq z!_P!4ywJk`DdSezRf8h}-W%3lJt?%d*8NW31sPX1*-$mhfc(UJ5oL?^zMrw&R#G)x zJm$62J$X;->+_RWS0wIy;N21N|Ka<_qhigEdT-ZqugfcWbb3aT*#=D?ujI)`bb=3s z6`l=KjWm4N`IFz^g@qGWYF*Vxz?EGB^LP-A0D!^uqicJaoE#s(&qX%?22CaFfIrm2>R z$*F0kMh2$F2FXb#7HM`|HUyO@#46a?aTS*&7L`;KrKWKin;KYfsj9mAyKw;k4ON;p delta 575 zcmcaAH(!22Kz;87N3KH#0dFlvsH~EFHJi+Y1@nc8NOe9bFBUq6s4+m&Qe_@u{zi*u4~DxY3Ckz z%&P5i(LFb#E=~1_PGWP_N59WJ@_z1{EB|j~*{@R=uUpBOQkd`0m714QTvC*pm=rpBg|BY7LNO%2Qy3_w63Pk{@}FfcGSF-8|N zHnK3B%)+NyZ){|OE@xn30<;9x44^VIbTI={LoDVRVW=}UHZwxkYiwc&785{rsIiHe z>Es=JcJYap$(BGDrX^b#n;9k=nOY`Unwpy$n;RLXm>DOhrrL4Y5LBWNt6*oxRa}x- WR8motn#N^pYGK5ss_N?R#svVp#khq4 From 6f48d4a676d7af48564271023f765b7cd1255f15 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 09:10:47 +0100 Subject: [PATCH 08/12] Update port number images --- .../Assets.xcassets/portA.imageset/portA.pdf | Bin 4047 -> 4046 bytes .../Assets.xcassets/portB.imageset/portB.pdf | Bin 6015 -> 4144 bytes .../Assets.xcassets/portC.imageset/portC.pdf | Bin 3988 -> 3994 bytes .../Assets.xcassets/portD.imageset/portD.pdf | Bin 4042 -> 4042 bytes BoostRemote/StickView.swift | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/BoostRemote/Assets.xcassets/portA.imageset/portA.pdf b/BoostRemote/Assets.xcassets/portA.imageset/portA.pdf index e33a308662d59e4e369a9fd1dbf0eb4bb79eecd4..d8281c60974704095407b498364581303de8059e 100644 GIT binary patch delta 628 zcmX>ve@=cvP`zhfi-EwN-=d{`DUVor=2RZ+IBavk%VeU$r55LX^R=2e+g+yZ+I4$x zn0?`4VY36}5rT6HG$lGeg-`k4_?z4A;g3HJ1`l5ImRrtBvHM_^D_6N#G{%0*Meona zixhQ_==JDsHGgX(|VU6iqTc5_RhNzMWYjC;8?|%1#H}if4suj4J<4pDlL(5j(s6eB|gMJ708zbKK1%Z{JwxN@v9GxVgS?O_GP}t(gy5xs27fvCo_;aU|}jhAWTb z5s?+#Qc-*x)ql;V=2)Wlp6D?cfV z%T&QY0Yn>_n@+B0Ok}j!{E*R`o6%yjF7G@JLjwZ~Aheu(nYT&PM8Nh*@`G6p7=M(AS3MwZ6tVg{yWn5G(;W2iGWF|b6}Yiwc)72`uV z)7aF|XtEK%UA%#TNn%QBl8I%iS*n?dNwTG(sfB?_lA%dTVseUwX`&sM4M8Oeu?lu} aT*W1cMI{wQscBrsW=57=s;aL3Zd?FWUDkvE delta 591 zcmX>ne_nnUJvF8M1!0M1q+Dqe}{F>X&yK+%T#F@u` zZHo^}nwRh;Z9Eit)U{CILaoEcxWdZA<~sd61&sFcJ60_2|6%n0vf2sh_;bq?D+0Zb zooJ6bH~)^rhSU;Hxp~5K&3@=`yX00u2g^YG+Cuw|Fq)Lv*}-x%%A;r z+-Ukz!)$KF+Z7W8x%GHs<=bBzv(1rQ^K^^w=hOT3*d>17SSVVweN)}BdKT6@<&y$D zW<6u~d?xDo*~RySy#Mk8oRv=nrgqpb;tE~C@^aR)wJvs#{PVR4 zykTjOoMvibW|5SZmS&h@W@wUXW@5)>Lr{rAtb&~#S8+*VQAtHnY8scZnXv(vs;aBM G8y5hWjm-i8 diff --git a/BoostRemote/Assets.xcassets/portB.imageset/portB.pdf b/BoostRemote/Assets.xcassets/portB.imageset/portB.pdf index 12d87029bcff9fb8bfbec1eb636c9a1c517e6f24..7b9b8273e1fbb2d4b2ef2d2cd462befd3d557cb2 100644 GIT binary patch delta 910 zcmeybw?Sb-K>gBS$1G+;o;|-st;9ENeHweb`W&|tU*&;IlMXGL@NB~Sa<{nZU=PhD z6W(}iOYt_o=K8HjP(N|PW){_R+I+D*h0;5ujHa!gojRq{yYnI&--6gvp6>HDxjafZ z`cn9x+`^~3JGZ?y{^J|9IYGT8Z<4eicYb5p`&k`LYo2-f71d0v_qU!Yn)0)1va(p! z&d&Ffeowf5*Yw0Y2LHci-wiKtB{w;HKVFcm-!5BmKrEYUk4(5vy2ukx9;LaZr}Rv= zyxS6gy8Y}Y#x>QgVRdJVx##X+kSut{RnGG0-n19JdHote5&KN9gdQ&Q`0B|gu=NC& zoln?;lTjO1G562WU8lLif}uXUQTNW{fF-e0c`wfMbg|Lu4V&pGeDa{F-1LxJHD(T> zNA4%DU7;H6dEP(p#@}@tY}Rf_`|kYk(kFY7ve3jXuW$3hZ!G+2<$HF)H-6DDqgM0w zyH+V~_i`S8?6B!^Q_b7;&rm8n!|X$QWZ%ui1NTz@^V+?>x`Qhlcf0%d~~^qqk=mSpDV zxg?gPDj0&a00n*XQ;_)xlPii+)3^*242>t}i%RPlo0$SNfPg}t0vDKJU|?clfi7lj zVq`XXo2Y8NiJ2w3oPnvO0lJv6u_e%TXy%%kVw!7gj-k%j)W95Fud%5qSgan|p~hy0 zNEVkAC1&QN7IE3wDCh@gRsn;;SV2E1Kfgo)qzV)!o_T5c3eZ6FbWw;_u(3!nPBKeL zGBrv{HZr%cFibQ^vrMxvv@lLHwoFbmOSa=eQ=*4OjY6yfFnEhg5{pW}fop7TWX`3k J>gw;t1puDpHc0>g delta 2644 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 delta 522 zcmbOwKSh2*K)r9ECttGx&z|R^cHvrQuQ8;@HCTLL2_GAc86uQd31)@!O4>k zBsZPpdhmFciSE{$qG#1+rtUext@5_%!f!=oroeqkt5y7Wmdd9`>|&g^y;QjQ@yV^6 zeExQKYNble@cErQ2ptw!v+F-UTZ&#*|55O?TPey#}A6~2~j}>Tr2ti{ynF0%j$yj#*20) zyKl|i`MAg0Cg~ur;;FoL+210UG&Q8T7PWp-4tu)k!BvaY-!VmVl$sp(&ZbZrP_dWdm#_ogF zd&bX)G=2q322BuOcE%yjCwUH=j`7L|Qj%nc1KjLi&;l9Q5CEzAteQccoKjgnK6Ee-6rYzQft IypCT606ICWkN^Mx delta 379 zcmX>le@cErP`zi~VFR8$uSJXX62fPT{(d9QV)um6sY@h)Yl+>H-?En`$u4L=(9~uk z&fCsE=VL=_|Bl0z2a6tDU>EoE`?pK*Ug&f)|7qHuyP6b#*!7HQ^9v8>S zK5Lz~eYqi<`n1_XvKwn8{)lWmGo?u}@#&NZmwl5biRRA8ED4*L{Cu&KH<|_HE&R6x;=WmJLxy_N6@49RWbG*fW#;5HS&68sp>ljTo-(mFTW;B_s!8?z` zz|zRr)YRB?^EuwRjLyl4$!W>SCMn5=7D+~_7RF|&mgb2`20*^KfrW*MxgD1cAtjU7 H@yh@J@!_Rv diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift index 8b987c8..a471e2f 100644 --- a/BoostRemote/StickView.swift +++ b/BoostRemote/StickView.swift @@ -55,7 +55,7 @@ class StickView: UIView { imageView.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 8), imageView.bottomAnchor.constraint(equalTo: bottomAnchor), imageView.centerXAnchor.constraint(equalTo: centerXAnchor), - imageView.heightAnchor.constraint(equalToConstant: 24), + imageView.heightAnchor.constraint(equalToConstant: 28), ]) } From 0b2e7ff31742c9da2d8e8220a9de8ffe219957e4 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 09:26:00 +0100 Subject: [PATCH 09/12] Tweak layout --- BoostRemote/Base.lproj/Main.storyboard | 12 ++++++------ BoostRemote/StickView.swift | 9 +++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/BoostRemote/Base.lproj/Main.storyboard b/BoostRemote/Base.lproj/Main.storyboard index bcaa9cc..16137aa 100644 --- a/BoostRemote/Base.lproj/Main.storyboard +++ b/BoostRemote/Base.lproj/Main.storyboard @@ -37,15 +37,15 @@ - + - + - + @@ -54,7 +54,7 @@ - + @@ -64,9 +64,9 @@ - + - + diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift index a471e2f..ae4f207 100644 --- a/BoostRemote/StickView.swift +++ b/BoostRemote/StickView.swift @@ -38,6 +38,7 @@ class StickView: UIView { private func initialize() { setupSlider() + setupImageView() verticalSlider.translatesAutoresizingMaskIntoConstraints = false imageView.translatesAutoresizingMaskIntoConstraints = false @@ -52,10 +53,10 @@ class StickView: UIView { ]) NSLayoutConstraint.activate([ - imageView.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 8), + imageView.topAnchor.constraint(equalTo: verticalSlider.bottomAnchor, constant: 16), imageView.bottomAnchor.constraint(equalTo: bottomAnchor), imageView.centerXAnchor.constraint(equalTo: centerXAnchor), - imageView.heightAnchor.constraint(equalToConstant: 28), + imageView.heightAnchor.constraint(equalToConstant: 32), ]) } @@ -68,4 +69,8 @@ class StickView: UIView { slider.minimumValue = -10 slider.value = 0 } + + private func setupImageView() { + imageView.contentMode = .center + } } From afd24768c0db5d71b811026fade571e3f12ffb7f Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Tue, 10 Oct 2017 09:34:42 +0100 Subject: [PATCH 10/12] Refactoring --- BoostRemote/StickView.swift | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/BoostRemote/StickView.swift b/BoostRemote/StickView.swift index ae4f207..f8b68d4 100644 --- a/BoostRemote/StickView.swift +++ b/BoostRemote/StickView.swift @@ -11,9 +11,6 @@ import UIKit @IBDesignable class StickView: UIView { - private let verticalSlider = VerticalSlider() - private let imageView = UIImageView() - var slider: UISlider { return verticalSlider.slider } @@ -37,12 +34,6 @@ class StickView: UIView { } private func initialize() { - setupSlider() - setupImageView() - - verticalSlider.translatesAutoresizingMaskIntoConstraints = false - imageView.translatesAutoresizingMaskIntoConstraints = false - addSubview(verticalSlider) addSubview(imageView) @@ -60,17 +51,26 @@ class StickView: UIView { ]) } - private func setupSlider() { - slider.setThumbImage(UIImage(named: "thumb"), for: .normal) - slider.setMinimumTrackImage(UIImage(named: "left"), for: .normal) - slider.setMaximumTrackImage(UIImage(named: "right"), for: .normal) + private let verticalSlider: VerticalSlider = { + let verticalSlider = VerticalSlider() + verticalSlider.translatesAutoresizingMaskIntoConstraints = false - slider.maximumValue = 10 - slider.minimumValue = -10 - slider.value = 0 - } + 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 func setupImageView() { + private let imageView: UIImageView = { + let imageView = UIImageView() + imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.contentMode = .center - } + return imageView + }() } From 1884e92798c2fe088ec3c27acaf99502b88b7767 Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Sat, 14 Oct 2017 01:30:45 +0100 Subject: [PATCH 11/12] Support four motors --- BoostRemote/Base.lproj/Main.storyboard | 71 ++++++++++++--------- BoostRemote/ControllerViewController.swift | 72 +++++++++++----------- 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/BoostRemote/Base.lproj/Main.storyboard b/BoostRemote/Base.lproj/Main.storyboard index 16137aa..11d2a24 100644 --- a/BoostRemote/Base.lproj/Main.storyboard +++ b/BoostRemote/Base.lproj/Main.storyboard @@ -36,40 +36,55 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + - - - - + + - - + @@ -84,7 +99,6 @@ - @@ -109,15 +123,16 @@ - - - + + + + - + diff --git a/BoostRemote/ControllerViewController.swift b/BoostRemote/ControllerViewController.swift index c3797b3..1090219 100644 --- a/BoostRemote/ControllerViewController.swift +++ b/BoostRemote/ControllerViewController.swift @@ -14,49 +14,46 @@ import ReSwift class ControllerViewController: UIViewController { - @IBOutlet private weak var leftStick: StickView! - @IBOutlet private weak var rightStick: StickView! - @IBOutlet private weak var centerStick: StickView! + @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 private weak var connectButtonImageView: UIImageView! private let connectionState = MutableProperty(ConnectionState.disconnected) - private var leftMotor: Motor? = Motor(port: .A) - private var rightMotor: Motor? = Motor(port: .B) - private var centerMotor: Motor? { + private var motors: [Port: Motor] = [:] { didSet { - let alpha: CGFloat - if let motor = centerMotor { - centerStick.port = motor.port - alpha = 1.0 - } else { - alpha = 0.0 - } - - UIView.animate(withDuration: 0.2) { - self.centerStick.alpha = alpha - } + stickC?.isHidden = !motors.keys.contains(.C) + stickD?.isHidden = !motors.keys.contains(.D) } } override func viewDidLoad() { super.viewDidLoad() - leftStick.port = .A - rightStick.port = .B - centerStick.alpha = 0.0 - setupConnectButtonImageView() - signal(for: leftStick.slider).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: rightStick.slider).observeValues { [weak self] (value) in - self?.sendCommand(motor: self?.rightMotor, power: value) + signal(for: stickB.slider).observeValues { [weak self] (value) in + self?.sendCommand(port: .B, power: value) } - signal(for: centerStick.slider).observeValues { [weak self] (value) in - self?.sendCommand(motor: self?.centerMotor, power: value) + signal(for: stickC.slider).observeValues { [weak self] (value) in + self?.sendCommand(port: .C, power: value) + } + signal(for: stickD.slider).observeValues { [weak self] (value) in + self?.sendCommand(port: .D, power: value) } } @@ -109,8 +106,8 @@ class ControllerViewController: UIViewController { return Signal.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) } } @@ -142,14 +139,17 @@ extension ControllerViewController: StoreSubscriber { 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 + 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 } - .first - } else { - centerMotor = nil + } } } } From baedb32f6089a96dc52c3c7f4c4f52defb6c7c7f Mon Sep 17 00:00:00 2001 From: Shinichiro Oba Date: Sat, 14 Oct 2017 01:39:02 +0100 Subject: [PATCH 12/12] Update the version number to 1.1.0 (15) --- BoostRemote/Info.plist | 4 ++-- BoostRemote/Settings.bundle/Root.plist | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BoostRemote/Info.plist b/BoostRemote/Info.plist index c342fca..874378c 100644 --- a/BoostRemote/Info.plist +++ b/BoostRemote/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.3 + 1.1.0 CFBundleVersion - 14 + 15 LSRequiresIPhoneOS NSBluetoothPeripheralUsageDescription diff --git a/BoostRemote/Settings.bundle/Root.plist b/BoostRemote/Settings.bundle/Root.plist index 0ff3d95..48b1074 100644 --- a/BoostRemote/Settings.bundle/Root.plist +++ b/BoostRemote/Settings.bundle/Root.plist @@ -16,7 +16,7 @@ Type PSTitleValueSpecifier DefaultValue - 1.0.3 + 1.1.0 Title Version Key