Cleanup silent XCB actions code
This commit is contained in:
parent
d7d26ce517
commit
a8d8ac783b
|
@ -286,14 +286,14 @@ public class Client {
|
||||||
media: [Attachment]? = nil,
|
media: [Attachment]? = nil,
|
||||||
sensitive: Bool? = nil,
|
sensitive: Bool? = nil,
|
||||||
spoilerText: String? = nil,
|
spoilerText: String? = nil,
|
||||||
visiblity: Status.Visibility? = nil,
|
visibility: Status.Visibility? = nil,
|
||||||
language: String? = nil) -> Request<Status> {
|
language: String? = nil) -> Request<Status> {
|
||||||
return Request<Status>(method: .post, path: "/api/v1/statuses", body: .parameters([
|
return Request<Status>(method: .post, path: "/api/v1/statuses", body: .parameters([
|
||||||
"status" => text,
|
"status" => text,
|
||||||
"in_reply_to_id" => inReplyTo,
|
"in_reply_to_id" => inReplyTo,
|
||||||
"sensitive" => sensitive,
|
"sensitive" => sensitive,
|
||||||
"spoiler_text" => spoilerText,
|
"spoiler_text" => spoilerText,
|
||||||
"visibility" => visiblity?.rawValue,
|
"visibility" => visibility?.rawValue,
|
||||||
"language" => language
|
"language" => language
|
||||||
] + "media_ids" => media?.map { $0.id }))
|
] + "media_ids" => media?.map { $0.id }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,7 @@ class ComposeViewController: UIViewController {
|
||||||
media: attachments,
|
media: attachments,
|
||||||
sensitive: sensitive,
|
sensitive: sensitive,
|
||||||
spoilerText: contentWarning,
|
spoilerText: contentWarning,
|
||||||
visiblity: visibility)
|
visibility: visibility)
|
||||||
MastodonController.shared.client.run(request) { response in
|
MastodonController.shared.client.run(request) { response in
|
||||||
guard case let .success(status, _) = response else { fatalError() }
|
guard case let .success(status, _) = response else { fatalError() }
|
||||||
self.status = status
|
self.status = status
|
||||||
|
|
|
@ -11,17 +11,15 @@ import UIKit
|
||||||
struct XCBActions {
|
struct XCBActions {
|
||||||
// MARK: - Posts
|
// MARK: - Posts
|
||||||
|
|
||||||
static func postStatus(_ url: XCallbackURL) -> Bool {
|
static func postStatus(_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) {
|
||||||
let session = XCBManager.createSession(type: .postStatus, url: url)
|
|
||||||
|
|
||||||
let mentioning = url.arguments["mentioning"]
|
let mentioning = url.arguments["mentioning"]
|
||||||
let text = url.arguments["text"]
|
let text = url.arguments["text"]
|
||||||
|
|
||||||
func postStatusSilently() {
|
if silent ?? false {
|
||||||
var status = ""
|
var status = ""
|
||||||
if let mentioning = mentioning { status += mentioning }
|
if let mentioning = mentioning { status += mentioning }
|
||||||
if let text = text { status += text }
|
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
|
MastodonController.shared.client.run(request) { response in
|
||||||
if case let .success(status, _) = response {
|
if case let .success(status, _) = response {
|
||||||
session.complete(with: .success, additionalData: [
|
session.complete(with: .success, additionalData: [
|
||||||
|
@ -34,40 +32,9 @@ struct XCBActions {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
func showComposeStatus() {
|
|
||||||
let vc = ComposeViewController.create(for: session, mentioning: mentioning, text: text)
|
let vc = ComposeViewController.create(for: session, mentioning: mentioning, text: text)
|
||||||
UIApplication.shared.keyWindow!.rootViewController!.present(vc, animated: true)
|
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 {
|
class XCBManager {
|
||||||
|
|
||||||
static var specs: [XCallbackURLSpec] = [
|
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?
|
static var currentSession: XCBSession?
|
||||||
|
@ -20,7 +20,7 @@ class XCBManager {
|
||||||
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return false }
|
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { return false }
|
||||||
if let spec = specs.first(where: { $0.matches(components) }) {
|
if let spec = specs.first(where: { $0.matches(components) }) {
|
||||||
let xcbURL = XCallbackURL(spec: spec, components: components)
|
let xcbURL = XCallbackURL(spec: spec, components: components)
|
||||||
return spec.handle(xcbURL)
|
return spec.handle(url: xcbURL)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,61 @@
|
||||||
// Copyright © 2018 Shadowfacts. All rights reserved.
|
// Copyright © 2018 Shadowfacts. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import UIKit
|
||||||
|
|
||||||
|
typealias XCBAction = (_ url: XCallbackURL, _ session: XCBSession, _ silent: Bool?) -> Void
|
||||||
|
|
||||||
struct XCallbackURLSpec {
|
struct XCallbackURLSpec {
|
||||||
|
|
||||||
let path: String
|
let path: String
|
||||||
|
let type: XCBSessionType
|
||||||
let arguments: [String: Bool]
|
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.path = path
|
||||||
|
self.type = type
|
||||||
|
self.canRunSilently = canRunSilently
|
||||||
|
self.action = action
|
||||||
|
var arguments = arguments
|
||||||
|
if canRunSilently {
|
||||||
|
arguments["silent"] = true
|
||||||
|
}
|
||||||
self.arguments = arguments
|
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 {
|
struct XCallbackURL {
|
||||||
let path: String
|
let path: String
|
||||||
let arguments: [String: String]
|
let arguments: [String: String]
|
||||||
|
let silent: Bool
|
||||||
let source: String?
|
let source: String?
|
||||||
let success: URL?
|
let success: URL?
|
||||||
let error: URL?
|
let error: URL?
|
||||||
|
@ -38,6 +82,11 @@ struct XCallbackURL {
|
||||||
result[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 }
|
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) }
|
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) }
|
error = queryItems.first(where: { $0.name == "x-error" }).flatMap { $0.value }.flatMap { URL(string: $0) }
|
||||||
|
@ -47,13 +96,8 @@ struct XCallbackURL {
|
||||||
|
|
||||||
extension XCallbackURLSpec {
|
extension XCallbackURLSpec {
|
||||||
func matches(_ components: URLComponents) -> Bool {
|
func matches(_ components: URLComponents) -> Bool {
|
||||||
return path == components.path && arguments.matches(components)
|
guard path == components.path else { return false }
|
||||||
}
|
for (name, optional) in arguments {
|
||||||
}
|
|
||||||
|
|
||||||
extension Dictionary where Key == String, Value == Bool {
|
|
||||||
func matches(_ components: URLComponents) -> Bool {
|
|
||||||
for (name, optional) in self {
|
|
||||||
if (!optional && components.queryItems?.first(where: { $0.name == name }) == nil) {
|
if (!optional && components.queryItems?.first(where: { $0.name == name }) == nil) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue