Skip to content

Commit 94afbb6

Browse files
authored
Merge pull request #292 from TaskarCenterAtUW/task-2408-Onboard-flow-Aviv-ScouteRoute-changes
Implemented deep linking with avivscr schema
2 parents 2f9a546 + d3fc23d commit 94afbb6

File tree

15 files changed

+157
-29
lines changed

15 files changed

+157
-29
lines changed

GoInfoGame/GoInfoGame.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@
519519
C77AACA52E447364006713B2 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
520520
C77EEBCE2DE59D3200494CB4 /* UndoMerge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UndoMerge.swift; sourceTree = "<group>"; };
521521
C78737AE2E4C9E3200289D13 /* FloatingLabelTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingLabelTextField.swift; sourceTree = "<group>"; };
522+
C787EF162E9676CC00BEF0A6 /* GoInfoGame.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GoInfoGame.entitlements; sourceTree = "<group>"; };
522523
C7927B532E42363000A7A34E /* XCAssets+Generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCAssets+Generated.swift"; sourceTree = "<group>"; };
523524
C7A922242E45C36D00705E21 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
524525
C7BA83532E3C9C3600755BA7 /* QuestSyncButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = QuestSyncButton.swift; path = GoInfoGame/UI/Map/QuestSyncButton.swift; sourceTree = SOURCE_ROOT; };
@@ -1561,6 +1562,7 @@
15611562
FAD5C4F12AFCBE700040C61A /* GoInfoGame */ = {
15621563
isa = PBXGroup;
15631564
children = (
1565+
C787EF162E9676CC00BEF0A6 /* GoInfoGame.entitlements */,
15641566
FA18CADE2CC7CD46008247F2 /* Kartaview */,
15651567
FAFDA2092C6F589900ECEAE9 /* UserProfile */,
15661568
FAFDA1FB2C6D321500ECEAE9 /* Login */,
@@ -2893,6 +2895,7 @@
28932895
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
28942896
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
28952897
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
2898+
CODE_SIGN_ENTITLEMENTS = GoInfoGame/GoInfoGame.entitlements;
28962899
CODE_SIGN_IDENTITY = "Apple Development";
28972900
CODE_SIGN_STYLE = Automatic;
28982901
CURRENT_PROJECT_VERSION = 1;
@@ -2958,6 +2961,7 @@
29582961
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
29592962
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
29602963
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
2964+
CODE_SIGN_ENTITLEMENTS = GoInfoGame/GoInfoGame.entitlements;
29612965
CODE_SIGN_IDENTITY = "Apple Development";
29622966
CODE_SIGN_STYLE = Automatic;
29632967
CURRENT_PROJECT_VERSION = 1;

GoInfoGame/GoInfoGame.xcodeproj/xcshareddata/xcschemes/GoInfoGame.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
</Testables>
6060
</TestAction>
6161
<LaunchAction
62-
buildConfiguration = "Debug"
62+
buildConfiguration = "Release"
6363
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
6464
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
6565
launchStyle = "0"

GoInfoGame/GoInfoGame/AppDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
6363
}
6464

6565
private func refreshToken() {
66-
TokenRefresher.shared.refreshToken { status in
66+
TokenRefresher.shared.refreshToken { status, _ in
6767
print("Refresh status \(status)")
6868
if status == false {
6969
DispatchQueue.main.async {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.developer.associated-domains</key>
6+
<array>
7+
<string>applinks:www.srikanthvoonna.co.in</string>
8+
<string>applinks:srikanthvoonna.co.in</string>
9+
<string>applinks:portal-dev.tdei.us</string>
10+
</array>
11+
</dict>
12+
</plist>

GoInfoGame/GoInfoGame/Helpers/Generated/Strings+Generated.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ internal enum L10n {
2121
internal static let composeMessage = L10n.tr("Localizable", "Compose message", fallback: "Compose message")
2222
/// Don't show again for this session
2323
internal static let dontShowAgain = L10n.tr("Localizable", "dont_show_again", fallback: "Don't show again for this session")
24+
/// Invalid credentials
25+
internal static let invalidCredentials = L10n.tr("Localizable", "Invalid credentials", fallback: "Invalid credentials")
2426
/// My Profile
2527
internal static let myProfile = L10n.tr("Localizable", "My Profile", fallback: "My Profile")
2628
/// OTHER ANSWERS...

GoInfoGame/GoInfoGame/Login/SessionManager.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import UIKit
1212
final class SessionManager: ObservableObject {
1313
static let shared = SessionManager()
1414
private init() {
15-
username = KeychainManager.load(.username, for: APIConfiguration.shared.environment)
1615
}
1716

1817
@Published var isLoginSuccessful: Bool = false
1918
@Published var hasLoginFailed: Bool = false
20-
private(set) var username: String? = nil
19+
var username: String? {
20+
return KeychainManager.load(.username, for: APIConfiguration.shared.environment)
21+
}
2122

2223
var lastLoginPassword: String?
2324

@@ -36,7 +37,6 @@ final class SessionManager: ObservableObject {
3637
DispatchQueue.main.async { [weak self] in
3738
switch result {
3839
case .success(let response):
39-
self?.username = username
4040
_ = KeychainManager.save(key: "accessToken", data: response.accessToken)
4141
self?.lastLoginPassword = password
4242
UserDefaults.standard.setValue(response.expiresIn, forKey: "accessToken_expire_in")
@@ -53,7 +53,7 @@ final class SessionManager: ObservableObject {
5353
print("Login failed:", error)
5454
self?.isLoginSuccessful = false
5555
self?.hasLoginFailed = true
56-
completion(false, "Invalid credentials")
56+
completion(false, L10n.Localizable.invalidCredentials)
5757
}
5858
}
5959
}

GoInfoGame/GoInfoGame/Login/View/PosmLogin.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ struct PosmLoginView: View {
6969
selectedEnvironment = environment
7070
APIConfiguration.shared.environment = environment
7171
}) {
72-
Text(environment.rawValue)
72+
Text(environment.displayString())
7373
}
7474
}
7575
} label: {
7676
HStack {
77-
Text("Environment: \(selectedEnvironment.rawValue)")
77+
Text("Environment: \(selectedEnvironment.displayString())")
7878
.foregroundColor(.black)
7979
Image(systemName: "chevron.down")
8080
}

GoInfoGame/GoInfoGame/Login/ViewModel/PosmLoginViewModel.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,70 @@ class PosmLoginViewModel: ObservableObject {
100100
self.isLoginSuccess = true
101101
}
102102
}
103+
104+
func loginWithRefreshToken(refreshToken: String) {
105+
isLoading = true
106+
107+
TokenRefresher.shared.refreshToken(refreshToken: refreshToken) { [weak self] result, error in
108+
DispatchQueue.main.async { [weak self, result, error] in
109+
self?.isLoading = false
110+
111+
self?.loggedIn = result
112+
self?.isLoginSuccess = result
113+
self?.hasLoginFailed = !result
114+
if let _ = error {
115+
self?.loginFailedMessage = L10n.Localizable.invalidCredentials
116+
}
117+
118+
guard result,
119+
let accessToken = KeychainManager.load(key: "accessToken"),
120+
let email = self?.emailIDfromJWT(token: accessToken) else {
121+
return
122+
}
123+
_ = KeychainManager.save(.username, value: email, for: APIConfiguration.shared.environment)
124+
}
125+
}
126+
}
127+
128+
private func emailIDfromJWT(token: String) -> String? {
129+
let segments = token.components(separatedBy: ".")
130+
guard segments.count == 3 else {
131+
debugPrint("Invalid JWT format.")
132+
return nil
133+
}
134+
135+
let payloadSegment = segments[1]
136+
var base64 = payloadSegment
137+
.replacingOccurrences(of: "-", with: "+")
138+
.replacingOccurrences(of: "_", with: "/")
139+
140+
let remainingLength = base64.count % 4
141+
if remainingLength > 0 {
142+
let padding = String(repeating: "=", count: 4 - remainingLength)
143+
base64 = base64 + padding
144+
}
145+
146+
guard let data = Data(base64Encoded: base64) else {
147+
debugPrint("Could not Base64URL decode the payload.")
148+
return nil
149+
}
150+
151+
do {
152+
guard let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
153+
debugPrint("Could not parse payload data as JSON object.")
154+
return nil
155+
}
156+
157+
if let email = jsonObject["email"] as? String {
158+
return email
159+
} else {
160+
debugPrint("Email claim not found in JWT payload, or is not a String.")
161+
return nil
162+
}
163+
} catch {
164+
debugPrint("Error parsing JSON payload: \(error)")
165+
return nil
166+
}
167+
}
103168
}
104169

GoInfoGame/GoInfoGame/Network/APIConfiguration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class APIConfiguration {
1818
let savedEnvironment = APIEnvironment(rawValue: savedValue) {
1919
return savedEnvironment
2020
}
21-
return .staging // default value
21+
return .production // default value
2222
}
2323
set {
2424
UserDefaults.standard.set(newValue.rawValue, forKey: environmentKey)

GoInfoGame/GoInfoGame/Network/APIEnvironment.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import Foundation
99

1010
enum APIEnvironment: String, CaseIterable {
11-
case development = "Development"
12-
case staging = "Staging"
13-
case production = "Production"
11+
case development = "dev"
12+
case staging = "stage"
13+
case production = "prod"
1414
// case osm = "OSM"
1515
//
1616
var workspaceBaseURL: String {
@@ -67,4 +67,15 @@ enum APIEnvironment: String, CaseIterable {
6767
return "https://api.openstreetcam.org/1.0"
6868
}
6969
}
70+
71+
func displayString() -> String {
72+
switch self {
73+
case .development:
74+
return "Development"
75+
case .staging:
76+
return "Staging"
77+
case .production:
78+
return "Production"
79+
}
80+
}
7081
}

0 commit comments

Comments
 (0)