Skip to content

Commit

Permalink
PROGRESS child view controllers, GFUserInfoHeaderVC
Browse files Browse the repository at this point in the history
  • Loading branch information
grenos committed Mar 31, 2020
1 parent 7254b2a commit f4b66bd
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 5 deletions.
12 changes: 12 additions & 0 deletions GHFollowers.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
7DA45F73242E332000AB426F /* UIHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F72242E332000AB426F /* UIHelper.swift */; };
7DA45F7A242FB95700AB426F /* GFEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F79242FB95700AB426F /* GFEmptyStateView.swift */; };
7DA45F7C2430E3C900AB426F /* UserInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F7B2430E3C900AB426F /* UserInfoVC.swift */; };
7DA45F812433DE1300AB426F /* GFTitleLabel-Secondary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F802433DE1300AB426F /* GFTitleLabel-Secondary.swift */; };
7DA45F832433F4FC00AB426F /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F822433F4FC00AB426F /* Constants.swift */; };
7DA45F852433FAF800AB426F /* GFUserInfoheaderVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DA45F842433FAF800AB426F /* GFUserInfoheaderVC.swift */; };
7DFAC88A242A86D200F5780C /* GFAlertContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DFAC889242A86D200F5780C /* GFAlertContainerView.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -57,6 +60,9 @@
7DA45F72242E332000AB426F /* UIHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIHelper.swift; sourceTree = "<group>"; };
7DA45F79242FB95700AB426F /* GFEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GFEmptyStateView.swift; sourceTree = "<group>"; };
7DA45F7B2430E3C900AB426F /* UserInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoVC.swift; sourceTree = "<group>"; };
7DA45F802433DE1300AB426F /* GFTitleLabel-Secondary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GFTitleLabel-Secondary.swift"; sourceTree = "<group>"; };
7DA45F822433F4FC00AB426F /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
7DA45F842433FAF800AB426F /* GFUserInfoheaderVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GFUserInfoheaderVC.swift; sourceTree = "<group>"; };
7DFAC889242A86D200F5780C /* GFAlertContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GFAlertContainerView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -168,6 +174,7 @@
children = (
7DA45F6B242BAEEC00AB426F /* ErrorMessage.swift */,
7DA45F72242E332000AB426F /* UIHelper.swift */,
7DA45F822433F4FC00AB426F /* Constants.swift */,
);
path = Utilities;
sourceTree = "<group>";
Expand Down Expand Up @@ -218,6 +225,7 @@
children = (
7D98BB45242A52B7006C53E9 /* GFTitleLabel.swift */,
7D98BB47242A5507006C53E9 /* GFBodyLabel.swift */,
7DA45F802433DE1300AB426F /* GFTitleLabel-Secondary.swift */,
);
path = Labels;
sourceTree = "<group>";
Expand All @@ -226,6 +234,7 @@
isa = PBXGroup;
children = (
7D98BB49242A55ED006C53E9 /* GFAlertVC.swift */,
7DA45F842433FAF800AB426F /* GFUserInfoheaderVC.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -315,12 +324,15 @@
7DA45F64242B73E600AB426F /* Follower.swift in Sources */,
7D98BB46242A52B7006C53E9 /* GFTitleLabel.swift in Sources */,
7D98BB4C242A7327006C53E9 /* UIViewController+EXT.swift in Sources */,
7DA45F812433DE1300AB426F /* GFTitleLabel-Secondary.swift in Sources */,
7D98BB44242A29B4006C53E9 /* FollowerListVC.swift in Sources */,
7DA45F6C242BAEEC00AB426F /* ErrorMessage.swift in Sources */,
7DA45F73242E332000AB426F /* UIHelper.swift in Sources */,
7DA45F69242B831900AB426F /* NetworkManager.swift in Sources */,
7D98BB282428FE73006C53E9 /* AppDelegate.swift in Sources */,
7DA45F852433FAF800AB426F /* GFUserInfoheaderVC.swift in Sources */,
7D98BB2A2428FE73006C53E9 /* SceneDelegate.swift in Sources */,
7DA45F832433F4FC00AB426F /* Constants.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Binary file not shown.
39 changes: 39 additions & 0 deletions GHFollowers/Components/Labels/GFTitleLabel-Secondary.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// GFTitleLabel-Secondary.swift
// GHFollowers
//
// Created by Vasileios Gkreen on 31/03/2020.
// Copyright © 2020 Vasileios Gkreen. All rights reserved.
//

import UIKit

class GFTitleLabel_Secondary: UILabel {

override init(frame: CGRect) {
super.init(frame: frame)
configure()
}


required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}


init(fontSize: CGFloat) {
super.init(frame: .zero)
font = UIFont.systemFont(ofSize: fontSize, weight: .medium)

configure()
}


private func configure () {
textColor = .secondaryLabel
adjustsFontSizeToFitWidth = true
minimumScaleFactor = 0.90
lineBreakMode = .byTruncatingTail
translatesAutoresizingMaskIntoConstraints = false
}
}
109 changes: 109 additions & 0 deletions GHFollowers/Components/ViewControllers/GFUserInfoheaderVC.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//
// GFUserInfoheaderVC.swift
// GHFollowers
//
// Created by Vasileios Gkreen on 01/04/2020.
// Copyright © 2020 Vasileios Gkreen. All rights reserved.
//


import UIKit

class GFUserInfoheaderVC: UIViewController {

let avatarImageView = GFAvatarImageView(frame: .zero)
let usernameLabel = GFTitleLabel(textAlignment: .left, fontSize: 34)
let nameLabel = GFTitleLabel_Secondary(fontSize: 18)
let locationImageView = UIImageView()
let locationLabel = GFTitleLabel_Secondary(fontSize: 18)
let bioLabel = GFBodyLabel(textAlignment: .left)

var user: User!

// create a custom initializer
// so when we initialize the VC we can pass the User object
init(user: User) {
super.init(nibName: nil, bundle: nil)
self.user = user
}
// the no storyboard init
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()
addSubViews()
layoutUI()
configureUIElements()
}


func configureUIElements() {
avatarImageView.downloadImage(from: user.avatarUrl)
usernameLabel.text = user.login
nameLabel.text = user.name ?? "" // nil coalescing (if null then use placeholder in string)
locationLabel.text = user.location ?? "No Location"
bioLabel.text = user.bio ?? ""
bioLabel.numberOfLines = 3

locationImageView.image = UIImage(systemName: SFSymbols.location)
// ovveride the default blue color of SFSymbols
locationImageView.tintColor = .secondaryLabel
}



// MARK: VIEW FUNCTIONS

// add all the subView here
func addSubViews() {
view.addSubview(avatarImageView)
view.addSubview(usernameLabel)
view.addSubview(nameLabel)
view.addSubview(locationImageView)
view.addSubview(locationLabel)
view.addSubview(bioLabel)
}


// add all constraints for the elements here
func layoutUI() {
let padding: CGFloat = 20
let textImagePadding: CGFloat = 12
locationImageView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
avatarImageView.topAnchor.constraint(equalTo: view.topAnchor, constant: padding),
avatarImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding),
avatarImageView.widthAnchor.constraint(equalToConstant: 90),
avatarImageView.heightAnchor.constraint(equalToConstant: 90),

usernameLabel.topAnchor.constraint(equalTo: avatarImageView.topAnchor),
usernameLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: textImagePadding),
usernameLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
usernameLabel.heightAnchor.constraint(equalToConstant: 38),

nameLabel.centerYAnchor.constraint(equalTo: avatarImageView.centerYAnchor, constant: 8),
nameLabel.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: textImagePadding),
nameLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
nameLabel.heightAnchor.constraint(equalToConstant: 20),

locationImageView.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor),
locationImageView.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: textImagePadding),
locationImageView.heightAnchor.constraint(equalToConstant: 20),
locationImageView.widthAnchor.constraint(equalToConstant: 20),

locationLabel.centerYAnchor.constraint(equalTo: locationImageView.centerYAnchor),
locationLabel.leadingAnchor.constraint(equalTo: locationImageView.trailingAnchor, constant: 5),
locationLabel.trailingAnchor.constraint(equalToSystemSpacingAfter: view.trailingAnchor, multiplier: -padding),
locationLabel.heightAnchor.constraint(equalToConstant: 20),

bioLabel.topAnchor.constraint(equalTo: avatarImageView.bottomAnchor, constant: textImagePadding),
bioLabel.leadingAnchor.constraint(equalTo: avatarImageView.leadingAnchor),
bioLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding),
bioLabel.heightAnchor.constraint(equalToConstant: 60)
])
}
}

35 changes: 30 additions & 5 deletions GHFollowers/Screens/UserInfoVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,62 @@ import UIKit

class UserInfoVC: UIViewController {

let headerView = UIView()

// username gets passed here from FollowerListVC from function -- extension FollowerListVC: UICollectionViewDelegate --
var username: String!

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .systemBackground
// create done button for navigation
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissVC))
// add button to navigation bar
navigationItem.rightBarButtonItem = doneButton

layoutUI()

NetworkManager.shared.getUserInfo(for: username) { [weak self] result in
guard let self = self else {return}

switch result {
case .success(let user):
print(user)

DispatchQueue.main.async {
self.add(childVC: GFUserInfoheaderVC(user: user), to: self.headerView)
}

case .failure(let error):
self.presentGFAlertOnMainThread(title: "Something went wrong", message: error.rawValue, buttonTitle: "Ok")
}


}

}

@objc func dismissVC() {
dismiss(animated: true)
}



func layoutUI() {
view.addSubview(headerView)
headerView.translatesAutoresizingMaskIntoConstraints = false

NSLayoutConstraint.activate([
headerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
headerView.heightAnchor.constraint(equalToConstant: 180)
])
}

func add(childVC: UIViewController, to containerView: UIView) {
addChild(childVC)
containerView.addSubview(childVC.view)
childVC.view.frame = containerView.bounds
childVC.didMove(toParent: self)
}


}
13 changes: 13 additions & 0 deletions GHFollowers/Utilities/Constants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// Constants.swift
// GHFollowers
//
// Created by Vasileios Gkreen on 01/04/2020.
// Copyright © 2020 Vasileios Gkreen. All rights reserved.
//

import Foundation

enum SFSymbols {
static let location = "mappin.and.ellipse"
}

0 comments on commit f4b66bd

Please sign in to comment.