From 6e894ddf5eee887607d439fdbaa8338316fbe0a6 Mon Sep 17 00:00:00 2001 From: GusRigor Date: Mon, 12 Dec 2022 13:46:43 -0300 Subject: [PATCH 1/3] implement navbutton to userProfile --- .../FinanceApp.xcodeproj/project.pbxproj | 28 +++++++ .../Screens/Commons/CodeBaseView.swift | 49 ++++++++++++ .../Screens/Commons/HierarchyRelation.swift | 13 +++ .../Screens/Home/HomeViewController.swift | 8 ++ .../Home/Subviews/ProfileButtonView.swift | 79 +++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift create mode 100644 solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/HierarchyRelation.swift create mode 100644 solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp.xcodeproj/project.pbxproj b/solutions/devsprint-pedro-alvarez-2/FinanceApp.xcodeproj/project.pbxproj index c80625f..b7d2cb9 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp.xcodeproj/project.pbxproj +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 1CD90C6F29475D1100237BD9 /* ProfileButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90C6E29475D1100237BD9 /* ProfileButtonView.swift */; }; + 1CD90C7229475E6500237BD9 /* CodeBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90C7129475E6500237BD9 /* CodeBaseView.swift */; }; + 1CD90C742947629000237BD9 /* HierarchyRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90C732947629000237BD9 /* HierarchyRelation.swift */; }; 1DBC0432294176F6000501FA /* TabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DBC0431294176F6000501FA /* TabBarController.swift */; }; 98584A6D277E32C30028DBEA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98584A6C277E32C30028DBEA /* AppDelegate.swift */; }; 98584A6F277E32C30028DBEA /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98584A6E277E32C30028DBEA /* SceneDelegate.swift */; }; @@ -71,6 +74,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1CD90C6E29475D1100237BD9 /* ProfileButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileButtonView.swift; sourceTree = ""; }; + 1CD90C7129475E6500237BD9 /* CodeBaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBaseView.swift; sourceTree = ""; }; + 1CD90C732947629000237BD9 /* HierarchyRelation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HierarchyRelation.swift; sourceTree = ""; }; 1DBC0431294176F6000501FA /* TabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarController.swift; sourceTree = ""; }; 98584A69277E32C30028DBEA /* FinanceApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FinanceApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 98584A6C277E32C30028DBEA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -146,6 +152,23 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1CD90C6D29475CDF00237BD9 /* Subviews */ = { + isa = PBXGroup; + children = ( + 1CD90C6E29475D1100237BD9 /* ProfileButtonView.swift */, + ); + path = Subviews; + sourceTree = ""; + }; + 1CD90C7029475E2700237BD9 /* Commons */ = { + isa = PBXGroup; + children = ( + 1CD90C7129475E6500237BD9 /* CodeBaseView.swift */, + 1CD90C732947629000237BD9 /* HierarchyRelation.swift */, + ); + path = Commons; + sourceTree = ""; + }; 1DBC043029417602000501FA /* TabBar */ = { isa = PBXGroup; children = ( @@ -238,6 +261,7 @@ 98584A9E277E35700028DBEA /* Screens */ = { isa = PBXGroup; children = ( + 1CD90C7029475E2700237BD9 /* Commons */, 98906BEC29392209001D1975 /* Components */, 98584B08277E602C0028DBEA /* ContactList */, 98584ADF277E50430028DBEA /* Confirmation */, @@ -252,6 +276,7 @@ 98584A9F277E35780028DBEA /* Home */ = { isa = PBXGroup; children = ( + 1CD90C6D29475CDF00237BD9 /* Subviews */, 98584AA6277E35F10028DBEA /* HomeView.swift */, 98584AA4277E35E90028DBEA /* HomeViewController.swift */, ); @@ -486,6 +511,7 @@ 98906BEE2939221B001D1975 /* AccountSummaryView.swift in Sources */, 98584B10277E605F0028DBEA /* ActivityDetailsViewController.swift in Sources */, 98584B20277E60740028DBEA /* ContactListViewController.swift in Sources */, + 1CD90C6F29475D1100237BD9 /* ProfileButtonView.swift in Sources */, 98584AF4277E50430028DBEA /* ConfirmationViewController.swift in Sources */, 98C8A4DD27C818A800A630ED /* HomeData.swift in Sources */, 98C8A4D927C8152200A630ED /* String+Extensions.swift in Sources */, @@ -496,6 +522,7 @@ 98906BF42939225B001D1975 /* ContactCellView.swift in Sources */, 98584B14277E605F0028DBEA /* ActivityDetailsView.swift in Sources */, 98584AE7277E50430028DBEA /* TransfersView.swift in Sources */, + 1CD90C742947629000237BD9 /* HierarchyRelation.swift in Sources */, 98906BF62939226B001D1975 /* UserProfileHeaderView.swift in Sources */, 98C8A4DB27C815C000A630ED /* UITableViewCell+Extensions.swift in Sources */, 98584AF3277E50430028DBEA /* ConfirmationView.swift in Sources */, @@ -504,6 +531,7 @@ 98584A6F277E32C30028DBEA /* SceneDelegate.swift in Sources */, 98906BF02939223C001D1975 /* ActivityCellView.swift in Sources */, 98584AA7277E35F10028DBEA /* HomeView.swift in Sources */, + 1CD90C7229475E6500237BD9 /* CodeBaseView.swift in Sources */, 98584B1F277E60740028DBEA /* ContactListView.swift in Sources */, 1DBC0432294176F6000501FA /* TabBarController.swift in Sources */, 989627E027ADC2F60009A07F /* DebugViewController.swift in Sources */, diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift new file mode 100644 index 0000000..919055f --- /dev/null +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift @@ -0,0 +1,49 @@ +// +// CodeBaseView.swift +// Pods +// +// Created by Pedro Alvarez on 08/12/22. +// +import UIKit + +public class CodeBaseView: UIView { + open var hierarchies: [HierarchyRelation] { [] } + + override init(frame: CGRect) { + super.init(frame: frame) + setupHierarchy() + setupConstraints() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private var viewModel: ViewModel? { + didSet { + configureView(viewModel) + } + } + + public func setupViewModel(_ viewModel: ViewModel) { + self.viewModel = viewModel + } + + private func setupHierarchy() { + for relation in hierarchies { + for subview in relation.subviews { + if let stackView = relation.parentView as? UIStackView { + stackView.addArrangedSubview(subview) + } else { + relation.parentView.addSubview(subview) + } + } + } + } + + private func setupConstraints() { + NSLayoutConstraint.activate(constraints) + } + + open func configureView(_ viewModel: ViewModel?) { } +} diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/HierarchyRelation.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/HierarchyRelation.swift new file mode 100644 index 0000000..96d397a --- /dev/null +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/HierarchyRelation.swift @@ -0,0 +1,13 @@ +// +// HierarchyRelation.swift +// FinanceApp +// +// Created by Gustavo Rigor on 12/12/22. +// + +import UIKit + +public struct HierarchyRelation { + let parentView: UIView + let subviews: [UIView] +} diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift index add9766..df0af8b 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift @@ -21,6 +21,7 @@ class HomeViewController: UIViewController { navigationItem.title = "Finance App 💰" navigationController?.navigationBar.prefersLargeTitles = true + setupProfileImage() service.fetchHomeData { homeData in @@ -40,4 +41,11 @@ class HomeViewController: UIViewController { override func loadView() { self.view = homeView } + + private func setupProfileImage() { + let barButton = UIBarButtonItem() + barButton.customView = ProfileButtonView() + self.navigationItem.rightBarButtonItem = barButton + } + } diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift new file mode 100644 index 0000000..4a1c5ae --- /dev/null +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift @@ -0,0 +1,79 @@ +// +// ProfileButtonView.swift +// FinanceApp +// +// Created by Gustavo Rigor on 12/12/22. +// + +import UIKit + +class ProfileButtonView: CodeBaseView { + + //MARK: - Custom Data + struct ViewModel { + let image: String + + init(image: String) { + self.image = image + } + } + + enum Constants { + static let imageName: String = "avatar-placeholder" + static let imageHeight: CGFloat = 36 + static let imageWidth: CGFloat = 36 + static let half: CGFloat = 0.5 + } + + private lazy var profileButton: UIButton = { + let button = UIButton() + button.frame = CGRectMake(.zero, .zero, Constants.imageHeight, Constants.imageWidth) + let image = UIImage(named: Constants.imageName) + if let image = image { + UIGraphicsBeginImageContextWithOptions(button.frame.size, false, image.scale) + + let rect = CGRectMake(.zero, .zero, button.frame.size.width, button.frame.size.height) + UIBezierPath(roundedRect: rect, cornerRadius: Constants.half * rect.width).addClip() + image.draw(in: rect) + + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + + let color = UIColor(patternImage: newImage!) + button.backgroundColor = color + button.layer.cornerRadius = Constants.half * button.bounds.size.width + } + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //MARK: - View Coding + override public var hierarchies: [HierarchyRelation] { + [ + .init(parentView: self, subviews: [profileButton]), + ] + } + + override public var constraints: [NSLayoutConstraint] { + [ + profileButton.topAnchor.constraint(equalTo: topAnchor), + profileButton.leadingAnchor.constraint(equalTo: leadingAnchor), + profileButton.trailingAnchor.constraint(equalTo: trailingAnchor), + profileButton.bottomAnchor.constraint(equalTo: bottomAnchor) + ] + } + + override public func configureView(_ viewModel: ViewModel?) { + // Configure + } + +} From 3a978c72160da9b334591c189c0183363ab42d52 Mon Sep 17 00:00:00 2001 From: GusRigor Date: Mon, 12 Dec 2022 16:54:15 -0300 Subject: [PATCH 2/3] fix request on pull request --- .../Screens/Commons/CodeBaseView.swift | 79 ++++++++++--------- .../Screens/Home/HomeViewController.swift | 6 ++ .../Home/Subviews/ProfileButtonView.swift | 2 +- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift index 919055f..c3b7175 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Commons/CodeBaseView.swift @@ -7,43 +7,50 @@ import UIKit public class CodeBaseView: UIView { - open var hierarchies: [HierarchyRelation] { [] } - - override init(frame: CGRect) { - super.init(frame: frame) - setupHierarchy() - setupConstraints() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private var viewModel: ViewModel? { - didSet { - configureView(viewModel) + + open var hierarchies: [HierarchyRelation] { [] } + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + @available(*,unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + setupHierarchy() + setupConstraints() + } + + private var viewModel: ViewModel? { + didSet { + configureView(viewModel) + } + } + + public func setupViewModel(_ viewModel: ViewModel) { + self.viewModel = viewModel } - } - - public func setupViewModel(_ viewModel: ViewModel) { - self.viewModel = viewModel - } - - private func setupHierarchy() { - for relation in hierarchies { - for subview in relation.subviews { - if let stackView = relation.parentView as? UIStackView { - stackView.addArrangedSubview(subview) - } else { - relation.parentView.addSubview(subview) + + private func setupHierarchy() { + for relation in hierarchies { + for subview in relation.subviews { + if let stackView = relation.parentView as? UIStackView { + stackView.addArrangedSubview(subview) + } else { + relation.parentView.addSubview(subview) + } + } } - } } - } - - private func setupConstraints() { - NSLayoutConstraint.activate(constraints) - } - - open func configureView(_ viewModel: ViewModel?) { } + + private func setupConstraints() { + NSLayoutConstraint.activate(constraints) + } + + open func configureView(_ viewModel: ViewModel?) { } + } diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift index df0af8b..a4181cf 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift @@ -45,7 +45,13 @@ class HomeViewController: UIViewController { private func setupProfileImage() { let barButton = UIBarButtonItem() barButton.customView = ProfileButtonView() + barButton.action = #selector(redirectToUserProfile) self.navigationItem.rightBarButtonItem = barButton } + + @objc private func redirectToUserProfile(){ + //TODO: Implement redirect to UserProfile + print("TODO: implementar redirect") + } } diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift index 4a1c5ae..db5031f 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift @@ -7,7 +7,7 @@ import UIKit -class ProfileButtonView: CodeBaseView { +final class ProfileButtonView: CodeBaseView { //MARK: - Custom Data struct ViewModel { From a1b74cb36af5f9264315305ab8300b8a14fea3ba Mon Sep 17 00:00:00 2001 From: GusRigor Date: Tue, 13 Dec 2022 10:45:11 -0300 Subject: [PATCH 3/3] refactor ProfileButtonView --- .../Screens/Home/HomeViewController.swift | 18 ++++--- .../Home/Subviews/ProfileButtonView.swift | 50 ++++++++----------- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift index a4181cf..c849e1d 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/HomeViewController.swift @@ -10,6 +10,15 @@ import UIKit class HomeViewController: UIViewController { private let service = FinanceService() + + private let barButton = { imageName in + let barButton = UIBarButtonItem() + let profileButton = ProfileButtonView() + profileButton.configureView(imageName) + barButton.customView = profileButton + barButton.action = #selector(redirectToUserProfile) + return barButton + } private let homeView: HomeView = { @@ -20,8 +29,8 @@ class HomeViewController: UIViewController { override func viewDidLoad() { navigationItem.title = "Finance App 💰" + navigationItem.rightBarButtonItem = barButton("avatar-placeholder") navigationController?.navigationBar.prefersLargeTitles = true - setupProfileImage() service.fetchHomeData { homeData in @@ -41,13 +50,6 @@ class HomeViewController: UIViewController { override func loadView() { self.view = homeView } - - private func setupProfileImage() { - let barButton = UIBarButtonItem() - barButton.customView = ProfileButtonView() - barButton.action = #selector(redirectToUserProfile) - self.navigationItem.rightBarButtonItem = barButton - } @objc private func redirectToUserProfile(){ //TODO: Implement redirect to UserProfile diff --git a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift index db5031f..3c23357 100644 --- a/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift +++ b/solutions/devsprint-pedro-alvarez-2/FinanceApp/Screens/Home/Subviews/ProfileButtonView.swift @@ -7,16 +7,7 @@ import UIKit -final class ProfileButtonView: CodeBaseView { - - //MARK: - Custom Data - struct ViewModel { - let image: String - - init(image: String) { - self.image = image - } - } +final class ProfileButtonView: CodeBaseView { enum Constants { static let imageName: String = "avatar-placeholder" @@ -27,23 +18,7 @@ final class ProfileButtonView: CodeBaseView { private lazy var profileButton: UIButton = { let button = UIButton() - button.frame = CGRectMake(.zero, .zero, Constants.imageHeight, Constants.imageWidth) - let image = UIImage(named: Constants.imageName) - if let image = image { - UIGraphicsBeginImageContextWithOptions(button.frame.size, false, image.scale) - - let rect = CGRectMake(.zero, .zero, button.frame.size.width, button.frame.size.height) - UIBezierPath(roundedRect: rect, cornerRadius: Constants.half * rect.width).addClip() - image.draw(in: rect) - - let newImage = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - - - let color = UIColor(patternImage: newImage!) - button.backgroundColor = color - button.layer.cornerRadius = Constants.half * button.bounds.size.width - } + button.translatesAutoresizingMaskIntoConstraints = false return button }() @@ -66,14 +41,29 @@ final class ProfileButtonView: CodeBaseView { override public var constraints: [NSLayoutConstraint] { [ profileButton.topAnchor.constraint(equalTo: topAnchor), - profileButton.leadingAnchor.constraint(equalTo: leadingAnchor), profileButton.trailingAnchor.constraint(equalTo: trailingAnchor), + profileButton.widthAnchor.constraint(equalToConstant: Constants.imageWidth), + profileButton.heightAnchor.constraint(equalToConstant: Constants.imageHeight), profileButton.bottomAnchor.constraint(equalTo: bottomAnchor) ] } - override public func configureView(_ viewModel: ViewModel?) { - // Configure + override public func configureView(_ viewModel: String?) { + let image = UIImage(named: viewModel ?? Constants.imageName) + DispatchQueue.main.async { + if let image = image { + UIGraphicsBeginImageContextWithOptions(self.profileButton.frame.size, false, image.scale) + let rect = CGRectMake(.zero, .zero, self.profileButton.frame.size.width, self.profileButton.frame.size.height) + UIBezierPath(roundedRect: rect, cornerRadius: Constants.half * rect.width).addClip() + image.draw(in: rect) + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + let color = UIColor(patternImage: newImage!) + self.profileButton.backgroundColor = color + self.profileButton.layer.cornerRadius = Constants.half * self.profileButton.bounds.size.width + } + } + } }