Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## Build generated
build/
DerivedData/

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/

## Other
PlikiTestowe
*.moved-aside
*.xccheckout
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
580 changes: 580 additions & 0 deletions MobileInternshipTask/MobileInternshipTask.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
18 changes: 18 additions & 0 deletions MobileInternshipTask/MobileInternshipTask/Controller/Alert.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Alerts.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 12/06/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import Foundation
import UIKit

class Alert {
static func showMessage(title: String, msg: String) {
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
UIApplication.topViewController()?.present(alert, animated: true, completion: nil)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// AppDelegate.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 25/04/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return true
}

func applicationWillResignActive(_ application: UIApplication) {

}

func applicationDidEnterBackground(_ application: UIApplication) {

}

func applicationWillEnterForeground(_ application: UIApplication) {

}

func applicationDidBecomeActive(_ application: UIApplication) {

}

func applicationWillTerminate(_ application: UIApplication) {

}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// DetailRepoViewController.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 30/04/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import UIKit

class DetailRepoViewController: UIViewController {
@IBOutlet weak var repoNameLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var languageLabel: UILabel!
@IBOutlet weak var createdLabel: UILabel!
@IBOutlet weak var updatedLabel: UILabel!
@IBOutlet weak var watchersLabel: UILabel!
@IBOutlet weak var forksLabel: UILabel!

var userRepo: UserRepos?
var createdDate: String?
var updatedDate: String?

override func viewDidLoad() {
super.viewDidLoad()
convertDateToString()
roundedCorners()
setupLabels()
}

func setupLabels() {
if let userRepos = userRepo {
repoNameLabel.text = userRepos.name
descriptionLabel.text = userRepos.description ?? "No description"
languageLabel.text = userRepos.language ?? "-"
watchersLabel.text = "Watchers: \((userRepos.watchers) ?? 0)"
forksLabel.text = "Forks: \(userRepos.forks ?? 0)"
updatedLabel.text = "Updated at: \n\(updatedDate ?? "-")"
createdLabel.text = "Created at: \n\(createdDate ?? "-")"
}
}

@IBAction func seeDetailsButton(_ sender: Any) {
if let htmlUrl = userRepo?.html_url {
guard let url = URL(string: htmlUrl) else {return}
UIApplication.shared.open(url, options: [:], completionHandler: nil )
}
}

func roundedCorners() {
repoNameLabel.makeRoundedCorners()
descriptionLabel.makeRoundedCorners()
languageLabel.makeRoundedCorners()
createdLabel.makeRoundedCorners()
updatedLabel.makeRoundedCorners()
watchersLabel.makeRoundedCorners()
forksLabel.makeRoundedCorners()
}

func convertDateToString() {
if let date = userRepo?.updated_at {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
if let dateFromString = dateFormatter.date(from: date) {
dateFormatter.dateStyle = .long
let dateToString = dateFormatter.string(from: dateFromString)
updatedDate = dateToString
}
}

if let date = userRepo?.created_at {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
if let dateFromString = dateFormatter.date(from: date) {
dateFormatter.dateStyle = .long
let dateToString = dateFormatter.string(from: dateFromString)
createdDate = dateToString
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// ConnectedToNetwork.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 01/05/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import Foundation
import SystemConfiguration

public class Reachability {

class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)

let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}

var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
return false
}

let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
let ret = (isReachable && !needsConnection)

return ret
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ReposFetcher.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 05/06/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import Foundation

class ReposFetcher {

private init() {}
static let shared = ReposFetcher()

func reposFetcher(userName: String, completion: @escaping ([UserRepos]?, Error?) -> ()) {
let githubAPI = "https://api.github.com/users/" + userName + "/repos"
guard let url = URL(string: githubAPI) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let data = data {
do {
let repos = try JSONDecoder().decode([UserRepos].self, from: data)
completion(repos, nil)
} catch {
completion(nil, error)
}
}
}.resume()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// ReposTableViewController.swift
// MobileInternshipTask
//
// Created by Dawid Ramone on 26/04/2018.
// Copyright © 2018 Dawid Czmyr. All rights reserved.
//

import UIKit

class ReposTableViewController: UITableViewController {

var repos: [UserRepos]?
var singleRepo: UserRepos?
let reposCell = "reposCell"
let detailRepo = "detailRepo"

override func viewDidLoad() {
super.viewDidLoad()
userDoesntHaveRepos()
setUserPhotoInNav()
registerCell()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == detailRepo {
guard let detailScreen = segue.destination as? DetailRepoViewController else { return }
detailScreen.userRepo = singleRepo
}
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let repos = repos else { return 0 }
return repos.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: reposCell, for: indexPath) as? ReposCell else { return UITableViewCell() }

if let repos = repos {
cell.repoTitleLabel.text = repos[indexPath.row].name
cell.languageLabel.text = repos[indexPath.row].language ?? "-"
}
return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let repos = repos {
let selectedRow = repos[indexPath.row]
singleRepo = selectedRow
performSegue(withIdentifier: detailRepo, sender: nil)
}
}

func userDoesntHaveRepos() {
if repos?.isEmpty == true {
Alert.showMessage(title: "Oops looks like user exist but doesn't have any repos", msg: "Try again")
}
}

func setUserPhotoInNav() {
if repos?.isEmpty == false {
if let repos = repos {
if let avatarUrl = repos[0].owner?.avatar_url {
guard let url = URL(string: avatarUrl) else { return }
URLSession.shared.dataTask(with: url) { (data, respone, error) in
if let error = error {
print(error)
}
if let dataImg = data {
let image = UIImage(data: dataImg)
DispatchQueue.main.async {
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
self.navigationItem.titleView = imageView
}
}
}.resume()
}
}
}
}

func registerCell() {
let customCellNibFile = UINib(nibName: "ReposCell", bundle: nil)
tableView.register(customCellNibFile, forCellReuseIdentifier: reposCell)
}

}
Loading