Skip to content

Commit

Permalink
implemented count lines of code feature
Browse files Browse the repository at this point in the history
  • Loading branch information
khoren93 committed Apr 16, 2020
1 parent 0e77ed0 commit b59bb7f
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 5 deletions.
16 changes: 16 additions & 0 deletions SwiftHub.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
073A1F792233F2F000D6F487 /* Search.graphql in Resources */ = {isa = PBXBuildFile; fileRef = 073A1F782233F2F000D6F487 /* Search.graphql */; };
074DBBEA24489E750062B35F /* CodetabsApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074DBBE924489E750062B35F /* CodetabsApi.swift */; };
074DBBEE2448A0480062B35F /* RepositoryNumberOfLines.json in Resources */ = {isa = PBXBuildFile; fileRef = 074DBBED2448A0480062B35F /* RepositoryNumberOfLines.json */; };
074DBBF12448AF0E0062B35F /* LinesCountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074DBBF02448AF0E0062B35F /* LinesCountViewModel.swift */; };
074DBBF32448AF220062B35F /* LinesCountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 074DBBF22448AF220062B35F /* LinesCountViewController.swift */; };
0752F48821C8D9A800A30BF2 /* TrendingRepositoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0752F48621C8D9A800A30BF2 /* TrendingRepositoryCell.swift */; };
0752F48921C8D9A800A30BF2 /* TrendingRepositoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0752F48721C8D9A800A30BF2 /* TrendingRepositoryCell.xib */; };
0752F48C21C8D9BA00A30BF2 /* TrendingUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0752F48A21C8D9BA00A30BF2 /* TrendingUserCell.swift */; };
Expand Down Expand Up @@ -364,6 +366,8 @@
073A1F782233F2F000D6F487 /* Search.graphql */ = {isa = PBXFileReference; lastKnownFileType = text; path = Search.graphql; sourceTree = "<group>"; };
074DBBE924489E750062B35F /* CodetabsApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodetabsApi.swift; sourceTree = "<group>"; };
074DBBED2448A0480062B35F /* RepositoryNumberOfLines.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = RepositoryNumberOfLines.json; sourceTree = "<group>"; };
074DBBF02448AF0E0062B35F /* LinesCountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinesCountViewModel.swift; sourceTree = "<group>"; };
074DBBF22448AF220062B35F /* LinesCountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinesCountViewController.swift; sourceTree = "<group>"; };
0752F48621C8D9A800A30BF2 /* TrendingRepositoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingRepositoryCell.swift; sourceTree = "<group>"; };
0752F48721C8D9A800A30BF2 /* TrendingRepositoryCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TrendingRepositoryCell.xib; sourceTree = "<group>"; };
0752F48A21C8D9BA00A30BF2 /* TrendingUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingUserCell.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -756,6 +760,15 @@
path = Events;
sourceTree = "<group>";
};
074DBBEF2448AEBF0062B35F /* Lines Count */ = {
isa = PBXGroup;
children = (
074DBBF22448AF220062B35F /* LinesCountViewController.swift */,
074DBBF02448AF0E0062B35F /* LinesCountViewModel.swift */,
);
path = "Lines Count";
sourceTree = "<group>";
};
0752F49221C8E61E00A30BF2 /* Languages */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -960,6 +973,7 @@
07AD154A227F3D4400FC8109 /* Issue Details */,
07E1B2FE21A44D1700F6EAE3 /* Issues */,
0752F49221C8E61E00A30BF2 /* Languages */,
074DBBEF2448AEBF0062B35F /* Lines Count */,
A0ED264620F76A45004E8137 /* Login */,
07FC33751FFFD47600D53888 /* Main */,
A034AF7121528087004C310B /* Notifications */,
Expand Down Expand Up @@ -2037,6 +2051,7 @@
07D46E5321920029008E5369 /* Content.swift in Sources */,
A088B12921008FDF0093D248 /* WebViewController.swift in Sources */,
A09DE8DD20E7C82E00F6F2BF /* SearchBar.swift in Sources */,
074DBBF32448AF220062B35F /* LinesCountViewController.swift in Sources */,
07E1B30621A44D9D00F6EAE3 /* IssueCellViewModel.swift in Sources */,
A0E2B08A210625D5000DA282 /* SettingSwitchCellViewModel.swift in Sources */,
A09DE8D020E7C05C00F6F2BF /* Kingfisher+Rx.swift in Sources */,
Expand All @@ -2053,6 +2068,7 @@
C762C6831E1D5A7300C09EBD /* UIFont+SwiftHub.swift in Sources */,
07B4AB642190C56E001E9337 /* RepositoryDetailCell.swift in Sources */,
075A55CB228843BC004DF9F7 /* PullRequestCommentsViewController.swift in Sources */,
074DBBF12448AF0E0062B35F /* LinesCountViewModel.swift in Sources */,
A0E2B0782101F789000DA282 /* UsersViewModel.swift in Sources */,
07E1B2F321A4349500F6EAE3 /* Issue.swift in Sources */,
0752F49C21C8E68D00A30BF2 /* RepoLanguageCellViewModel.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions SwiftHub/Application/Navigator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Navigator {
case notifications(viewModel: NotificationsViewModel)
case issues(viewModel: IssuesViewModel)
case issueDetails(viewModel: IssueViewModel)
case linesCount(viewModel: LinesCountViewModel)
case theme(viewModel: ThemeViewModel)
case language(viewModel: LanguageViewModel)
case acknowledgements
Expand Down Expand Up @@ -91,6 +92,7 @@ class Navigator {
case .notifications(let viewModel): return NotificationsViewController(viewModel: viewModel, navigator: self)
case .issues(let viewModel): return IssuesViewController(viewModel: viewModel, navigator: self)
case .issueDetails(let viewModel): return IssueViewController(viewModel: viewModel, navigator: self)
case .linesCount(let viewModel): return LinesCountViewController(viewModel: viewModel, navigator: self)
case .theme(let viewModel): return ThemeViewController(viewModel: viewModel, navigator: self)
case .language(let viewModel): return LanguageViewController(viewModel: viewModel, navigator: self)
case .acknowledgements: return AcknowListViewController()
Expand Down
4 changes: 4 additions & 0 deletions SwiftHub/Managers/AnalyticsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum SwifthubEvent {
case issues(fullname: String)
case source(fullname: String)
case readme(fullname: String)
case linesCount(fullname: String)
}

extension SwifthubEvent: Umbrella.EventType {
Expand All @@ -61,6 +62,7 @@ extension SwifthubEvent: Umbrella.EventType {
case .issues: return "Issues"
case .source: return "Source"
case .readme: return "Readme"
case .linesCount: return "Lines Count"
}
}

Expand Down Expand Up @@ -96,6 +98,8 @@ extension SwifthubEvent: Umbrella.EventType {
return ["Fullname": fullname]
case .readme(let fullname):
return ["Fullname": fullname]
case .linesCount(let fullname):
return ["Fullname": fullname]
default:
return nil
}
Expand Down
10 changes: 5 additions & 5 deletions SwiftHub/Models/Language.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ struct RepoLanguage {
struct LanguageLines: Mappable {

var language: String?
var files: Int?
var lines: Int?
var blanks: Int?
var comments: Int?
var linesOfCode: Int?
var files: String?
var lines: String?
var blanks: String?
var comments: String?
var linesOfCode: String?

init?(map: Map) {}
init() {}
Expand Down
127 changes: 127 additions & 0 deletions SwiftHub/Modules/Lines Count/LinesCountViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//
// LinesCountViewController.swift
// SwiftHub
//
// Created by Sygnoos9 on 4/16/20.
// Copyright © 2020 Khoren Markosyan. All rights reserved.
//

import UIKit
import RxSwift
import RxCocoa
import Charts
import BonMot

class LinesCountViewController: ViewController {

var totalLines: LanguageLines?

lazy var chartView: PieChartView = {
let view = PieChartView()
view.delegate = self
view.usePercentValuesEnabled = false
view.drawSlicesUnderHoleEnabled = true
view.holeRadiusPercent = 0.58
view.transparentCircleRadiusPercent = 0.610
view.chartDescription?.enabled = true
view.setExtraOffsets(left: self.inset, top: self.inset, right: self.inset, bottom: self.inset)

view.drawCenterTextEnabled = true
view.drawHoleEnabled = true
view.rotationEnabled = false
view.highlightPerTapEnabled = true
view.holeColor = UIColor.primaryDark()

let legend = view.legend
// l.horizontalAlignment = .right
// l.verticalAlignment = .top
legend.orientation = .vertical
legend.drawInside = false
legend.textColor = .text()
// l.xEntrySpace = 7
// l.yEntrySpace = 0
// l.yOffset = 0
return view
}()

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
}

override func makeUI() {
super.makeUI()

stackView.addArrangedSubview(chartView)
}

override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? LinesCountViewModel else { return }

let refresh = Observable.of(Observable.just(())).merge()
let input = LinesCountViewModel.Input(refresh: refresh)
let output = viewModel.transform(input: input)

viewModel.loading.asObservable().bind(to: isLoading).disposed(by: rx.disposeBag)

isLoading.subscribe(onNext: { [weak self] (loading) in
loading ? self?.startAnimating(): self?.stopAnimating()
}).disposed(by: rx.disposeBag)

output.items.drive(onNext: { [weak self] (items) in
self?.totalLines = items.filter { $0.language == "Total" }.first
self?.chartView.centerAttributedText = self?.totalLines?.attributetDetail()

let languages = items.filter { $0.language != "Total" }
let languageEntries = languages.map { PieChartDataEntry(value: Double($0.linesOfCode?.int ?? 0), label: $0.language, data: $0) }
let colors = languages.map { $0.language ?? "" }.map { viewModel.color(for: $0) ?? "" }.map { UIColor(hexString: $0) ?? UIColor.random }
let languagesDataSet = PieChartDataSet(entries: languageEntries, label: "Type of Files")
languagesDataSet.colors = colors
let data = PieChartData(dataSet: languagesDataSet)
self?.chartView.data = data

self?.chartView.animate(xAxisDuration: 1.4, easingOption: .easeOutBack)
}).disposed(by: rx.disposeBag)
}
}

extension LinesCountViewController: ChartViewDelegate {
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
if let languageEntry = entry.data as? LanguageLines {
self.chartView.centerAttributedText = languageEntry.attributetDetail()
}
}

func chartValueNothingSelected(_ chartView: ChartViewBase) {
self.chartView.centerAttributedText = totalLines?.attributetDetail()
}
}

extension LanguageLines {
func attributetDetail() -> NSAttributedString? {
var texts: [NSAttributedString] = []

let titleStyle = StringStyle(.font(UIFont.boldSystemFont(ofSize: 15)), .color(.text()))
let valueStyle = StringStyle(.font(UIFont.systemFont(ofSize: 14)), .color(.text()))

let language = (self.language ?? "").styled(with: titleStyle).styled(with: .underline(.single, .text()))
let files = (self.files ?? "").styled(with: valueStyle)
let lines = (self.lines ?? "").styled(with: valueStyle)
let blanks = (self.blanks ?? "").styled(with: valueStyle)
let comments = (self.comments ?? "").styled(with: valueStyle)
let linesOfCode = (self.linesOfCode ?? "").styled(with: valueStyle)

texts.append(NSAttributedString.composed(of: [
language, Special.nextLine,
"Files".styled(with: titleStyle), Special.emSpace, files, Special.nextLine,
"Blanks".styled(with: titleStyle), Special.emSpace, blanks, Special.nextLine,
"Comments".styled(with: titleStyle), Special.emSpace, comments, Special.nextLine,
"Code".styled(with: titleStyle), Special.emSpace, linesOfCode, Special.nextLine,
"Lines".styled(with: titleStyle), Special.emSpace, lines, Special.nextLine
]))

return NSAttributedString.composed(of: texts)
}
}
51 changes: 51 additions & 0 deletions SwiftHub/Modules/Lines Count/LinesCountViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// LinesCountViewModel.swift
// SwiftHub
//
// Created by Sygnoos9 on 4/16/20.
// Copyright © 2020 Khoren Markosyan. All rights reserved.
//

import Foundation
import RxCocoa
import RxSwift

class LinesCountViewModel: ViewModel, ViewModelType {

struct Input {
let refresh: Observable<Void>
}

struct Output {
let items: Driver<[LanguageLines]>
}

let repository: BehaviorRelay<Repository>

init(repository: Repository, provider: SwiftHubAPI) {
self.repository = BehaviorRelay(value: repository)
super.init(provider: provider)
if let fullname = repository.fullname {
analytics.log(.linesCount(fullname: fullname))
}
}

func transform(input: Input) -> Output {

let elements = input.refresh.flatMapLatest { () -> Observable<[LanguageLines]> in
let fullname = self.repository.value.fullname ?? ""
return self.provider.numberOfLines(fullname: fullname)
.trackActivity(self.loading)
.trackError(self.error)
}.asDriver(onErrorJustReturn: [])

return Output(items: elements)
}

func color(for language: String) -> String? {
guard let language = repository.value.languages?.languages.filter({ $0.name == language }).first else {
return nil
}
return language.color
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ class RepositoryViewController: TableViewController {
if let url = viewModel.starHistoryUrl() {
self?.navigator.show(segue: .webController(url), sender: self)
}
case .countLinesOfCodeItem:
if let viewModel = viewModel.viewModel(for: item) as? LinesCountViewModel {
self?.navigator.show(segue: .linesCount(viewModel: viewModel), sender: self)
}
default:
self?.deselectSelectedRow()
}
Expand Down
4 changes: 4 additions & 0 deletions SwiftHub/Modules/Repository Details/RepositoryViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@ class RepositoryViewModel: ViewModel, ViewModelType {
let viewModel = ContentsViewModel(repository: repository.value, content: nil, ref: ref, provider: provider)
return viewModel

case .countLinesOfCodeItem:
let viewModel = LinesCountViewModel(repository: repository.value, provider: provider)
return viewModel

default: return nil
}
return nil
Expand Down

0 comments on commit b59bb7f

Please sign in to comment.