From 5a7d7711bc000ce9d52ba1485c2e3c98bbc90a71 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Tue, 25 Sep 2018 21:41:12 -0400 Subject: [PATCH] Refactor XCB actions code, add JSON responses --- Tusker.xcodeproj/project.pbxproj | 12 +++-- Tusker/XCallbackURL/XCBActions.swift | 54 +++++++++---------- Tusker/XCallbackURL/XCBManager.swift | 28 +++++----- Tusker/XCallbackURL/XCBRequest.swift | 44 +++++++++++++++ ...CallbackURL.swift => XCBRequestSpec.swift} | 54 +++++-------------- Tusker/XCallbackURL/XCBSession.swift | 38 ++++++------- 6 files changed, 126 insertions(+), 104 deletions(-) create mode 100644 Tusker/XCallbackURL/XCBRequest.swift rename Tusker/XCallbackURL/{XCallbackURL.swift => XCBRequestSpec.swift} (57%) diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index f5cb14f3..ff3b7153 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -61,6 +61,7 @@ D641C77D213CB024004B4513 /* FollowNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D641C77C213CB024004B4513 /* FollowNotificationTableViewCell.swift */; }; D641C77F213DC78A004B4513 /* InlineTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D641C77E213DC78A004B4513 /* InlineTextAttachment.swift */; }; D641C78F213DF2AA004B4513 /* VisibilityTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D641C78E213DF2AA004B4513 /* VisibilityTableViewController.swift */; }; + D6434EB3215B1856001A919A /* XCBRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6434EB2215B1856001A919A /* XCBRequest.swift */; }; D646C956213B365700269FB5 /* LargeImageExpandAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D646C955213B365700269FB5 /* LargeImageExpandAnimationController.swift */; }; D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D646C957213B367000269FB5 /* LargeImageShrinkAnimationController.swift */; }; D646C95A213B5D0500269FB5 /* LargeImageInteractionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D646C959213B5D0500269FB5 /* LargeImageInteractionController.swift */; }; @@ -94,7 +95,7 @@ D667E5F52135BCD50057A976 /* ConversationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F42135BCD50057A976 /* ConversationViewController.swift */; }; D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */; }; D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A7B2157E01900721E32 /* XCBManager.swift */; }; - D6757A7E2157E02600721E32 /* XCallbackURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A7D2157E02600721E32 /* XCallbackURL.swift */; }; + D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A7D2157E02600721E32 /* XCBRequestSpec.swift */; }; D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6757A812157E8FA00721E32 /* XCBSession.swift */; }; D679C09F215850EF00DA27FE /* XCBActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D679C09E215850EF00DA27FE /* XCBActions.swift */; }; D6BED170212663DA00F02DA0 /* SwiftSoup.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -222,6 +223,7 @@ D641C77C213CB024004B4513 /* FollowNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowNotificationTableViewCell.swift; sourceTree = ""; }; D641C77E213DC78A004B4513 /* InlineTextAttachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineTextAttachment.swift; sourceTree = ""; }; D641C78E213DF2AA004B4513 /* VisibilityTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityTableViewController.swift; sourceTree = ""; }; + D6434EB2215B1856001A919A /* XCBRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBRequest.swift; sourceTree = ""; }; D646C955213B365700269FB5 /* LargeImageExpandAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeImageExpandAnimationController.swift; sourceTree = ""; }; D646C957213B367000269FB5 /* LargeImageShrinkAnimationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeImageShrinkAnimationController.swift; sourceTree = ""; }; D646C959213B5D0500269FB5 /* LargeImageInteractionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeImageInteractionController.swift; sourceTree = ""; }; @@ -254,7 +256,7 @@ D667E5F42135BCD50057A976 /* ConversationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationViewController.swift; sourceTree = ""; }; D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Equatable.swift"; sourceTree = ""; }; D6757A7B2157E01900721E32 /* XCBManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBManager.swift; sourceTree = ""; }; - D6757A7D2157E02600721E32 /* XCallbackURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCallbackURL.swift; sourceTree = ""; }; + D6757A7D2157E02600721E32 /* XCBRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBRequestSpec.swift; sourceTree = ""; }; D6757A812157E8FA00721E32 /* XCBSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBSession.swift; sourceTree = ""; }; D679C09E215850EF00DA27FE /* XCBActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActions.swift; sourceTree = ""; }; D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftSoup.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -580,7 +582,8 @@ isa = PBXGroup; children = ( D6757A7B2157E01900721E32 /* XCBManager.swift */, - D6757A7D2157E02600721E32 /* XCallbackURL.swift */, + D6757A7D2157E02600721E32 /* XCBRequestSpec.swift */, + D6434EB2215B1856001A919A /* XCBRequest.swift */, D6757A812157E8FA00721E32 /* XCBSession.swift */, D64F80E1215875CC00BEF393 /* XCBActionType.swift */, D679C09E215850EF00DA27FE /* XCBActions.swift */, @@ -963,6 +966,7 @@ D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */, D6C94D892139E6EC00CB5196 /* AttachmentView.swift in Sources */, D6C94D872139E62700CB5196 /* LargeImageViewController.swift in Sources */, + D6434EB3215B1856001A919A /* XCBRequest.swift in Sources */, D663626221360B1900C9CBA2 /* Preferences.swift in Sources */, D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */, D641C78F213DF2AA004B4513 /* VisibilityTableViewController.swift in Sources */, @@ -984,7 +988,7 @@ D641C773213CAA25004B4513 /* NotificationsTableViewController.swift in Sources */, D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */, D64A0CD32132153900640E3B /* HTMLContentLabel.swift in Sources */, - D6757A7E2157E02600721E32 /* XCallbackURL.swift in Sources */, + D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */, D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */, D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */, D667E5E721349D4C0057A976 /* ProfileTableViewController.swift in Sources */, diff --git a/Tusker/XCallbackURL/XCBActions.swift b/Tusker/XCallbackURL/XCBActions.swift index 7b39e3fb..e18c6104 100644 --- a/Tusker/XCallbackURL/XCBActions.swift +++ b/Tusker/XCallbackURL/XCBActions.swift @@ -23,8 +23,8 @@ struct XCBActions { navController.pushViewController(vc, animated: animated) } - static func getStatus(from url: XCallbackURL, session: XCBSession, completion: @escaping (Status) -> Void) { - if let id = url.arguments["statusID"] { + static func getStatus(from request: XCBRequest, session: XCBSession, completion: @escaping (Status) -> Void) { + if let id = request.arguments["statusID"] { MastodonCache.status(for: id) { (status) in if let status = status { completion(status) @@ -34,7 +34,7 @@ struct XCBActions { ]) } } - } else if let searchQuery = url.arguments["statusURL"] { + } else if let searchQuery = request.arguments["statusURL"] { let request = MastodonController.shared.client.search(query: searchQuery) MastodonController.shared.client.run(request) { (response) in if case let .success(results, _) = response, @@ -54,8 +54,8 @@ struct XCBActions { } } - static func getAccount(from url: XCallbackURL, session: XCBSession, completion: @escaping (Account) -> Void) { - if let id = url.arguments["accountID"] { + static func getAccount(from request: XCBRequest, session: XCBSession, completion: @escaping (Account) -> Void) { + if let id = request.arguments["accountID"] { MastodonCache.account(for: id) { (account) in if let account = account { completion(account) @@ -65,7 +65,7 @@ struct XCBActions { ]) } } - } else if let searchQuery = url.arguments["accountURL"] { + } else if let searchQuery = request.arguments["accountURL"] { let request = MastodonController.shared.client.search(query: searchQuery) MastodonController.shared.client.run(request) { (response) in if case let .success(results, _) = response { @@ -83,7 +83,7 @@ struct XCBActions { ]) } } - } else if let acct = url.arguments["acct"] { + } else if let acct = request.arguments["acct"] { let request = MastodonController.shared.client.searchForAccount(query: acct) MastodonController.shared.client.run(request) { (response) in if case let .success(accounts, _) = response { @@ -109,8 +109,8 @@ struct XCBActions { } // MARK: - Statuses - static func showStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - getStatus(from: url, session: session) { (status) in + static func showStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + getStatus(from: request, session: session) { (status) in let vc = ConversationViewController.create(for: status.id) DispatchQueue.main.async { presentNav(vc, animated: true) @@ -118,9 +118,9 @@ struct XCBActions { } } - static func postStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - let mentioning = url.arguments["mentioning"] - let text = url.arguments["text"] + static func postStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + let mentioning = request.arguments["mentioning"] + let text = request.arguments["text"] if silent ?? false { var status = "" @@ -145,9 +145,9 @@ struct XCBActions { } } - static func getStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - getStatus(from: url, session: session) { (status) in - let html = Bool(url.arguments["html"] ?? "false") ?? false + static func getStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + getStatus(from: request, session: session) { (status) in + let html = Bool(request.arguments["html"] ?? "false") ?? false let content: String if html { content = status.content @@ -175,15 +175,15 @@ struct XCBActions { } } - static func favoriteStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - statusAction(request: Status.favourite, alertTitle: "Favorite status?", url, session, silent) + static func favoriteStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + statusAction(request: Status.favourite, alertTitle: "Favorite status?", request, session, silent) } - static func reblogStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - statusAction(request: Status.reblog, alertTitle: "Reblog status?", url, session, silent) + static func reblogStatus(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + statusAction(request: Status.reblog, alertTitle: "Reblog status?", request, session, silent) } - static func statusAction(request: @escaping (Status) -> Request, alertTitle: String, _ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { + static func statusAction(request: @escaping (Status) -> Request, alertTitle: String, _ url: XCBRequest, _ session: XCBSession, _ silent: Bool?) { func performAction(status: Status, completion: ((Status) -> Void)?) { MastodonController.shared.client.run(request(status)) { (response) in if case let .success(status, _) = response { @@ -230,8 +230,8 @@ struct XCBActions { } // MARK: - Accounts - static func showAccount(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - getAccount(from: url, session: session) { (account) in + static func showAccount(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + getAccount(from: request, session: session) { (account) in let vc = ProfileTableViewController.create(for: account.id) DispatchQueue.main.async { presentNav(vc, animated: true) @@ -239,8 +239,8 @@ struct XCBActions { } } - static func getAccount(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { - getAccount(from: url, session: session) { (account) in + static func getAccount(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { + getAccount(from: request, session: session) { (account) in session.complete(with: .success, additionalData: [ "username": account.acct, "displayName": account.displayName, @@ -254,7 +254,7 @@ struct XCBActions { } } - static func getCurrentUser(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { + static func getCurrentUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { let account = MastodonController.shared.account! session.complete(with: .success, additionalData: [ "username": account.acct, @@ -268,7 +268,7 @@ struct XCBActions { ]) } - static func followUser(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) { + static func followUser(_ request: XCBRequest, _ session: XCBSession, _ silent: Bool?) { func performAction(_ account: Account) { let request = Account.follow(account.id) MastodonController.shared.client.run(request) { (response) in @@ -306,6 +306,6 @@ struct XCBActions { } } - getAccount(from: url, session: session, completion: follow) + getAccount(from: request, session: session, completion: follow) } } diff --git a/Tusker/XCallbackURL/XCBManager.swift b/Tusker/XCallbackURL/XCBManager.swift index 9f4646ca..c172b6e7 100644 --- a/Tusker/XCallbackURL/XCBManager.swift +++ b/Tusker/XCallbackURL/XCBManager.swift @@ -10,18 +10,18 @@ import UIKit class XCBManager { - static var specs: [XCallbackURLSpec] = [ + static var specs: [XCBRequestSpec] = [ // Statuses - XCallbackURLSpec(type: .showStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: false, action: XCBActions.showStatus), - XCallbackURLSpec(type: .getStatus, arguments: ["statusID": true, "statusURL": true, "html": true], canRunSilently: false, action: XCBActions.getStatus), - XCallbackURLSpec(type: .postStatus, arguments: ["mentioning": true, "text": true], canRunSilently: true, action: XCBActions.postStatus), - XCallbackURLSpec(type: .favoriteStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.favoriteStatus), - XCallbackURLSpec(type: .reblogStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.reblogStatus), + XCBRequestSpec(type: .showStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: false, action: XCBActions.showStatus), + XCBRequestSpec(type: .getStatus, arguments: ["statusID": true, "statusURL": true, "html": true], canRunSilently: false, action: XCBActions.getStatus), + XCBRequestSpec(type: .postStatus, arguments: ["mentioning": true, "text": true], canRunSilently: true, action: XCBActions.postStatus), + XCBRequestSpec(type: .favoriteStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.favoriteStatus), + XCBRequestSpec(type: .reblogStatus, arguments: ["statusID": true, "statusURL": true], canRunSilently: true, action: XCBActions.reblogStatus), // Accounts - XCallbackURLSpec(type: .showAccount, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: false, action: XCBActions.showAccount), - XCallbackURLSpec(type: .getAccount, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: false, action: XCBActions.getAccount), - XCallbackURLSpec(type: .getCurrentUser, arguments: [:], canRunSilently: false, action: XCBActions.getCurrentUser), - XCallbackURLSpec(type: .followUser, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: true, action: XCBActions.followUser) + XCBRequestSpec(type: .showAccount, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: false, action: XCBActions.showAccount), + XCBRequestSpec(type: .getAccount, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: false, action: XCBActions.getAccount), + XCBRequestSpec(type: .getCurrentUser, arguments: [:], canRunSilently: false, action: XCBActions.getCurrentUser), + XCBRequestSpec(type: .followUser, arguments: ["accountID": true, "accountURL": true, "acct": true], canRunSilently: true, action: XCBActions.followUser) ] static var currentSession: XCBSession? @@ -29,14 +29,14 @@ class XCBManager { static func handle(url: URL) -> Bool { guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return false } if let spec = specs.first(where: { $0.matches(components) }) { - let xcbURL = XCallbackURL(spec: spec, components: components) - return spec.handle(url: xcbURL) + let request = XCBRequest(spec: spec, components: components) + return spec.handle(request: request) } return false } - static func createSession(type: XCBActionType, url: XCallbackURL) -> XCBSession { - let session = XCBSession(type: type, success: url.success, error: url.error, cancel: url.cancel) + static func createSession(type: XCBActionType, request: XCBRequest) -> XCBSession { + let session = XCBSession(type: type, request: request) currentSession = session return session } diff --git a/Tusker/XCallbackURL/XCBRequest.swift b/Tusker/XCallbackURL/XCBRequest.swift new file mode 100644 index 00000000..5b32f223 --- /dev/null +++ b/Tusker/XCallbackURL/XCBRequest.swift @@ -0,0 +1,44 @@ +// +// XCBRequest.swift +// Tusker +// +// Created by Shadowfacts on 9/25/18. +// Copyright © 2018 Shadowfacts. All rights reserved. +// + +import Foundation + +struct XCBRequest { + let path: String + let arguments: [String: String] + let json: Bool + let silent: Bool + let source: String? + let success: URL? + let error: URL? + let cancel: URL? + + init(spec: XCBRequestSpec, components: URLComponents) { + self.path = spec.path + let queryItems = components.queryItems! + self.arguments = spec.arguments.reduce(into: [String: String](), { (result, el) in + if let value = queryItems.first(where: { $0.name == el.key })?.value { + result[el.key] = value + } + }) + if let arg = arguments["json"] { + json = Bool(arg) ?? false + } else { + json = false + } + if spec.canRunSilently, let arg = arguments["silent"] { + silent = Bool(arg) ?? false + } else { + silent = false + } + source = queryItems.first(where: { $0.name == "x-source" }).flatMap { $0.value } + success = queryItems.first(where: { $0.name == "x-success" }).flatMap { $0.value }.flatMap { URL(string: $0) } + error = queryItems.first(where: { $0.name == "x-error" }).flatMap { $0.value }.flatMap { URL(string: $0) } + cancel = queryItems.first(where: { $0.name == "x-cancel" }).flatMap { $0.value }.flatMap { URL(string: $0) } + } +} diff --git a/Tusker/XCallbackURL/XCallbackURL.swift b/Tusker/XCallbackURL/XCBRequestSpec.swift similarity index 57% rename from Tusker/XCallbackURL/XCallbackURL.swift rename to Tusker/XCallbackURL/XCBRequestSpec.swift index 794d1d3f..a5c8a956 100644 --- a/Tusker/XCallbackURL/XCallbackURL.swift +++ b/Tusker/XCallbackURL/XCBRequestSpec.swift @@ -8,9 +8,9 @@ import UIKit -typealias XCBAction = (_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) -> Void +typealias XCBAction = (_ url: XCBRequest, _ session: XCBSession, _ silent: Bool?) -> Void -struct XCallbackURLSpec { +struct XCBRequestSpec { let path: String let type: XCBActionType @@ -27,28 +27,29 @@ struct XCallbackURLSpec { if canRunSilently { arguments["silent"] = true } + arguments["json"] = true self.arguments = arguments } - func handle(url: XCallbackURL) -> Bool { - let session = XCBManager.createSession(type: type, url: url) - if canRunSilently && url.silent { - if let source = url.source { + func handle(request: XCBRequest) -> Bool { + let session = XCBManager.createSession(type: type, request: request) + if canRunSilently && request.silent { + if let source = request.source { let permission = Preferences.shared.silentActions[source] ?? .undecided switch permission { case .accepted: - action(url, session, true) + action(request, session, true) case .rejected: - action(url, session, false) + action(request, session, false) case .undecided: let alert = UIAlertController(title: "\(source) wants to perform actions silently", message: "Accepting will allow \(source) to perform actions without your confirmation, rejecting will always prompt for confirmation.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Accept", style: .default, handler: { (_) in Preferences.shared.silentActions[source] = .accepted - self.action(url, session, true) + self.action(request, session, true) })) alert.addAction(UIAlertAction(title: "Reject", style: .default, handler: { (_) in Preferences.shared.silentActions[source] = .rejected - self.action(url, session, false) + self.action(request, session, false) })) UIApplication.shared.keyWindow!.rootViewController!.present(alert, animated: true) } @@ -58,43 +59,14 @@ struct XCallbackURLSpec { ]) } } else { - action(url, session, nil) + action(request, session, nil) } return true } } -struct XCallbackURL { - let path: String - let arguments: [String: String] - let silent: Bool - let source: String? - let success: URL? - let error: URL? - let cancel: URL? - - init(spec: XCallbackURLSpec, components: URLComponents) { - self.path = spec.path - let queryItems = components.queryItems! - self.arguments = spec.arguments.reduce(into: [String: String](), { (result, el) in - if let value = queryItems.first(where: { $0.name == el.key })?.value { - result[el.key] = value - } - }) - if spec.canRunSilently { - silent = Bool(arguments["silent"] ?? "false") ?? false - } else { - silent = false - } - source = queryItems.first(where: { $0.name == "x-source" }).flatMap { $0.value } - success = queryItems.first(where: { $0.name == "x-success" }).flatMap { $0.value }.flatMap { URL(string: $0) } - error = queryItems.first(where: { $0.name == "x-error" }).flatMap { $0.value }.flatMap { URL(string: $0) } - cancel = queryItems.first(where: { $0.name == "x-cancel" }).flatMap { $0.value }.flatMap { URL(string: $0) } - } -} - -extension XCallbackURLSpec { +extension XCBRequestSpec { func matches(_ components: URLComponents) -> Bool { guard path == components.path else { return false } for (name, optional) in arguments { diff --git a/Tusker/XCallbackURL/XCBSession.swift b/Tusker/XCallbackURL/XCBSession.swift index c4179c70..bd37bbb5 100644 --- a/Tusker/XCallbackURL/XCBSession.swift +++ b/Tusker/XCallbackURL/XCBSession.swift @@ -9,31 +9,33 @@ import UIKit class XCBSession { - let type: XCBActionType - let success: URL? - let error: URL? - let cancel: URL? + static let encoder = JSONEncoder() - init(type: XCBActionType, success: URL?, error: URL?, cancel: URL?) { + let type: XCBActionType + let request: XCBRequest + + init(type: XCBActionType, request: XCBRequest) { self.type = type - self.success = success - self.error = error - self.cancel = cancel + self.request = request } func complete(with result: XCBSessionResult, additionalData: [String: String?]? = nil) { - let url = result == .success ? success : result == .error ? error : cancel - if var url = url { - XCBManager.currentSession = nil - if let additionalData = additionalData { - var components = URLComponents(url: url, resolvingAgainstBaseURL: true)! - components.queryItems = components.queryItems ?? [] + guard var url = result == .success ? request.success : result == .error ? request.error : request.cancel else { return } + XCBManager.currentSession = nil + if let additionalData = additionalData { + var components = URLComponents(url: url, resolvingAgainstBaseURL: true)! + components.queryItems = components.queryItems ?? [] + if request.json { + let data = try! XCBSession.encoder.encode(additionalData) + let response = String(data: data, encoding: .utf8) + components.queryItems!.append(URLQueryItem(name: "response", value: response)) + } else { components.queryItems!.append(contentsOf: additionalData.map(URLQueryItem.init)) - url = components.url! - } - DispatchQueue.main.async { - UIApplication.shared.open(url, options: [:]) } + url = components.url! + } + DispatchQueue.main.async { + UIApplication.shared.open(url, options: [:]) } } }