Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Commit 4fb7f73

Browse files
authored
enable adding a PAT from settings (#2566)
1 parent 75de7aa commit 4fb7f73

File tree

9 files changed

+169
-31
lines changed

9 files changed

+169
-31
lines changed

Classes/Settings/Settings.storyboard

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -633,29 +633,50 @@
633633
<scene sceneID="Xjx-IC-OZR">
634634
<objects>
635635
<tableViewController id="Pin-sZ-TSO" customClass="SettingsAccountsViewController" customModule="Freetime" customModuleProvider="target" sceneMemberID="viewController">
636-
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="vrj-05-S8l">
636+
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="55" sectionHeaderHeight="18" sectionFooterHeight="18" id="vrj-05-S8l">
637637
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
638638
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
639639
<color key="backgroundColor" red="0.96470588239999999" green="0.97254901959999995" blue="0.98039215690000003" alpha="1" colorSpace="calibratedRGB"/>
640640
<color key="separatorColor" red="0.73725490199999999" green="0.73333333329999995" blue="0.75686274509999996" alpha="1" colorSpace="calibratedRGB"/>
641641
<prototypes>
642-
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="account" textLabel="ASM-DA-gBk" style="IBUITableViewCellStyleDefault" id="lpN-QC-8cv" customClass="StyledTableCell" customModule="Freetime" customModuleProvider="target">
643-
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
642+
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="account" id="lpN-QC-8cv" customClass="SettingsAccountCell" customModule="Freetime" customModuleProvider="target">
643+
<rect key="frame" x="0.0" y="55.5" width="375" height="55"/>
644644
<autoresizingMask key="autoresizingMask"/>
645645
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lpN-QC-8cv" id="yMj-Hq-uAw">
646-
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
646+
<rect key="frame" x="0.0" y="0.0" width="375" height="54.5"/>
647647
<autoresizingMask key="autoresizingMask"/>
648648
<subviews>
649-
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ASM-DA-gBk">
650-
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
651-
<autoresizingMask key="autoresizingMask"/>
649+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6O9-UD-6n2">
650+
<rect key="frame" x="318" y="19" width="41" height="17"/>
651+
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
652+
<color key="tintColor" red="0.011764705882352941" green="0.40000000000000002" blue="0.83921568627450982" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
653+
<inset key="imageEdgeInsets" minX="-8" minY="0.0" maxX="0.0" maxY="0.0"/>
654+
<state key="normal" title="PAT" image="pencil-small">
655+
<color key="titleColor" red="0.011764705882352941" green="0.40000000000000002" blue="0.83921568627450982" alpha="1" colorSpace="calibratedRGB"/>
656+
</state>
657+
<connections>
658+
<action selector="onPAT:" destination="lpN-QC-8cv" eventType="touchUpInside" id="QUr-5v-MqJ"/>
659+
</connections>
660+
</button>
661+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B9k-QM-ueb">
662+
<rect key="frame" x="16" y="17.5" width="39.5" height="19.5"/>
652663
<fontDescription key="fontDescription" type="system" pointSize="16"/>
653-
<nil key="textColor"/>
654-
<color key="highlightedColor" red="0.14117647058823529" green="0.16078431372549018" blue="0.1803921568627451" alpha="1" colorSpace="calibratedRGB"/>
664+
<color key="textColor" red="0.14117647058823529" green="0.16078431372549018" blue="0.1803921568627451" alpha="1" colorSpace="calibratedRGB"/>
665+
<nil key="highlightedColor"/>
655666
</label>
656667
</subviews>
668+
<constraints>
669+
<constraint firstAttribute="trailing" secondItem="6O9-UD-6n2" secondAttribute="trailing" constant="16" id="HNT-1f-04p"/>
670+
<constraint firstItem="6O9-UD-6n2" firstAttribute="centerY" secondItem="yMj-Hq-uAw" secondAttribute="centerY" id="JAv-gW-2e0"/>
671+
<constraint firstItem="B9k-QM-ueb" firstAttribute="centerY" secondItem="yMj-Hq-uAw" secondAttribute="centerY" id="PAQ-4P-bog"/>
672+
<constraint firstItem="B9k-QM-ueb" firstAttribute="leading" secondItem="yMj-Hq-uAw" secondAttribute="leadingMargin" id="m3G-Lp-6cu"/>
673+
</constraints>
657674
</tableViewCellContentView>
658675
<color key="tintColor" red="0.011764705882352941" green="0.40000000000000002" blue="0.83921568627450982" alpha="1" colorSpace="calibratedRGB"/>
676+
<connections>
677+
<outlet property="patButton" destination="6O9-UD-6n2" id="OLP-Oh-pnn"/>
678+
<outlet property="usernameLabel" destination="B9k-QM-ueb" id="MYz-Ox-FmK"/>
679+
</connections>
659680
</tableViewCell>
660681
</prototypes>
661682
<connections>
@@ -712,5 +733,6 @@
712733
</scenes>
713734
<resources>
714735
<image name="link-external" width="19" height="25"/>
736+
<image name="pencil-small" width="14" height="14"/>
715737
</resources>
716738
</document>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// SettingsAccountCell.swift
3+
// Freetime
4+
//
5+
// Created by Ryan Nystrom on 12/29/18.
6+
// Copyright © 2018 Ryan Nystrom. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
protocol SettingsAccountCellDelegate: class {
12+
func didTapPAT(for cell: SettingsAccountCell)
13+
}
14+
15+
final class SettingsAccountCell: StyledTableCell {
16+
17+
@IBOutlet private weak var usernameLabel: UILabel!
18+
@IBOutlet private weak var patButton: UIButton!
19+
20+
private weak var delegate: SettingsAccountCellDelegate?
21+
22+
@IBAction func onPAT(_ sender: Any) {
23+
delegate?.didTapPAT(for: self)
24+
}
25+
26+
func configure(
27+
with username: String,
28+
delegate: SettingsAccountCellDelegate,
29+
hasPAT: Bool,
30+
isCurrentUser: Bool
31+
) {
32+
usernameLabel.text = username
33+
self.delegate = delegate
34+
patButton.setImage(
35+
UIImage(named: hasPAT ? "pencil-small" : "plus-small")?.withRenderingMode(.alwaysTemplate),
36+
for: .normal
37+
)
38+
accessoryType = isCurrentUser ? .checkmark : .none
39+
}
40+
41+
}

Classes/Settings/SettingsAccountsViewController.swift

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import UIKit
1010
import GitHubAPI
1111
import GitHubSession
1212

13-
final class SettingsAccountsViewController: UITableViewController, GitHubSessionListener {
13+
final class SettingsAccountsViewController: UITableViewController,
14+
GitHubSessionListener,
15+
SettingsAccountCellDelegate {
1416

1517
private var client: Client!
1618
private var sessionManager: GitHubSessionManager!
@@ -33,12 +35,28 @@ final class SettingsAccountsViewController: UITableViewController, GitHubSession
3335
// MARK: Private API
3436

3537
@IBAction func onAdd(_ sender: Any) {
36-
let alert = UIAlertController.configured(
37-
title: NSLocalizedString("Add Account", comment: ""),
38-
message: NSLocalizedString("To sign in with another account, please add a new Personal Access Token with user and repo scopes.", comment: ""),
39-
preferredStyle: .alert
40-
)
38+
showPATAlert()
39+
}
40+
41+
private func showPATAlert(updating session: GitHubUserSession? = nil) {
42+
let title: String
43+
let message: String
44+
45+
if let username = session?.username {
46+
title = username
47+
message = NSLocalizedString(
48+
"Add or update a Personal Access Token with user, repo, and notification scopes.",
49+
comment: ""
50+
)
51+
} else {
52+
title = NSLocalizedString("Add Account", comment: "")
53+
message = NSLocalizedString(
54+
"To sign in with another account, please add a new Personal Access Token with user, repo, and notification scopes.",
55+
comment: ""
56+
)
57+
}
4158

59+
let alert = UIAlertController.configured(title: title, message: message, preferredStyle: .alert)
4260
alert.addTextField { (textField) in
4361
textField.placeholder = NSLocalizedString("Personal Access Token", comment: "")
4462
}
@@ -53,11 +71,11 @@ final class SettingsAccountsViewController: UITableViewController, GitHubSession
5371
case .failure:
5472
self?.handleError()
5573
case .success(let user):
56-
self?.finishLogin(token: token, authMethod: .pat, username: user.data.login)
74+
self?.finishLogin(token: token, username: user.data.login, updateSession: session)
5775
}
5876
}
5977
})
60-
])
78+
])
6179

6280
present(alert, animated: trueUnlessReduceMotionEnabled)
6381
}
@@ -72,10 +90,13 @@ final class SettingsAccountsViewController: UITableViewController, GitHubSession
7290
present(alert, animated: trueUnlessReduceMotionEnabled)
7391
}
7492

75-
private func finishLogin(token: String, authMethod: GitHubUserSession.AuthMethod, username: String) {
76-
sessionManager.focus(
77-
GitHubUserSession(token: token, authMethod: authMethod, username: username)
78-
)
93+
private func finishLogin(token: String, username: String, updateSession: GitHubUserSession?) {
94+
let newUserSession = GitHubUserSession(token: token, authMethod: .pat, username: username)
95+
if let oldUserSession = updateSession {
96+
sessionManager.update(oldUserSession: oldUserSession, newUserSession: newUserSession)
97+
} else {
98+
sessionManager.focus(newUserSession)
99+
}
79100
}
80101

81102
private func updateUserSessions() {
@@ -92,9 +113,15 @@ final class SettingsAccountsViewController: UITableViewController, GitHubSession
92113

93114
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
94115
let cell = tableView.dequeueReusableCell(withIdentifier: "account", for: indexPath)
95-
let session = userSessions[indexPath.row]
96-
cell.textLabel?.text = session.username ?? session.token
97-
cell.accessoryType = sessionManager.focusedUserSession == session ? .checkmark : .none
116+
if let cell = cell as? SettingsAccountCell {
117+
let session = userSessions[indexPath.row]
118+
cell.configure(
119+
with: session.username ?? session.token,
120+
delegate: self,
121+
hasPAT: session.authMethod == .pat,
122+
isCurrentUser: sessionManager.focusedUserSession == session
123+
)
124+
}
98125
return cell
99126
}
100127

@@ -117,4 +144,11 @@ final class SettingsAccountsViewController: UITableViewController, GitHubSession
117144

118145
func didLogout(manager: GitHubSessionManager) {}
119146

147+
// MARK: SettingsAccountCellDelegate
148+
149+
func didTapPAT(for cell: SettingsAccountCell) {
150+
guard let indexPath = tableView.indexPath(for: cell) else { return }
151+
showPATAlert(updating: userSessions[indexPath.row])
152+
}
153+
120154
}

Freetime.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@
302302
298BA0971EC947F100B01946 /* SegmentedControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0951EC947F100B01946 /* SegmentedControlCell.swift */; };
303303
298BA0981EC947F100B01946 /* SegmentedControlSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0961EC947F100B01946 /* SegmentedControlSectionController.swift */; };
304304
298BA09A1EC947FC00B01946 /* SegmentedControlModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0991EC947FC00B01946 /* SegmentedControlModel.swift */; };
305+
298C7E2621D7F56600DD2A60 /* SettingsAccountCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298C7E2521D7F56600DD2A60 /* SettingsAccountCell.swift */; };
305306
2990B9DB218BF23D009865EB /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2990B9DA218BF23D009865EB /* Router.swift */; };
306307
29921BCC1EF624D400C1E848 /* UIFont+MutableTraits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29921BCB1EF624D400C1E848 /* UIFont+MutableTraits.swift */; };
307308
299304691FBA8A88007B9737 /* IssueManagingSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299304681FBA8A88007B9737 /* IssueManagingSectionController.swift */; };
@@ -892,6 +893,7 @@
892893
298BA0951EC947F100B01946 /* SegmentedControlCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlCell.swift; sourceTree = "<group>"; };
893894
298BA0961EC947F100B01946 /* SegmentedControlSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlSectionController.swift; sourceTree = "<group>"; };
894895
298BA0991EC947FC00B01946 /* SegmentedControlModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlModel.swift; sourceTree = "<group>"; };
896+
298C7E2521D7F56600DD2A60 /* SettingsAccountCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAccountCell.swift; sourceTree = "<group>"; };
895897
2990B9DA218BF23D009865EB /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
896898
29921BCB1EF624D400C1E848 /* UIFont+MutableTraits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+MutableTraits.swift"; sourceTree = "<group>"; };
897899
299304681FBA8A88007B9737 /* IssueManagingSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueManagingSectionController.swift; sourceTree = "<group>"; };
@@ -2045,6 +2047,7 @@
20452047
2930988E211F32D100E1178B /* DefaultReactionDetailController.swift */,
20462048
292AD6B1217236C200273D80 /* PushNotificationsDisclaimerViewController.swift */,
20472049
292FF8AB1F2FD3EC009E63F7 /* Settings.storyboard */,
2050+
298C7E2521D7F56600DD2A60 /* SettingsAccountCell.swift */,
20482051
297FB7771F51128A00F2E618 /* SettingsAccountsViewController.swift */,
20492052
29764C131FDC4DB60095FF95 /* SettingsLabel.swift */,
20502053
292FF8AD1F2FD4A8009E63F7 /* SettingsViewController.swift */,
@@ -3239,6 +3242,7 @@
32393242
29EDFE821F661562005BCCEB /* RepositoryReadmeModel.swift in Sources */,
32403243
29EDFE841F661776005BCCEB /* RepositoryReadmeSectionController.swift in Sources */,
32413244
29136BDF200A7A75007317BE /* UIScrollView+LeftRightSafeInset.swift in Sources */,
3245+
298C7E2621D7F56600DD2A60 /* SettingsAccountCell.swift in Sources */,
32423246
986B87381F2CB29700AAB55C /* RepositorySummaryCell.swift in Sources */,
32433247
986B87361F2CB28C00AAB55C /* RepositorySummarySectionController.swift in Sources */,
32443248
2905AFAF1F7357FA0015AE32 /* RepositoryViewController.swift in Sources */,

Local Pods/GitHubSession/GitHubSession/GitHubSessionManager.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ public class GitHubSessionManager: NSObject {
6666
}
6767
}
6868

69+
private func _update(oldUserSession: GitHubUserSession, newUserSession: GitHubUserSession) {
70+
_userSessions.remove(oldUserSession)
71+
_userSessions.insert(newUserSession, at: 0)
72+
save()
73+
74+
let isSwitch = _userSessions.count > 0
75+
for wrapper in listeners {
76+
wrapper.listener?.didFocus(manager: self, userSession: newUserSession, isSwitch: isSwitch)
77+
}
78+
}
79+
6980
// MARK: Public API
7081

7182
public var focusedUserSession: GitHubUserSession? {
@@ -85,13 +96,11 @@ public class GitHubSessionManager: NSObject {
8596
public func focus(
8697
_ userSession: GitHubUserSession
8798
) {
88-
let isSwitch = _userSessions.count > 0
89-
_userSessions.remove(userSession)
90-
_userSessions.insert(userSession, at: 0)
91-
save()
92-
for wrapper in listeners {
93-
wrapper.listener?.didFocus(manager: self, userSession: userSession, isSwitch: isSwitch)
94-
}
99+
_update(oldUserSession: userSession, newUserSession: userSession)
100+
}
101+
102+
public func update(oldUserSession: GitHubUserSession, newUserSession: GitHubUserSession) {
103+
_update(oldUserSession: oldUserSession, newUserSession: newUserSession)
95104
}
96105

97106
public func logout() {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"scale" : "1x"
6+
},
7+
{
8+
"idiom" : "universal",
9+
"filename" : "pencil-small@2x.png",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"filename" : "pencil-small@3x.png",
15+
"scale" : "3x"
16+
}
17+
],
18+
"info" : {
19+
"version" : 1,
20+
"author" : "xcode"
21+
},
22+
"properties" : {
23+
"template-rendering-intent" : "template"
24+
}
25+
}
433 Bytes
Loading
565 Bytes
Loading

Resources/Assets.xcassets/plus-small.imageset/Contents.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@
1818
"info" : {
1919
"version" : 1,
2020
"author" : "xcode"
21+
},
22+
"properties" : {
23+
"template-rendering-intent" : "template"
2124
}
2225
}

0 commit comments

Comments
 (0)