Improve Share Suggestion execution flow

This commit is contained in:
Ilya Laktyushin 2019-11-28 18:22:40 +04:00
parent 45224e6e96
commit 5e620dc318
6 changed files with 94 additions and 59 deletions

View File

@ -426,7 +426,7 @@ public final class ShareController: ViewController {
return
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare)
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId)
self.controllerNode.dismiss = { [weak self] shared in
self?.presentingViewController?.dismiss(animated: false, completion: nil)
self?.dismissed?(shared)
@ -704,15 +704,12 @@ public final class ShareController: ViewController {
}
self.displayNodeDidLoad()
if let _ = self.immediatePeerId {
} else {
self.peersDisposable.set((self.peers.get()
|> deliverOnMainQueue).start(next: { [weak self] next in
if let strongSelf = self {
strongSelf.controllerNode.updatePeers(account: strongSelf.currentAccount, switchableAccounts: strongSelf.switchableAccounts, peers: next.0, accountPeer: next.1, defaultAction: strongSelf.defaultAction)
}
}))
}
self._ready.set(self.controllerNode.ready.get())
}
@ -827,9 +824,6 @@ public final class ShareController: ViewController {
return (resultPeers, accountPeer)
}
})
if let immediatePeerId = self.immediatePeerId {
self.sendImmediately(peerId: immediatePeerId)
} else {
self.peersDisposable.set((self.peers.get()
|> deliverOnMainQueue).start(next: { [weak self] next in
if let strongSelf = self {
@ -849,9 +843,4 @@ public final class ShareController: ViewController {
}
}))
}
}
private func sendImmediately(peerId: PeerId) {
self.controllerNode.send(peerId: peerId)
}
}

View File

@ -31,6 +31,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private var presentationData: PresentationData
private let externalShare: Bool
private let immediateExternalShare: Bool
private var immediatePeerId: PeerId?
private let defaultAction: ShareControllerAction?
private let requestLayout: (ContainedViewLayoutTransition) -> Void
@ -75,11 +76,12 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private var hapticFeedback: HapticFeedback?
init(sharedContext: SharedAccountContext, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool) {
init(sharedContext: SharedAccountContext, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?) {
self.sharedContext = sharedContext
self.presentationData = sharedContext.currentPresentationData.with { $0 }
self.externalShare = externalShare
self.immediateExternalShare = immediateExternalShare
self.immediatePeerId = immediatePeerId
self.presentError = presentError
self.defaultAction = defaultAction
@ -642,6 +644,17 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
return
}
if let peerId = self.immediatePeerId {
self.immediatePeerId = nil
let _ = (account.postbox.transaction { transaction -> RenderedPeer? in
return transaction.getPeer(peerId).flatMap(RenderedPeer.init(peer:))
} |> deliverOnMainQueue).start(next: { [weak self] peer in
if let strongSelf = self, let peer = peer {
strongSelf.controllerInteraction?.togglePeer(peer, true)
}
})
}
let animated = self.peersContentNode == nil
let peersContentNode = SharePeersContainerNode(sharedContext: self.sharedContext, account: account, switchableAccounts: switchableAccounts, theme: self.presentationData.theme, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, peers: peers, accountPeer: accountPeer, controllerInteraction: self.controllerInteraction!, externalShare: self.externalShare, switchToAnotherAccount: { [weak self] in
self?.switchToAnotherAccount?()

View File

@ -181,9 +181,13 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou
}
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .outgoing
interaction.identifier = "sendMessage_\(account.peerId.toInt64())_\(peer.id.toInt64)"
interaction.identifier = "sendMessage_\(account.peerId.toInt64())_\(peer.id.toInt64())"
interaction.groupIdentifier = "sendMessage_\(subject.toString())_\(account.peerId.toInt64())"
interaction.donate()
interaction.donate { error in
if let error = error {
print(error)
}
}
}
})
}
@ -191,7 +195,7 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou
public func deleteSendMessageIntents(account: Account, peerId: PeerId) {
if #available(iOS 10.0, *) {
INInteraction.delete(with: ["sendMessage_\(account.peerId.toInt64())_\(peerId.toInt64)"])
INInteraction.delete(with: ["sendMessage_\(account.peerId.toInt64())_\(peerId.toInt64())"])
}
}

View File

@ -1199,7 +1199,7 @@ final class SharedApplicationContext {
self.logoutDisposable.set((self.sharedContextPromise.get()
|> take(1)
|> mapToSignal { sharedContext -> Signal<Set<PeerId>, NoError> in
|> mapToSignal { sharedContext -> Signal<(AccountManager, Set<PeerId>), NoError> in
return sharedContext.sharedContext.activeAccounts
|> map { _, accounts, _ -> Set<PeerId> in
return Set(accounts.map { $0.1.peerId })
@ -1210,10 +1210,27 @@ final class SharedApplicationContext {
}
return updated
}
}).start(next: { loggedOutAccountPeerIds in
|> map { loggedOutAccountPeerIds -> (AccountManager, Set<PeerId>) in
return (sharedContext.sharedContext.accountManager, loggedOutAccountPeerIds)
}
}).start(next: { [weak self] accountManager, loggedOutAccountPeerIds in
guard let strongSelf = self else {
return
}
for peerId in loggedOutAccountPeerIds {
deleteAllSendMessageIntents(accountPeerId: peerId)
}
let _ = (updateIntentsSettingsInteractively(accountManager: accountManager) { current in
var updated = current
for peerId in loggedOutAccountPeerIds {
if peerId == updated.account {
updated = updated.withUpdatedAccount(nil)
break
}
}
return updated
}).start()
}))
self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context.get() |> flatMap { WatchCommunicationManagerContext(context: $0.context) }, allowBackgroundTimeExtension: { timeout in

View File

@ -198,6 +198,16 @@ public class ShareRootControllerImpl {
globalInternalContext = internalContext
}
var immediatePeerId: PeerId?
if #available(iOS 13.2, *), let sendMessageIntent = self.getExtensionContext()?.intent as? INSendMessageIntent {
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
if let userId = Int32(string) {
immediatePeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
}
}
}
let account: Signal<(SharedAccountContextImpl, Account, [AccountWithInfo]), ShareAuthorizationError> = internalContext.sharedContext.accountManager.transaction { transaction -> (SharedAccountContextImpl, LoggingSettings) in
return (internalContext.sharedContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
}
@ -208,24 +218,36 @@ public class ShareRootControllerImpl {
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
return combineLatest(sharedContext.activeAccountsWithInfo, accountManager.transaction { transaction -> Set<AccountRecordId> in
return Set(transaction.getRecords().map { record in
return combineLatest(sharedContext.activeAccountsWithInfo, accountManager.transaction { transaction -> (Set<AccountRecordId>, PeerId?) in
let accountRecords = Set(transaction.getRecords().map { record in
return record.id
})
let intentsSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.intentsSettings) as? IntentsSettings ?? IntentsSettings.defaultSettings
return (accountRecords, intentsSettings.account)
})
|> castError(ShareAuthorizationError.self)
|> take(1)
|> mapToSignal { primaryAndAccounts, validAccountIds -> Signal<(SharedAccountContextImpl, Account, [AccountWithInfo]), ShareAuthorizationError> in
|> mapToSignal { primaryAndAccounts, validAccountIdsAndIntentsAccountId -> Signal<(SharedAccountContextImpl, Account, [AccountWithInfo]), ShareAuthorizationError> in
var (maybePrimary, accounts) = primaryAndAccounts
let (validAccountIds, intentsAccountId) = validAccountIdsAndIntentsAccountId
for i in (0 ..< accounts.count).reversed() {
if !validAccountIds.contains(accounts[i].account.id) {
accounts.remove(at: i)
}
}
if let _ = immediatePeerId, let intentsAccountId = intentsAccountId {
for account in accounts {
if account.peer.id == intentsAccountId {
maybePrimary = account.account.id
}
}
}
guard let primary = maybePrimary, validAccountIds.contains(primary) else {
return .fail(.unauthorized)
}
guard let info = accounts.first(where: { $0.account.id == primary }) else {
return .fail(.unauthorized)
}
@ -295,16 +317,6 @@ public class ShareRootControllerImpl {
|> then(.single(.done))
}
var immediatePeerId: PeerId?
if #available(iOS 13.0, *), let sendMessageIntent = self?.getExtensionContext()?.intent as? INSendMessageIntent {
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
if let userId = Int32(string) {
immediatePeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
}
}
}
let shareController = ShareController(context: context, subject: .fromExternal({ peerIds, additionalText, account in
if let strongSelf = self, let inputItems = strongSelf.getExtensionContext()?.inputItems, !inputItems.isEmpty, !peerIds.isEmpty {
let rawSignals = TGItemProviderSignals.itemSignals(forInputItems: inputItems)!

View File

@ -27,7 +27,7 @@ public struct IntentsSettings: PreferencesEntry, Equatable {
}
public init(decoder: PostboxDecoder) {
self.initiallyReset = decoder.decodeBoolForKey("initiallyReset_v2", orElse: false)
self.initiallyReset = decoder.decodeBoolForKey("initiallyReset_v1", orElse: false)
self.account = decoder.decodeOptionalInt64ForKey("account").flatMap { PeerId($0) }
self.contacts = decoder.decodeBoolForKey("contacts", orElse: true)
self.privateChats = decoder.decodeBoolForKey("privateChats", orElse: false)
@ -37,7 +37,7 @@ public struct IntentsSettings: PreferencesEntry, Equatable {
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeBool(self.initiallyReset, forKey: "initiallyReset_v2")
encoder.encodeBool(self.initiallyReset, forKey: "initiallyReset_v1")
if let account = self.account {
encoder.encodeInt64(account.toInt64(), forKey: "account")
} else {
@ -62,7 +62,7 @@ public struct IntentsSettings: PreferencesEntry, Equatable {
return lhs.initiallyReset == rhs.initiallyReset && lhs.account == rhs.account && lhs.contacts == rhs.contacts && lhs.privateChats == rhs.privateChats && lhs.savedMessages == rhs.savedMessages && lhs.groups == rhs.groups && lhs.onlyShared == rhs.onlyShared
}
public func withUpdatedAccount(_ account: PeerId) -> IntentsSettings {
public func withUpdatedAccount(_ account: PeerId?) -> IntentsSettings {
return IntentsSettings(initiallyReset: self.initiallyReset, account: account, contacts: self.contacts, privateChats: self.privateChats, savedMessages: self.savedMessages, groups: self.groups, onlyShared: self.onlyShared)
}