view PR file changes

This commit is contained in:
Ryan Nystrom
2017-08-12 17:29:48 -04:00
parent e54b13b9e1
commit 60ba786162
8 changed files with 295 additions and 3 deletions

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="PPj-lB-M7i">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Files-->
<scene sceneID="tKg-iT-yYb">
<objects>
<tableViewController id="PPj-lB-M7i" customClass="IssueFilesViewController" customModule="Freetime" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="55" sectionHeaderHeight="28" sectionFooterHeight="28" id="KNl-L9-JZB">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<view key="tableFooterView" contentMode="scaleToFill" id="r6V-ei-wRF">
<rect key="frame" x="0.0" y="283" width="375" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="file" rowHeight="55" id="JPL-MS-99q" customClass="IssueFilesTableCell" customModule="Freetime" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="55"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JPL-MS-99q" id="ztL-p0-l2R">
<rect key="frame" x="0.0" y="0.0" width="342" height="54.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="+10 -30" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bJP-Ct-HaV">
<rect key="frame" x="16" y="10" width="51.5" height="16"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Classes/Issues/Files/Files.storyboard" textAlignment="natural" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fJx-UB-1Ql">
<rect key="frame" x="16" y="26" width="326" height="20"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<color key="textColor" red="0.14117647058823529" green="0.16078431372549018" blue="0.1803921568627451" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailing" relation="lessThanOrEqual" secondItem="fJx-UB-1Ql" secondAttribute="trailing" id="ACt-N8-x8n"/>
<constraint firstItem="bJP-Ct-HaV" firstAttribute="bottom" secondItem="fJx-UB-1Ql" secondAttribute="top" id="C2M-42-Mqh"/>
<constraint firstItem="fJx-UB-1Ql" firstAttribute="leading" secondItem="ztL-p0-l2R" secondAttribute="leading" constant="16" id="WX3-Hy-XLn"/>
<constraint firstItem="fJx-UB-1Ql" firstAttribute="centerY" secondItem="ztL-p0-l2R" secondAttribute="centerY" constant="8" id="Z8b-qg-1Gp"/>
<constraint firstItem="bJP-Ct-HaV" firstAttribute="leading" secondItem="ztL-p0-l2R" secondAttribute="leading" constant="16" id="yWZ-tO-BiL"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="changeLabel" destination="bJP-Ct-HaV" id="wiF-o8-2qN"/>
<outlet property="pathLabel" destination="fJx-UB-1Ql" id="tYK-dW-GXZ"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="error" textLabel="tab-0u-kgf" rowHeight="200" style="IBUITableViewCellStyleDefault" id="gPQ-gF-Wvz">
<rect key="frame" x="0.0" y="83" width="375" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="gPQ-gF-Wvz" id="gKa-d5-BG1">
<rect key="frame" x="0.0" y="0.0" width="375" height="199.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Error loading files." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tab-0u-kgf">
<rect key="frame" x="15" y="0.0" width="345" height="199.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.63921568627450975" green="0.66666666666666663" blue="0.69411764705882351" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="PPj-lB-M7i" id="NAL-uh-icg"/>
<outlet property="delegate" destination="PPj-lB-M7i" id="AQM-qF-Rf2"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Files" id="eB1-Tv-RSI"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="sGJ-KI-JZv" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-418.39999999999998" y="151.57421289355324"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,40 @@
//
// GitHubClient+PullRequestFiles.swift
// Freetime
//
// Created by Ryan Nystrom on 8/12/17.
// Copyright © 2017 Ryan Nystrom. All rights reserved.
//
import Foundation
extension GithubClient {
enum FileResult {
case success([File])
case error
}
func fetchFiles(
owner: String,
repo: String,
number: Int,
completion: @escaping (FileResult) -> ()) {
request(Request(
path: "repos/\(owner)/\(repo)/pulls/\(number)/files",
completion: { (response, _) in
if let arr = response.value as? [ [String: Any] ] {
var files = [File]()
for json in arr {
if let file = File(json: json) {
files.append(file)
}
}
completion(.success(files))
} else {
completion(.error)
}
}))
}
}

View File

@@ -0,0 +1,39 @@
//
// IssueFilesTableCell.swift
// Freetime
//
// Created by Ryan Nystrom on 8/12/17.
// Copyright © 2017 Ryan Nystrom. All rights reserved.
//
import UIKit
final class IssueFilesTableCell: UITableViewCell {
@IBOutlet weak var changeLabel: UILabel!
@IBOutlet weak var pathLabel: UILabel!
// MARK: Public API
func configure(path: String, additions: Int, deletions: Int) {
let changeString = NSMutableAttributedString()
var attributes: [String: Any] = [
NSFontAttributeName: Styles.Fonts.secondaryBold,
]
if additions > 0 {
attributes[NSForegroundColorAttributeName] = Styles.Colors.Green.medium.color
changeString.append(NSAttributedString(string: "+\(additions) ", attributes: attributes))
}
if deletions > 0 {
attributes[NSForegroundColorAttributeName] = Styles.Colors.Red.medium.color
changeString.append(NSAttributedString(string: "-\(deletions)", attributes: attributes))
}
changeLabel.attributedText = changeString
pathLabel.text = path
}
}

View File

@@ -0,0 +1,100 @@
//
// IssueFilesViewController.swift
// Freetime
//
// Created by Ryan Nystrom on 8/12/17.
// Copyright © 2017 Ryan Nystrom. All rights reserved.
//
import UIKit
final class IssueFilesViewController: UITableViewController {
private var model: IssueDetailsModel!
private var client: GithubClient!
private var result: GithubClient.FileResult? = nil
override func viewDidLoad() {
super.viewDidLoad()
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(IssueFilesViewController.onRefresh), for: .valueChanged)
tableView.refreshControl = refreshControl
refreshControl.beginRefreshing()
fetch()
}
// MARK: Public API
func configure(model: IssueDetailsModel, client: GithubClient) {
self.model = model
self.client = client
}
// MARK: Private API
func onRefresh() {
fetch()
}
func fetch() {
client.fetchFiles(
owner: model.owner,
repo: model.repo,
number: model.number) { [weak self] (result) in
self?.handle(result: result)
}
}
func handle(result: GithubClient.FileResult) {
self.result = result
tableView.reloadData()
tableView.refreshControl?.endRefreshing()
switch result {
case .success(let files):
let titleFormat = NSLocalizedString("Files (%zi)", comment: "")
title = String.localizedStringWithFormat(titleFormat, files.count)
default: break
}
}
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let result = self.result else { return 0 }
switch result {
case .success(let files): return files.count
case .error: return 1
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let result = self.result else { fatalError("No cells when no data") }
let identifier: String
var file: File? = nil
switch result {
case .success(let files):
identifier = "file"
file = files[indexPath.row]
case .error:
identifier = "error"
}
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
if let cell = cell as? IssueFilesTableCell, let file = file {
cell.configure(path: file.filename, additions: file.additions.intValue, deletions: file.deletions.intValue)
}
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}

View File

@@ -12,9 +12,11 @@ import IGListKit
final class IssueViewFilesSectionController: ListSectionController {
private let issueModel: IssueDetailsModel
private let client: GithubClient
init(issueModel: IssueDetailsModel) {
init(issueModel: IssueDetailsModel, client: GithubClient) {
self.issueModel = issueModel
self.client = client
super.init()
}
@@ -31,6 +33,12 @@ final class IssueViewFilesSectionController: ListSectionController {
override func didSelectItem(at index: Int) {
collectionContext?.deselectItem(at: index, sectionController: self, animated: true)
guard let controller = UIStoryboard(name: "Files", bundle: Bundle.main)
.instantiateInitialViewController() as? IssueFilesViewController
else { return }
controller.configure(model: issueModel, client: client)
viewController?.showDetailViewController(controller, sender: nil)
}
}

View File

@@ -288,7 +288,7 @@ IssueTextActionsViewDelegate {
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
if let object = object as? ListDiffable, object === viewFilesModel {
return IssueViewFilesSectionController(issueModel: model)
return IssueViewFilesSectionController(issueModel: model, client: client)
}
switch object {

View File

@@ -26,6 +26,10 @@
291929471F3EAB250012067B /* IssueDetailsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 291929461F3EAB250012067B /* IssueDetailsModel.swift */; };
291929491F3EAD2E0012067B /* IssueViewFilesSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 291929481F3EAD2E0012067B /* IssueViewFilesSectionController.swift */; };
2919294B1F3EAD890012067B /* IssueViewFilesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2919294A1F3EAD890012067B /* IssueViewFilesCell.swift */; };
2919294D1F3F746B0012067B /* GithubClient+PullRequestFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2919294C1F3F746B0012067B /* GithubClient+PullRequestFiles.swift */; };
2919294F1F3F76A20012067B /* Files.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2919294E1F3F76A20012067B /* Files.storyboard */; };
291929511F3F76B10012067B /* IssueFilesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 291929501F3F76B10012067B /* IssueFilesViewController.swift */; };
291929531F3F9E490012067B /* IssueFilesTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 291929521F3F9E490012067B /* IssueFilesTableCell.swift */; };
292484B81F01CB5C0054FE20 /* SwipeCellKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 292484B71F01CB5C0054FE20 /* SwipeCellKit.framework */; };
292484B91F01CB5C0054FE20 /* SwipeCellKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 292484B71F01CB5C0054FE20 /* SwipeCellKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2928C7881F15D7C50000D06D /* IssueRenamedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2928C7871F15D7C50000D06D /* IssueRenamedModel.swift */; };
@@ -322,6 +326,10 @@
291929461F3EAB250012067B /* IssueDetailsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueDetailsModel.swift; sourceTree = "<group>"; };
291929481F3EAD2E0012067B /* IssueViewFilesSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueViewFilesSectionController.swift; sourceTree = "<group>"; };
2919294A1F3EAD890012067B /* IssueViewFilesCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueViewFilesCell.swift; sourceTree = "<group>"; };
2919294C1F3F746B0012067B /* GithubClient+PullRequestFiles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GithubClient+PullRequestFiles.swift"; sourceTree = "<group>"; };
2919294E1F3F76A20012067B /* Files.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Files.storyboard; sourceTree = "<group>"; };
291929501F3F76B10012067B /* IssueFilesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueFilesViewController.swift; sourceTree = "<group>"; };
291929521F3F9E490012067B /* IssueFilesTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueFilesTableCell.swift; sourceTree = "<group>"; };
292484B71F01CB5C0054FE20 /* SwipeCellKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwipeCellKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2928C7871F15D7C50000D06D /* IssueRenamedModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueRenamedModel.swift; sourceTree = "<group>"; };
2928C7891F15D7E00000D06D /* IssueRenamedCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueRenamedCell.swift; sourceTree = "<group>"; };
@@ -591,6 +599,10 @@
291929431F3EAAAF0012067B /* Files */ = {
isa = PBXGroup;
children = (
2919294E1F3F76A20012067B /* Files.storyboard */,
2919294C1F3F746B0012067B /* GithubClient+PullRequestFiles.swift */,
291929521F3F9E490012067B /* IssueFilesTableCell.swift */,
291929501F3F76B10012067B /* IssueFilesViewController.swift */,
2919294A1F3EAD890012067B /* IssueViewFilesCell.swift */,
291929481F3EAD2E0012067B /* IssueViewFilesSectionController.swift */,
);
@@ -1342,6 +1354,7 @@
buildActionMask = 2147483647;
files = (
29416BF91F1138B700D03E1A /* OauthLogin.storyboard in Resources */,
2919294F1F3F76A20012067B /* Files.storyboard in Resources */,
297AE8821EC0D5C200B44A1F /* LaunchScreen.storyboard in Resources */,
292FF8AC1F2FD3EC009E63F7 /* Settings.storyboard in Resources */,
29EE1C171F3A2E7A0046A54D /* Labels.storyboard in Resources */,
@@ -1497,6 +1510,7 @@
292FCB091EDFCC510026635E /* IssueCommentSummaryModel.swift in Sources */,
290EF5791F06BAF4006A2160 /* NoNewNotificationsSectionController.swift in Sources */,
292FCB151EDFCC510026635E /* IssueLabelsSectionController.swift in Sources */,
291929531F3F9E490012067B /* IssueFilesTableCell.swift in Sources */,
297403D91F18545A00ABA95A /* IssueAssigneesSectionController.swift in Sources */,
292EB08D1F1FF58D0046865D /* IssueMilestoneEventModel.swift in Sources */,
292FCAFC1EDFCC510026635E /* IssueCommentImageModel.swift in Sources */,
@@ -1577,6 +1591,7 @@
29A476A01ED0E6C6005D0953 /* UIColor+Overlay.swift in Sources */,
29F7F05F1F2A839100F6075D /* IssueNeckLoadSectionController.swift in Sources */,
297403D11F184F8D00ABA95A /* IssueAssigneesModel.swift in Sources */,
2919294D1F3F746B0012067B /* GithubClient+PullRequestFiles.swift in Sources */,
292FF8B51F303BD0009E63F7 /* IssuePreviewSectionController.swift in Sources */,
290D2A3D1F044CB20082E6CC /* UIViewController+SmartDeselection.swift in Sources */,
29A08FBD1F12EF7C00C5368E /* IssueReferencedCommitCell.swift in Sources */,
@@ -1675,6 +1690,7 @@
29C1677A1ECA14F700439D62 /* Feed.swift in Sources */,
292FCB171EDFCC510026635E /* IssueLabelSummaryModel.swift in Sources */,
291929491F3EAD2E0012067B /* IssueViewFilesSectionController.swift in Sources */,
291929511F3F76B10012067B /* IssueFilesViewController.swift in Sources */,
98835BD41F1A17EE005BA24F /* Bundle+Version.swift in Sources */,
29FB94301EE752280016E6D4 /* IssueLabeledCell.swift in Sources */,
295C31C71F09E62600521CED /* NotificationNextPageCell.swift in Sources */,

View File

@@ -32,7 +32,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1338</string>
<string>1347</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>