Cleanup silent XCB actions code

This commit is contained in:
Shadowfacts 2018-09-23 21:10:45 -04:00
parent 41600d9ba6
commit 0016964191
5 changed files with 64 additions and 53 deletions

View File

@ -286,14 +286,14 @@ public class Client {
media: [Attachment]? = nil,
sensitive: Bool? = nil,
spoilerText: String? = nil,
visiblity: Status.Visibility? = nil,
visibility: Status.Visibility? = nil,
language: String? = nil) -> Request<Status> {
return Request<Status>(method: .post, path: "/api/v1/statuses", body: .parameters([
"status" => text,
"in_reply_to_id" => inReplyTo,
"sensitive" => sensitive,
"spoiler_text" => spoilerText,
"visibility" => visiblity?.rawValue,
"visibility" => visibility?.rawValue,
"language" => language
] + "media_ids" => media?.map { $0.id }))
}

View File

@ -244,7 +244,7 @@ class ComposeViewController: UIViewController {
media: attachments,
sensitive: sensitive,
spoilerText: contentWarning,
visiblity: visibility)
visibility: visibility)
MastodonController.shared.client.run(request) { response in
guard case let .success(status, _) = response else { fatalError() }
self.status = status

View File

@ -11,17 +11,15 @@ import UIKit
struct XCBActions {
// MARK: - Posts
static func postStatus(_ url: XCallbackURL) -> Bool {
let session = XCBManager.createSession(type: .postStatus, url: url)
static func postStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) {
let mentioning = url.arguments["mentioning"]
let text = url.arguments["text"]
func postStatusSilently() {
if silent ?? false {
var status = ""
if let mentioning = mentioning { status += mentioning }
if let text = text { status += text }
let request = MastodonController.shared.client.createStatus(text: status)
let request = MastodonController.shared.client.createStatus(text: status, visibility: Preferences.shared.defaultPostVisibility)
MastodonController.shared.client.run(request) { response in
if case let .success(status, _) = response {
session.complete(with: .success, additionalData: [
@ -34,40 +32,9 @@ struct XCBActions {
])
}
}
}
func showComposeStatus() {
} else {
let vc = ComposeViewController.create(for: session, mentioning: mentioning, text: text)
UIApplication.shared.keyWindow!.rootViewController!.present(vc, animated: true)
}
let silent = Bool(url.arguments["silent"] ?? "false") ?? false
if silent {
if let source = url.source {
let permission = Preferences.shared.silentActions[source] ?? .undecided
switch permission {
case .accepted:
postStatusSilently()
case .rejected:
showComposeStatus()
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
postStatusSilently()
}))
alert.addAction(UIAlertAction(title: "Reject", style: .default, handler: { (_) in
Preferences.shared.silentActions[source] = .rejected
showComposeStatus()
}))
UIApplication.shared.keyWindow!.rootViewController!.present(alert, animated: true)
}
} else {
session.complete(with: .error, additionalData: ["error": "Cannot perform silent action without source app, x-source parameter must be specified"])
}
} else {
showComposeStatus()
}
return true
}
}

View File

@ -11,7 +11,7 @@ import UIKit
class XCBManager {
static var specs: [XCallbackURLSpec] = [
XCallbackURLSpec(path: "/postStatus", arguments: ["mentioning": true, "text": true, "silent": true], handle: XCBActions.postStatus)
XCallbackURLSpec(path: "/postStatus", type: .postStatus, arguments: ["mentioning": true, "text": true], canRunSilently: true, action: XCBActions.postStatus)
]
static var currentSession: XCBSession?
@ -20,7 +20,7 @@ class XCBManager {
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(xcbURL)
return spec.handle(url: xcbURL)
}
return false
}

View File

@ -6,18 +6,61 @@
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import Foundation
import UIKit
typealias XCBAction = (_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) -> Void
struct XCallbackURLSpec {
let path: String
let type: XCBSessionType
let arguments: [String: Bool]
let handle: (XCallbackURL) -> Bool
let canRunSilently: Bool
let action: XCBAction
init(path: String, arguments: [String: Bool], handle: @escaping (XCallbackURL) -> Bool) {
init(path: String, type: XCBSessionType, arguments: [String: Bool], canRunSilently: Bool, action: @escaping XCBAction) {
self.path = path
self.type = type
self.canRunSilently = canRunSilently
self.action = action
var arguments = arguments
if canRunSilently {
arguments["silent"] = true
}
self.arguments = arguments
self.handle = handle
}
func handle(url: XCallbackURL) -> Bool {
let session = XCBManager.createSession(type: type, url: url)
if canRunSilently && url.silent {
if let source = url.source {
let permission = Preferences.shared.silentActions[source] ?? .undecided
switch permission {
case .accepted:
action(url, session, true)
case .rejected:
action(url, 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)
}))
alert.addAction(UIAlertAction(title: "Reject", style: .default, handler: { (_) in
Preferences.shared.silentActions[source] = .rejected
self.action(url, session, false)
}))
UIApplication.shared.keyWindow!.rootViewController!.present(alert, animated: true)
}
} else {
session.complete(with: .error, additionalData: [
"error": "Cannot perform silent action without source app, x-source parameter must be specified"
])
}
} else {
action(url, session, nil)
}
return true
}
}
@ -25,6 +68,7 @@ struct XCallbackURLSpec {
struct XCallbackURL {
let path: String
let arguments: [String: String]
let silent: Bool
let source: String?
let success: URL?
let error: URL?
@ -38,6 +82,11 @@ struct XCallbackURL {
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) }
@ -47,13 +96,8 @@ struct XCallbackURL {
extension XCallbackURLSpec {
func matches(_ components: URLComponents) -> Bool {
return path == components.path && arguments.matches(components)
}
}
extension Dictionary where Key == String, Value == Bool {
func matches(_ components: URLComponents) -> Bool {
for (name, optional) in self {
guard path == components.path else { return false }
for (name, optional) in arguments {
if (!optional && components.queryItems?.first(where: { $0.name == name }) == nil) {
return false
}