Support universal link (to report)
This commit is contained in:
parent
717138bb3e
commit
7a090e8827
@ -34,6 +34,7 @@
|
||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
|
||||
7A11474B23FF368B00B424AF /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474A23FF368B00B424AF /* Settings.swift */; };
|
||||
7A15051224DB3E3000F39631 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A15051124DB3E3000F39631 /* AnyEncodable.swift */; };
|
||||
7A1DC38E2517ED98002E9C99 /* BlockBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1DC38D2517ED98002E9C99 /* BlockBarButtonItem.swift */; };
|
||||
7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A21112924FC3D7E003BBF6F /* AudioEngine.swift */; };
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADC6249D43210035F39E /* RegionsController.swift */; };
|
||||
7A27ADF3249F8B650035F39E /* RecordsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF2249F8B650035F39E /* RecordsController.swift */; };
|
||||
@ -129,6 +130,7 @@
|
||||
7A11474A23FF368B00B424AF /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
||||
7A15051124DB3E3000F39631 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
||||
7A1DC38D2517ED98002E9C99 /* BlockBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockBarButtonItem.swift; sourceTree = "<group>"; };
|
||||
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioEngine.swift; sourceTree = "<group>"; };
|
||||
7A27ADC6249D43210035F39E /* RegionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegionsController.swift; sourceTree = "<group>"; };
|
||||
7A27ADF2249F8B650035F39E /* RecordsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordsController.swift; sourceTree = "<group>"; };
|
||||
@ -415,6 +417,7 @@
|
||||
7AB67E8D2435D1A000258F61 /* CustomButton.swift */,
|
||||
7A1090EB24A4E3E100B4F0B2 /* CellProgressView.swift */,
|
||||
7ADF6C96250F41B000F237B2 /* PNKeyboard.swift */,
|
||||
7A1DC38D2517ED98002E9C99 /* BlockBarButtonItem.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -562,6 +565,7 @@
|
||||
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
|
||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
|
||||
7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */,
|
||||
7A1DC38E2517ED98002E9C99 /* BlockBarButtonItem.swift in Sources */,
|
||||
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */,
|
||||
7A27ADF3249F8B650035F39E /* RecordsController.swift in Sources */,
|
||||
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */,
|
||||
|
||||
@ -73,10 +73,10 @@
|
||||
filePath = "AutoCat/Utils/Api.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "228"
|
||||
endingLineNumber = "228"
|
||||
startingLineNumber = "232"
|
||||
endingLineNumber = "232"
|
||||
landmarkName = "add(event:to:)"
|
||||
landmarkType = "7">
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
|
||||
@ -13,6 +13,7 @@ enum QuickAction {
|
||||
case check
|
||||
case checkNumber(String, VehicleEvent?)
|
||||
case addVoiceRecord
|
||||
case openReport(String)
|
||||
}
|
||||
|
||||
@UIApplicationMain
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
<string>applinks:auto.aliencat.pro</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
|
||||
@ -99,6 +99,12 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
|
||||
case .addVoiceRecord:
|
||||
self.tabBarController?.selectedIndex = 1
|
||||
break
|
||||
case .openReport(let number):
|
||||
ad.quickAction = .none
|
||||
if let sd = self.view.window?.windowScene?.delegate as? SceneDelegate {
|
||||
sd.openReport(with: number)
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@ -421,7 +421,7 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
|
||||
let shareLink = UIAlertAction(title: "As link", style: .default) { _ in
|
||||
guard let vehicle = self.vehicle else { return }
|
||||
|
||||
if let jwt = try? JWT.generate(for: vehicle.number), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) {
|
||||
if let jwt = try? JWT<EmptyPayload>.generate(for: vehicle.number), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) {
|
||||
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
||||
controller.popoverPresentationController?.barButtonItem = sender
|
||||
self.present(controller, animated: true)
|
||||
|
||||
@ -14,7 +14,7 @@ class SettingsController: FormViewController {
|
||||
}
|
||||
<<< LabelRow("GoogleAccount") { row in
|
||||
row.title = "Google"
|
||||
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT(string: jwtString) {
|
||||
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT<FirebasePayload>(string: jwtString) {
|
||||
row.value = jwt.payload.email
|
||||
} else {
|
||||
row.value = "Log In"
|
||||
@ -92,7 +92,7 @@ class SettingsController: FormViewController {
|
||||
}
|
||||
|
||||
func displayLogoutSheet(for row: String) {
|
||||
guard let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT(string: jwtString) else { return }
|
||||
guard let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT<FirebasePayload>(string: jwtString) else { return }
|
||||
|
||||
let sheet = UIAlertController(title: jwt.payload.name, message: "You are currently signed in with email \(jwt.payload.email). It will help to gather more data about vehicles.", preferredStyle: .actionSheet)
|
||||
|
||||
@ -116,7 +116,7 @@ class SettingsController: FormViewController {
|
||||
if let vc = storyboard.instantiateViewController(identifier: "GoogleSignInController") as? GoogleSignInController {
|
||||
vc.completion = {
|
||||
guard let googleRow = self.form.rowBy(tag: "GoogleAccount") as? LabelRow else { return }
|
||||
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT(string: jwtString) {
|
||||
if let jwtString = Settings.shared.user.firebaseIdToken, let jwt = JWT<FirebasePayload>(string: jwtString) {
|
||||
googleRow.value = jwt.payload.email
|
||||
} else {
|
||||
googleRow.value = "Log In"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import UIKit
|
||||
import os.log
|
||||
import AVFoundation
|
||||
import RxSwift
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
@ -17,6 +18,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
if activity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
|
||||
ad.quickAction = .addVoiceRecord
|
||||
}
|
||||
|
||||
if let url = activity.webpageURL {
|
||||
if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
|
||||
if let jwt = JWT<NumberPayload>(string: token) {
|
||||
ad.quickAction = .openReport(jwt.payload.plateNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.window = UIWindow(windowScene: windowScene)
|
||||
@ -104,6 +113,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
if userActivity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
|
||||
self.handleAddVoiceRecordAction()
|
||||
}
|
||||
|
||||
if let url = userActivity.webpageURL {
|
||||
if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
|
||||
if let jwt = JWT<NumberPayload>(string: token) {
|
||||
self.openReport(with: jwt.payload.plateNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleAddVoiceRecordAction() {
|
||||
@ -124,5 +141,23 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func openReport(with number: String) {
|
||||
guard let rootController = self.window?.rootViewController else { return }
|
||||
|
||||
IHProgressHUD.show()
|
||||
_ = Api.getReport(for: number).observeOn(MainScheduler.instance).subscribe { vehicle in
|
||||
let sb = UIStoryboard(name: "Main", bundle: nil)
|
||||
let controller = sb.instantiateViewController(identifier: "ReportController") as ReportController
|
||||
controller.vehicle = vehicle
|
||||
let nav = UINavigationController(rootViewController: controller)
|
||||
nav.modalPresentationStyle = .fullScreen
|
||||
controller.navigationItem.leftBarButtonItem = BlockBarButtonItem(barButtonSystemItem: .close) { _ in nav.dismiss(animated: true) }
|
||||
rootController.present(nav, animated: true)
|
||||
IHProgressHUD.dismiss()
|
||||
} onError: { error in
|
||||
IHProgressHUD.show(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ class Api {
|
||||
// MARK: - Firebase API
|
||||
|
||||
public static func refreshFbToken() -> Single<Void> {
|
||||
guard let token = Settings.shared.user.firebaseIdToken, let refreshToken = Settings.shared.user.firebaseRefreshToken, let jwt = JWT(string: token), jwt.expired else {
|
||||
guard let token = Settings.shared.user.firebaseIdToken, let refreshToken = Settings.shared.user.firebaseRefreshToken, let jwt = JWT<FirebasePayload>(string: token), jwt.expired else {
|
||||
return .just(())
|
||||
}
|
||||
|
||||
@ -208,6 +208,10 @@ class Api {
|
||||
}
|
||||
}
|
||||
|
||||
public static func getReport(for number: String) -> Single<Vehicle> {
|
||||
return self.makeGetRequest(api: "vehicles/report", params: ["number": number])
|
||||
}
|
||||
|
||||
public static func getBrands() -> Single<[String]> {
|
||||
return self.makeEmptyGetRequest(api: "vehicles/brands")
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ import Foundation
|
||||
enum Constants {
|
||||
static var baseUrl: String {
|
||||
#if DEBUG
|
||||
//return "http://127.0.0.1:3000/"
|
||||
return "http://127.0.0.1:3000/"
|
||||
//return "http://192.168.1.67:3000/"
|
||||
return "https://vps.aliencat.pro:8443/"
|
||||
//return "https://vps.aliencat.pro:8443/"
|
||||
#else
|
||||
return "https://vps.aliencat.pro:8443/"
|
||||
#endif
|
||||
|
||||
@ -61,15 +61,28 @@ extension String {
|
||||
}
|
||||
}
|
||||
|
||||
struct JwtPayload: Codable {
|
||||
var email: String
|
||||
var name: String
|
||||
var exp: Int
|
||||
protocol JwtPayload: Codable {
|
||||
var exp: Int { get }
|
||||
}
|
||||
|
||||
class JWT {
|
||||
extension JwtPayload {
|
||||
var exp: Int { 0 }
|
||||
}
|
||||
|
||||
struct EmptyPayload: JwtPayload { }
|
||||
|
||||
struct FirebasePayload: JwtPayload {
|
||||
var email: String
|
||||
var name: String
|
||||
}
|
||||
|
||||
struct NumberPayload: JwtPayload {
|
||||
var plateNumber: String
|
||||
}
|
||||
|
||||
class JWT<T> where T: JwtPayload {
|
||||
private var jwt: String
|
||||
public let payload: JwtPayload
|
||||
public let payload: T
|
||||
public var expired: Bool {
|
||||
return TimeInterval(self.payload.exp) < Date().timeIntervalSince1970
|
||||
}
|
||||
@ -80,13 +93,14 @@ class JWT {
|
||||
let parts = string.split(separator: ".")
|
||||
if parts.count == 3 {
|
||||
var payloadStr = String(parts[1])
|
||||
if (payloadStr.count % 2 != 0) {
|
||||
payloadStr += String(repeating: "=", count: (payloadStr.count % 2))
|
||||
if (payloadStr.count % 4 != 0) {
|
||||
payloadStr += String(repeating: "=", count: (payloadStr.count % 4))
|
||||
}
|
||||
if let json = Data(base64Encoded: payloadStr, options: [.ignoreUnknownCharacters]) {
|
||||
if let resp = try? JSONDecoder().decode(JwtPayload.self, from: json) {
|
||||
self.payload = resp
|
||||
} else {
|
||||
do {
|
||||
self.payload = try JSONDecoder().decode(T.self, from: json)
|
||||
} catch {
|
||||
print(error)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
|
||||
29
AutoCat/Views/BlockBarButtonItem.swift
Normal file
29
AutoCat/Views/BlockBarButtonItem.swift
Normal file
@ -0,0 +1,29 @@
|
||||
import UIKit
|
||||
|
||||
class BlockBarButtonItem: UIBarButtonItem {
|
||||
typealias ActionHandler = (UIBarButtonItem) -> Void
|
||||
|
||||
private var actionHandler: ActionHandler?
|
||||
|
||||
convenience init(image: UIImage?, style: UIBarButtonItem.Style, actionHandler: ActionHandler?) {
|
||||
self.init(image: image, style: style, target: nil, action: #selector(barButtonItemPressed(sender:)))
|
||||
target = self
|
||||
self.actionHandler = actionHandler
|
||||
}
|
||||
|
||||
convenience init(title: String?, style: UIBarButtonItem.Style, actionHandler: ActionHandler?) {
|
||||
self.init(title: title, style: style, target: nil, action: #selector(barButtonItemPressed(sender:)))
|
||||
target = self
|
||||
self.actionHandler = actionHandler
|
||||
}
|
||||
|
||||
convenience init(barButtonSystemItem systemItem: UIBarButtonItem.SystemItem, actionHandler: ActionHandler?) {
|
||||
self.init(barButtonSystemItem: systemItem, target: nil, action: #selector(barButtonItemPressed(sender:)))
|
||||
target = self
|
||||
self.actionHandler = actionHandler
|
||||
}
|
||||
|
||||
@objc func barButtonItemPressed(sender: UIBarButtonItem) {
|
||||
actionHandler?(sender)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user