Skip to content

Commit bbde934

Browse files
authored
Merge pull request #11 from codeRIT/peter-profile
Profile Updates, Login refactor
2 parents 6e62b6e + 269c7d0 commit bbde934

8 files changed

Lines changed: 127 additions & 164 deletions

File tree

BrickHack-Mobile.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
31C5F541219B29CD00E3E1AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31C5F540219B29CD00E3E1AF /* AppDelegate.swift */; };
1515
31C5F546219B29CD00E3E1AF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 31C5F544219B29CD00E3E1AF /* Main.storyboard */; };
1616
31C5F548219B29CF00E3E1AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 31C5F547219B29CF00E3E1AF /* Assets.xcassets */; };
17+
D706937323E8F86B004FA788 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = D706937223E8F86B004FA788 /* User.swift */; };
1718
D750E81823DF67360075C639 /* FavoriteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D750E81723DF67360075C639 /* FavoriteButton.swift */; };
1819
D772876C23DFF92800C2D541 /* ScheduleParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D772876B23DFF92800C2D541 /* ScheduleParser.swift */; };
1920
D789978223D652ED0058060A /* ScheduleTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D789978123D652ED0058060A /* ScheduleTableViewController.swift */; };
@@ -51,6 +52,7 @@
5152
31C5F54C219B29CF00E3E1AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5253
31E39209219F765E00F7A3BE /* BrickHack-Mobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "BrickHack-Mobile.entitlements"; sourceTree = "<group>"; };
5354
C029FC28202ED2177D811FF7 /* Pods-BrickHack-Mobile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BrickHack-Mobile.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BrickHack-Mobile/Pods-BrickHack-Mobile.debug.xcconfig"; sourceTree = "<group>"; };
55+
D706937223E8F86B004FA788 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
5456
D750E81723DF67360075C639 /* FavoriteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FavoriteButton.swift; path = "BrickHack-Mobile/Views/FavoriteButton.swift"; sourceTree = SOURCE_ROOT; };
5557
D772876B23DFF92800C2D541 /* ScheduleParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleParser.swift; sourceTree = "<group>"; };
5658
D789978123D652ED0058060A /* ScheduleTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleTableViewController.swift; sourceTree = "<group>"; };
@@ -141,6 +143,7 @@
141143
children = (
142144
D79AA2B723425DFA009C469D /* APIRoutes.swift */,
143145
D772876B23DFF92800C2D541 /* ScheduleParser.swift */,
146+
D706937223E8F86B004FA788 /* User.swift */,
144147
);
145148
path = Models;
146149
sourceTree = "<group>";
@@ -296,6 +299,7 @@
296299
D7D4B037234813A70001DFC5 /* AlertMessage.swift in Sources */,
297300
D7C41E27236383300091C480 /* ResourcesViewController.swift in Sources */,
298301
D789978523D6A4DC0058060A /* ProfileTableViewController.swift in Sources */,
302+
D706937323E8F86B004FA788 /* User.swift in Sources */,
299303
31C5F541219B29CD00E3E1AF /* AppDelegate.swift in Sources */,
300304
D79AA2B823425DFA009C469D /* APIRoutes.swift in Sources */,
301305
31602385220A116000F73F58 /* EventsViewController.swift in Sources */,

BrickHack-Mobile/Base.lproj/Main.storyboard

Lines changed: 42 additions & 48 deletions
Large diffs are not rendered by default.

BrickHack-Mobile/Controllers/EventsViewController.swift

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,15 @@
77
//
88

99
import UIKit
10-
import p2_OAuth2
1110
import TimelineTableViewCell
1211

1312
class EventsViewController: UIViewController { //UserDataHandler {
1413

1514

1615
// MARK: UI
17-
18-
1916

2017
// General properties
21-
// @FIXME When login works
22-
// var oauthGrant: OAuth2ImplicitGrant!
23-
// var userID: Int!
18+
var currentUser: User!
2419

2520
override func viewDidLoad() {
2621
super.viewDidLoad()
@@ -45,11 +40,8 @@ class EventsViewController: UIViewController { //UserDataHandler {
4540

4641
// @FIXME: Fill using user data once login is working
4742
// (either here or in helper function or in previous VC)
48-
tableVC.nameLabel.text = "Aanya Schroeder"
49-
tableVC.schoolLabel.text = "University of Buffalo"
50-
51-
// @TODO: Emoji picker for ImageView? Don't think backend supports images atm.
52-
43+
tableVC.nameLabel.text = currentUser.firstName + " " + currentUser.lastName
44+
tableVC.schoolLabel.text = "Unknown School"
5345

5446
}
5547
}

BrickHack-Mobile/Controllers/LoginViewController.swift

Lines changed: 41 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ class LoginViewController: UIViewController {
6565
print("Authorization successful.")
6666

6767
// If login is successful, continue to main app
68-
// @FIXME: "NavController on SFViewController, whose view is not in the window hierarchy!"
6968
self.loginFlow()
7069

7170
}
@@ -89,6 +88,9 @@ class LoginViewController: UIViewController {
8988
"redirect_uris": ["brickhack-ios://oauth/callback"],
9089
"scope": "Access-your-bricks"] as OAuth2JSON)
9190

91+
// User model instance
92+
var currentUser: User?
93+
9294
// @TODO: Nonexistent value is 0 by default, maybe wrap somehow to nil?
9395
var userID: Int {
9496
get {
@@ -106,7 +108,9 @@ class LoginViewController: UIViewController {
106108
if hasInternetAccess() {
107109

108110
// Only continue automatically if authenticated, AND user data is persisted
109-
if oauthGrant.hasUnexpiredAccessToken() && userID != 0 {
111+
if oauthGrant.hasUnexpiredAccessToken() && currentUser != nil {
112+
113+
print("currentUser: \(currentUser)")
110114

111115
// Continue to main app if authorized, don't show spinner
112116
self.performSegue(withIdentifier: "authSuccessSegue", sender: self)
@@ -120,7 +124,18 @@ class LoginViewController: UIViewController {
120124
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
121125
if (segue.identifier == "authSuccessSegue") {
122126

127+
// Make the destination be fullscreen
128+
segue.destination.modalPresentationStyle = .fullScreen
129+
130+
// Pass data forward (temp to main screen)
131+
if let eventsVC = segue.destination as? EventsViewController {
132+
print("passed user object")
133+
eventsVC.currentUser = self.currentUser
134+
}
135+
136+
123137
// Check for MainTabBarController (skip through nav controller)
138+
// Note: not used!
124139
if let tabVC = segue.destination.children.first as? MainTabBarController {
125140

126141
// Check if valid user (on error, user will reauth)
@@ -141,19 +156,10 @@ class LoginViewController: UIViewController {
141156

142157
func loginFlow() {
143158

144-
// Generate signed request for userID
145-
let idRequest = signURLRequest(withRoute: Routes.currentUser)
146-
guard let signedIDRequest = idRequest else {
147-
DispatchQueue.main.async {
148-
MessageHandler.showAuthSigningError()
149-
}
150-
return
151-
}
152-
153159
// Generate signed request for username
154160
// (user id is added in network chain)
155161
let nameRequest = signURLRequest(withRoute: Routes.questionnaire)
156-
guard var signedNameRequest = nameRequest else {
162+
guard let signedNameRequest = nameRequest else {
157163
DispatchQueue.main.async {
158164
MessageHandler.showAuthSigningError()
159165
}
@@ -165,10 +171,9 @@ class LoginViewController: UIViewController {
165171
SVProgressHUD.show()
166172
}
167173

168-
// Networking!
169-
// First, grab the user id from teh server.
170-
URLSession.shared.dataTask(with: signedIDRequest) { (data, response, error) in
174+
URLSession.shared.dataTask(with: signedNameRequest) { (data, response, error) in
171175

176+
// MARK: Error checking
172177
guard error == nil else {
173178
DispatchQueue.main.async {
174179
MessageHandler.showNetworkError(withText: error!.localizedDescription)
@@ -179,112 +184,53 @@ class LoginViewController: UIViewController {
179184

180185
guard let data = data else {
181186
DispatchQueue.main.async {
182-
MessageHandler.showNetworkError(withText: error!.localizedDescription)
187+
MessageHandler.showUserDataParsingError()
183188
SVProgressHUD.dismiss()
184189
}
185190
return
186191
}
187192

188-
// Convert server data to JSON
189-
var json: [String: Any]
190-
do {
191-
json = try JSON(data: data).dictionaryObject!
192-
} catch {
193+
// Check response code
194+
guard let httpResponse = response as? HTTPURLResponse else {
193195
DispatchQueue.main.async {
194-
MessageHandler.showNetworkError(withText: error.localizedDescription)
196+
MessageHandler.showNetworkError(withText: "Invalid response code")
195197
SVProgressHUD.dismiss()
196198
}
197199
return
198200
}
199201

200-
// Grab our integer from it
201-
let userIDConverted = json["resource_owner_id"] as? Int
202-
203-
// Check cast
204-
guard let userID = userIDConverted else {
202+
guard httpResponse.statusCode != 404 else {
205203
DispatchQueue.main.async {
206-
MessageHandler.showNetworkError(withText: error!.localizedDescription)
204+
MessageHandler.showNetworkError(withText: "User account not found")
207205
SVProgressHUD.dismiss()
208206
}
209207
return
210208
}
211209

212-
// Save userID
213-
UserDefaults.standard.set(userID, forKey: "userID")
214-
print("userID: \(userID)")
215-
216-
// @FIXME: Bypass name functionality for now
217-
// Segue to main app
218-
DispatchQueue.main.async {
219-
self.performSegue(withIdentifier: "authSuccessSegue", sender: self)
220-
}
221-
222-
// Now that we have the user ID, append it and
223-
// request the user info.
224-
signedNameRequest.url?.appendPathComponent("\(userID).json")
225-
signedNameRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
226210

227-
// Note: spinner is still visible!
228-
URLSession.shared.dataTask(with: signedNameRequest) { (data, response, error) in
211+
// MARK: Data conversion
229212

230-
guard error == nil else {
231-
DispatchQueue.main.async {
232-
MessageHandler.showNetworkError(withText: error!.localizedDescription)
233-
SVProgressHUD.dismiss()
234-
}
235-
return
236-
}
237-
238-
guard let data = data else {
239-
DispatchQueue.main.async {
240-
MessageHandler.showUserDataParsingError()
241-
SVProgressHUD.dismiss()
242-
}
243-
return
244-
}
245-
246-
// Check response code
247-
if let httpResponse = response as? HTTPURLResponse {
248-
DispatchQueue.main.async {
249-
MessageHandler.showNetworkError(withText: httpResponse.statusString)
250-
SVProgressHUD.dismiss()
251-
}
252-
return
253-
}
254-
255-
// Convert server data to JSON
256-
var json: JSON
257-
258-
do {
259-
json = try JSON(data: data, options: .allowFragments)
260-
} catch {
261-
DispatchQueue.main.async {
262-
MessageHandler.showUserDataParsingError(withText: "Unable to convert JSON")
263-
SVProgressHUD.dismiss()
264-
}
265-
return
266-
}
267-
268-
// @FIXME
269-
// Hello, Developer.
270-
// At this point, the code should have errored out.
271-
// The backend has not implemented the functionality needed for the preivous code to work.
272-
// But, just in case something happens, this should do it.
213+
// Convert server data to our User object
214+
do {
215+
self.currentUser = try JSONDecoder().decode(User.self, from: data)
216+
} catch (let error) {
273217
DispatchQueue.main.async {
274-
MessageHandler.showUserDataParsingError()
218+
print("parsing error: \(error)")
219+
MessageHandler.showUserDataParsingError(withText: "Unable to convert JSON")
275220
SVProgressHUD.dismiss()
276221
}
277-
278222
return
223+
}
279224

225+
// Now that we have the user data, go to the main screen,
226+
// passing the data forward!
227+
DispatchQueue.main.async {
228+
SVProgressHUD.dismiss()
229+
self.performSegue(withIdentifier: "authSuccessSegue", sender: self)
230+
}
280231

281-
// This is some debugging code for the time being, that will not be reached:
282-
let contents = String(data: data, encoding: .ascii)
283-
print(json)
284-
print(contents!)
285-
print("JSON data:")
232+
return
286233

287-
}.resume()
288234
}.resume()
289235

290236
}

BrickHack-Mobile/Controllers/ProfileTableViewController.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class ProfileTableViewController: UITableViewController {
1616
// MARK: IBOutlets
1717
@IBOutlet weak var nameLabel: UILabel!
1818
@IBOutlet weak var schoolLabel: UILabel!
19-
@IBOutlet weak var profileImage: UIImageView!
2019

2120
override func viewDidLoad() {
2221
super.viewDidLoad()

BrickHack-Mobile/Controllers/ScheduleTableViewController.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class ScheduleTableViewController: UITableViewController {
6666
// which runs each minute (while the screen is visible) and updates the timeline view if necessary.
6767
// @TODO: Change from 60s to change on every hour, effectively caching the result
6868
// (or maybe don't bother with cache and do it every time the view is loaded / minimal persistance)
69-
scheduleTimer = Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(refreshTimeline), userInfo: nil, repeats: true)
69+
scheduleTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(refreshTimeline), userInfo: nil, repeats: true)
7070
scheduleTimer.fire()
7171
}
7272

@@ -80,7 +80,6 @@ class ScheduleTableViewController: UITableViewController {
8080
override func numberOfSections(in tableView: UITableView) -> Int {
8181
// This property is stored in the ScheduleParser,
8282
// as this is pretty much the only time it's needed here.
83-
print("from sec num: \(ScheduleParser.sectionCount)")
8483
return ScheduleParser.sectionCount
8584
}
8685

BrickHack-Mobile/Models/APIRoutes.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,10 @@ import Alamofire
1515
// For local development, route through ngrok,
1616
// and set App Transpot to allow localhost in info.plist
1717
struct Routes {
18-
static let environment = "https://apply.brickhack.io"
18+
static let environment = "https://hm.baudouin.io"
1919
static let authorize = "\(environment)/oauth/authorize"
2020
static let currentUser = "\(environment)/oauth/token/info"
21-
static let questionnaire = "\(environment)/manage/questionnaires" // :id
22-
static let todaysStatsData = "\(environment)/manage/dashboard/todays_stats_data"
23-
static let trackableTags = "\(environment)/manage/trackable_tags.json"
24-
static let trackableEvents = "\(environment)/manage/trackable_events.json"
25-
static let editTrackableEvent = "\(environment)/manage/trackable_events/"
26-
static let trackableEventsByUser = "\(environment)/manage/trackable_events.json?trackable_event[user_id]="
21+
static let questionnaire = "\(environment)/apply.json"
2722
static let resetPassword = "\(environment)/users/password/new"
2823

2924
}

BrickHack-Mobile/Models/User.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// User.swift
3+
// BrickHack-Mobile
4+
//
5+
// Created by Peter Kos on 2/3/20.
6+
// Copyright © 2020 codeRIT. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
// User model
12+
struct User: Decodable {
13+
14+
var firstName: String
15+
var lastName: String
16+
// @TODO: School name
17+
18+
init(firstName: String, lastName: String) {
19+
self.firstName = firstName
20+
self.lastName = lastName
21+
}
22+
23+
init() {
24+
self.init(firstName: "", lastName: "")
25+
}
26+
27+
// Map underscored JSON values into camelCase in this code
28+
private enum CodingKeys: String, CodingKey {
29+
case firstName = "first_name"
30+
case lastName = "last_name"
31+
}
32+
}
33+
34+

0 commit comments

Comments
 (0)