Cleanup silent XCB actions code
This commit is contained in:
parent
d7d26ce517
commit
a8d8ac783b
|
@ -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 }))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue