From a60bde85e09351d62288588f19676ac0792482bc Mon Sep 17 00:00:00 2001 From: Danny Date: Fri, 3 May 2019 14:18:56 +0200 Subject: [PATCH 1/2] add logout button (clear user token ) --- .../UserProfileViewController.swift | 13 +++++-- .../UserProfile/UserProfileViewController.xib | 16 +++++++-- .../UserProfile/UserProfileViewModel.swift | 34 ++++++++++++++++++- Podfile.lock | 2 +- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/Papr/Scenes/UserProfile/UserProfileViewController.swift b/Papr/Scenes/UserProfile/UserProfileViewController.swift index 6502e68..8950955 100644 --- a/Papr/Scenes/UserProfile/UserProfileViewController.swift +++ b/Papr/Scenes/UserProfile/UserProfileViewController.swift @@ -7,14 +7,23 @@ // import UIKit +import RxSwift class UserProfileViewController: UIViewController, BindableType { + @IBOutlet weak var logoutButton: UIButton! + var viewModel: UserProfileViewModel! - + + private let disposeBag = DisposeBag() + override func viewDidLoad() { super.viewDidLoad() } - func bindViewModel() {} + func bindViewModel() { + let inputs = viewModel.inputs + + logoutButton.rx.action = inputs.logoutAction + } } diff --git a/Papr/Scenes/UserProfile/UserProfileViewController.xib b/Papr/Scenes/UserProfile/UserProfileViewController.xib index 0f2c513..9520d6a 100644 --- a/Papr/Scenes/UserProfile/UserProfileViewController.xib +++ b/Papr/Scenes/UserProfile/UserProfileViewController.xib @@ -1,17 +1,18 @@ - + - + + @@ -23,12 +24,21 @@ + + + diff --git a/Papr/Scenes/UserProfile/UserProfileViewModel.swift b/Papr/Scenes/UserProfile/UserProfileViewModel.swift index e7b562f..b06ee16 100644 --- a/Papr/Scenes/UserProfile/UserProfileViewModel.swift +++ b/Papr/Scenes/UserProfile/UserProfileViewModel.swift @@ -8,7 +8,39 @@ import Foundation import RxSwift +import Action -class UserProfileViewModel { +protocol UserProfileViewModelInput { + var logoutAction: CocoaAction { get } +} + +protocol UserProfileViewModelOutput { +} + +protocol UserProfileViewModelType { + var inputs: UserProfileViewModelInput { get } + var outputs: UserProfileViewModelOutput { get } +} + +class UserProfileViewModel: UserProfileViewModelType, UserProfileViewModelInput, UserProfileViewModelOutput { + + var inputs: UserProfileViewModelInput { return self } + var outputs: UserProfileViewModelOutput { return self } + + + // MARK: Private + private let sceneCoordinator: SceneCoordinatorType + + init(sceneCoordinator: SceneCoordinatorType = SceneCoordinator.shared) { + self.sceneCoordinator = sceneCoordinator + } + + lazy var logoutAction: CocoaAction = { + return CocoaAction { _ in + UnsplashAuthManager.shared.clearAccessToken() + + return self.sceneCoordinator.transition(to: Scene.papr) + } + }() } diff --git a/Podfile.lock b/Podfile.lock index b297c0b..a7e808b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -62,4 +62,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 7bb83ef22953fe01a8077c84b732c839ebdb4a78 -COCOAPODS: 1.6.0.beta.2 +COCOAPODS: 1.6.1 From 1f65e7e3b6b3592b048c84223081427e50457cb0 Mon Sep 17 00:00:00 2001 From: Danny Date: Mon, 6 May 2019 22:25:27 +0200 Subject: [PATCH 2/2] add custom button component (animate on press) --- Papr.xcodeproj/project.pbxproj | 4 + Papr/Commons/Constants.swift | 1 + Papr/Custom UI/ButtonRounded.swift | 109 ++++++++++++++++++ .../UserProfileViewController.swift | 6 +- .../UserProfile/UserProfileViewController.xib | 17 ++- 5 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 Papr/Custom UI/ButtonRounded.swift diff --git a/Papr.xcodeproj/project.pbxproj b/Papr.xcodeproj/project.pbxproj index 85ab195..7fcf7be 100644 --- a/Papr.xcodeproj/project.pbxproj +++ b/Papr.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1090D75275C09BAE87BE25BD /* Pods_Papr.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D778F2E1EFA76CEB59A377CB /* Pods_Papr.framework */; }; 63CC2B27C8EE9499B1D6C702 /* Pods_PaprTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD3D8A956FB1C8A8D3B456A7 /* Pods_PaprTests.framework */; }; + B15C6FAD2280A44F008D641D /* ButtonRounded.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15C6FAC2280A44F008D641D /* ButtonRounded.swift */; }; C006934F2189DB4500AC6736 /* CollectionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C006934D2189DB4500AC6736 /* CollectionCell.xib */; }; C00739572151547500F51C91 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C00739562151547500F51C91 /* LoadingView.swift */; }; C09D7656216CC91E0035F54D /* UserProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C09D7654216CC91E0035F54D /* UserProfileViewController.swift */; }; @@ -361,6 +362,7 @@ 54A367A7275D753D93ACC1AB /* Pods-Papr.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Papr.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Papr/Pods-Papr.debug.xcconfig"; sourceTree = ""; }; 73C64AFFEE5BB0DA9AE1AB4D /* Pods-Papr.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Papr.release.xcconfig"; path = "Pods/Target Support Files/Pods-Papr/Pods-Papr.release.xcconfig"; sourceTree = ""; }; 7ADA4A068C8B3E3A9F491B6C /* Pods-PaprUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PaprUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PaprUITests/Pods-PaprUITests.release.xcconfig"; sourceTree = ""; }; + B15C6FAC2280A44F008D641D /* ButtonRounded.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonRounded.swift; sourceTree = ""; }; C006934D2189DB4500AC6736 /* CollectionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CollectionCell.xib; sourceTree = ""; }; C00739562151547500F51C91 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; C09D7654216CC91E0035F54D /* UserProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileViewController.swift; sourceTree = ""; }; @@ -779,6 +781,7 @@ DCB915AE20B9A8DE003D1069 /* PinterestLayout.swift */, DC3918CE21046AE8003DA2CA /* PaprNavigationController.swift */, DC487F482104FCB00042DBBC /* BouncyView.swift */, + B15C6FAC2280A44F008D641D /* ButtonRounded.swift */, ); path = "Custom UI"; sourceTree = ""; @@ -1368,6 +1371,7 @@ C0CD2444213EB2BD0053A802 /* CollectionsViewController.swift in Sources */, DCBB1B5B1FA8B840004E95F0 /* SceneTransitionType.swift in Sources */, DCB915B520BB1A9A003D1069 /* SearchPhotosCell.swift in Sources */, + B15C6FAD2280A44F008D641D /* ButtonRounded.swift in Sources */, DC5AF7591FAD2F1E00ADA2BB /* OrderBy.swift in Sources */, DCBB1B671FA8BA39004E95F0 /* LoginViewModel.swift in Sources */, DC487F432104F0970042DBBC /* ClassIdentifiable.swift in Sources */, diff --git a/Papr/Commons/Constants.swift b/Papr/Commons/Constants.swift index 3febfcd..50d1944 100644 --- a/Papr/Commons/Constants.swift +++ b/Papr/Commons/Constants.swift @@ -20,6 +20,7 @@ struct Constants { struct Style { static let imageCornersRadius: CGFloat = 8.0 + static let imageCornersRadiusWidth: CGFloat = 3.0 } } diff --git a/Papr/Custom UI/ButtonRounded.swift b/Papr/Custom UI/ButtonRounded.swift new file mode 100644 index 0000000..b54b900 --- /dev/null +++ b/Papr/Custom UI/ButtonRounded.swift @@ -0,0 +1,109 @@ +// +// ButtonRounded.swift +// Papr +// +// Created by imo on 6.05.19. +// Copyright © 2019 Joan Disho. All rights reserved. +// + +import Foundation +import UIKit + +enum ButtonRoundedStyle { + case border, fill +} + +class ButtonRounded: UIButton { + + var style: ButtonRoundedStyle = .border + + public func configure(type: ButtonRoundedStyle) { + style = type + setNeedsLayout() + layoutIfNeeded() + } + + override func layoutSubviews() { + super.layoutSubviews() + + layer.cornerRadius = Constants.Appearance.Style.imageCornersRadius + backgroundColor = .clear + + if style == .border { + layer.borderWidth = Constants.Appearance.Style.imageCornersRadiusWidth + layer.borderColor = UIColor.black.cgColor + layer.backgroundColor = UIColor.white.cgColor + + setTitleColor(.black, for: .normal) + + } else { + layer.borderColor = UIColor.clear.cgColor + layer.backgroundColor = UIColor.black.cgColor + + setTitleColor(.white, for: .normal) + } + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + borderDissapear(highlighted: true) + titleDissapear(highlighted: true) + backgroundDissapear(highlighted: true) + } + + override func touchesEnded(_ touches: Set, with event: UIEvent?) { + borderDissapear(highlighted: false) + titleDissapear(highlighted: false) + backgroundDissapear(highlighted: false) + } + + func borderDissapear (highlighted: Bool) { + let animation = CABasicAnimation(keyPath: "borderColor") + animation.duration = 0.1 + animation.autoreverses = false + animation.repeatCount = 1 + animation.fillMode = CAMediaTimingFillMode.forwards + animation.isRemovedOnCompletion = false + if highlighted { + animation.fromValue = self.layer.borderColor?.copy(alpha: 1) + animation.toValue = self.layer.borderColor?.copy(alpha: 0.3) + } else if !highlighted { + animation.fromValue = self.layer.borderColor?.copy(alpha: 0.3) + animation.toValue = self.layer.borderColor?.copy(alpha: 1) + } + self.layer.add(animation, forKey: "borderColor") + } + + func titleDissapear (highlighted: Bool) { + if !highlighted { + self.titleLabel?.textColor = self.titleLabel?.textColor.withAlphaComponent(0.3) + } else { + self.titleLabel?.textColor = self.titleLabel?.textColor.withAlphaComponent(1) + } + + UIView.animate(withDuration: 0.1, delay: 0, options: [.transitionCrossDissolve, .beginFromCurrentState], animations: { + if highlighted { + self.titleLabel?.textColor = self.titleLabel?.textColor.withAlphaComponent(0.3) + } else { + self.titleLabel?.textColor = self.titleLabel?.textColor.withAlphaComponent(1) + } + }, completion: nil) + } + + func backgroundDissapear (highlighted: Bool) { + let animation = CABasicAnimation(keyPath: "backgroundColor") + animation.duration = 0.1 + animation.autoreverses = false + animation.repeatCount = 1 + animation.fillMode = CAMediaTimingFillMode.forwards + animation.isRemovedOnCompletion = false + if highlighted { + animation.fromValue = self.layer.backgroundColor?.copy(alpha: 1) + animation.toValue = self.layer.backgroundColor?.copy(alpha: 0.3) + } else if !highlighted { + animation.fromValue = self.layer.backgroundColor?.copy(alpha: 0.3) + animation.toValue = self.layer.backgroundColor?.copy(alpha: 1) + } + self.layer.add(animation, forKey: "backgroundColor") + } + +} diff --git a/Papr/Scenes/UserProfile/UserProfileViewController.swift b/Papr/Scenes/UserProfile/UserProfileViewController.swift index 8950955..41c569a 100644 --- a/Papr/Scenes/UserProfile/UserProfileViewController.swift +++ b/Papr/Scenes/UserProfile/UserProfileViewController.swift @@ -11,7 +11,7 @@ import RxSwift class UserProfileViewController: UIViewController, BindableType { - @IBOutlet weak var logoutButton: UIButton! + @IBOutlet weak var logoutButton: ButtonRounded! var viewModel: UserProfileViewModel! @@ -19,6 +19,10 @@ class UserProfileViewController: UIViewController, BindableType { override func viewDidLoad() { super.viewDidLoad() + + logoutButton.configure(type: .border) + + title = "User profile" } func bindViewModel() { diff --git a/Papr/Scenes/UserProfile/UserProfileViewController.xib b/Papr/Scenes/UserProfile/UserProfileViewController.xib index 9520d6a..af0abd7 100644 --- a/Papr/Scenes/UserProfile/UserProfileViewController.xib +++ b/Papr/Scenes/UserProfile/UserProfileViewController.xib @@ -1,6 +1,6 @@ - + @@ -18,17 +18,20 @@ - + -