diff --git a/submodules/AppIntents/Sources/AppIntents.swift b/submodules/AppIntents/Sources/AppIntents.swift index aeb4d66687..7d009ab733 100644 --- a/submodules/AppIntents/Sources/AppIntents.swift +++ b/submodules/AppIntents/Sources/AppIntents.swift @@ -6,6 +6,7 @@ import Postbox import TelegramCore import SyncCore import SwiftSignalKit +import TelegramUIPreferences import TelegramPresentationData import AvatarNode import AccountContext @@ -30,33 +31,104 @@ private let savedMessagesAvatar: UIImage = { }! }() -public enum SendMessageIntentSubject { - case contact - case privateChat - case savedMessages - case group +public enum SendMessageIntentContext { + case chat + case share } -public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, peerIds: [PeerId]) { - if #available(iOSApplicationExtension 13.2, iOS 13.2, *) { - let _ = (account.postbox.transaction { transaction -> [Peer] in - var peers: [Peer] = [] - for peerId in peerIds { - if peerId.namespace != Namespaces.Peer.SecretChat, let peer = transaction.getPeer(peerId) { - peers.append(peer) - } - } - return peers +public enum SendMessageIntentSubject: CaseIterable { + case contact + case savedMessages + case privateChat + case group + + func toString() -> String { + switch self { + case .contact: + return "contact" + case .savedMessages: + return "savedMessages" + case .privateChat: + return "privateChat" + case .group: + return "group" } - |> mapToSignal { peers -> Signal<[(Peer, UIImage?)], NoError> in - var signals: [Signal<(Peer, UIImage?), NoError>] = [] - for peer in peers { + } +} + +public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, intentContext: SendMessageIntentContext, peerIds: [PeerId]) { + if #available(iOSApplicationExtension 13.2, iOS 13.2, *) { + let _ = (sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.intentsSettings]) + |> mapToSignal { sharedData -> Signal<[(Peer, SendMessageIntentSubject)], NoError> in + let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.intentsSettings] as? IntentsSettings) ?? IntentsSettings.defaultSettings + if let accountId = settings.account, accountId != account.peerId { + return .single([]) + } + if case .chat = intentContext, settings.onlyShared { + return .single([]) + } + return account.postbox.transaction { transaction -> [(Peer, SendMessageIntentSubject)] in + var peers: [(Peer, SendMessageIntentSubject)] = [] + for peerId in peerIds { + if peerId.namespace != Namespaces.Peer.SecretChat, let peer = transaction.getPeer(peerId) { + var subject: SendMessageIntentSubject? + let chatListIndex = transaction.getPeerChatListIndex(peerId) + if chatListIndex?.0 == Namespaces.PeerGroup.archive { + continue + } + if peerId.namespace == Namespaces.Peer.CloudUser { + if peerId == account.peerId { + if !settings.savedMessages { + continue + } + subject = .savedMessages + } + if transaction.isPeerContact(peerId: peerId) { + if !settings.contacts { + continue + } + subject = .contact + } else { + if !settings.privateChats { + continue + } + subject = .privateChat + } + } else if peerId.namespace == Namespaces.Peer.CloudGroup { + if !settings.groups { + continue + } + subject = .group + } else if let peer = peer as? TelegramChannel { + if case .group = peer.info { + if !settings.groups { + continue + } + subject = .group + } else { + continue + } + } else { + continue + } + + if let subject = subject { + peers.append((peer, subject)) + } + } + } + return peers + } + } + |> mapToSignal { peers -> Signal<[(Peer, SendMessageIntentSubject, UIImage?)], NoError> in + var signals: [Signal<(Peer, SendMessageIntentSubject, UIImage?), NoError>] = [] + for (peer, subject) in peers { if peer.id == account.peerId { - signals.append(.single((peer, savedMessagesAvatar))) + signals.append(.single((peer, subject, savedMessagesAvatar))) } else { let peerAndAvatar = (peerAvatarImage(account: account, peer: peer, authorOfMessage: nil, representation: peer.smallProfileImage, round: false) ?? .single(nil)) |> map { avatarImage in - return (peer, avatarImage) + return (peer, subject, avatarImage) } signals.append(peerAndAvatar) } @@ -66,7 +138,7 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou |> deliverOnMainQueue).start(next: { peers in let presentationData = sharedContext.currentPresentationData.with { $0 } - for (peer, avatarImage) in peers { + for (peer, subject, avatarImage) in peers { let recipientHandle = INPersonHandle(value: "tg\(peer.id.id)", type: .unknown) let displayTitle: String var nameComponents = PersonNameComponents() @@ -97,18 +169,31 @@ 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.groupIdentifier = "sendMessage_\(account.peerId.toInt64())" + //interaction.identifier = "sendMessage_\(account.peerId.toInt64())_\(peer.id.toInt64)" + interaction.groupIdentifier = "sendMessage_\(subject.toString())_\(account.peerId.toInt64())" interaction.donate() } }) } } -public func deleteAllSendMessageIntents(accountPeerId: PeerId? = nil) { +public func deleteSendMessageIntents(account: Account, peerId: PeerId) { + if #available(iOS 10.0, *) { + INInteraction.delete(with: ["sendMessage_\(account.peerId.toInt64())_\(peerId.toInt64)"]) + } +} + +public func deleteAllSendMessageIntents(accountPeerId: PeerId? = nil, subject: SendMessageIntentSubject? = nil) { if #available(iOS 10.0, *) { if let peerId = accountPeerId { - INInteraction.delete(with: "sendMessage_\(peerId.toInt64())") + if let subject = subject { + INInteraction.delete(with: "sendMessage_\(subject.toString())_\(peerId.toInt64())") + } else { + INInteraction.delete(with: "sendMessage_\(peerId.toInt64())") + for subject in SendMessageIntentSubject.allCases { + INInteraction.delete(with: "sendMessage_\(subject.toString())_\(peerId.toInt64())") + } + } } else { INInteraction.deleteAll() } diff --git a/submodules/SettingsUI/Sources/AccountUtils.swift b/submodules/SettingsUI/Sources/AccountUtils.swift index a33713f992..5e10545b35 100644 --- a/submodules/SettingsUI/Sources/AccountUtils.swift +++ b/submodules/SettingsUI/Sources/AccountUtils.swift @@ -6,7 +6,7 @@ import SyncCore import TelegramUIPreferences import AccountContext -func activeAccountsAndPeers(context: AccountContext) -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> { +func activeAccountsAndPeers(context: AccountContext, includePrimary: Bool = false) -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> { let sharedContext = context.sharedContext return context.sharedContext.activeAccounts |> mapToSignal { primary, activeAccounts, _ -> Signal<((Account, Peer)?, [(Account, Peer, Int32)]), NoError> in @@ -37,7 +37,8 @@ func activeAccountsAndPeers(context: AccountContext) -> Signal<((Account, Peer)? if let first = accounts.filter({ $0?.0.id == primary?.id }).first, let (account, peer, _) = first { primaryRecord = (account, peer) } - return (primaryRecord, accounts.filter({ $0?.0.id != primary?.id }).compactMap({ $0 })) + let accountRecords: [(Account, Peer, Int32)] = (includePrimary ? accounts : accounts.filter({ $0?.0.id != primary?.id })).compactMap({ $0 }) + return (primaryRecord, accountRecords) } } } diff --git a/submodules/SettingsUI/Sources/Data and Storage/IntentsSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/IntentsSettingsController.swift index fb6d78d0ae..3bc38b6ee9 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/IntentsSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/IntentsSettingsController.swift @@ -7,6 +7,7 @@ import TelegramCore import TelegramPresentationData import TelegramUIPreferences import ItemListUI +import ItemListPeerItem import AccountContext import AppIntents @@ -185,11 +186,10 @@ private enum IntentsSettingsControllerEntry: ItemListNodeEntry { switch self { case let .accountHeader(theme, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - // case let .browser(theme, title, application, identifier, selected, _): - // return WebBrowserItem(account: arguments.context.account, theme: theme, title: title, application: application, checked: selected, sectionId: self.section) { - // arguments.updateDefaultBrowser(identifier) - // } case let .account(theme, peer, selected, _): + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .dayFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: ""), nameDisplayOrder: .firstLast, account: arguments.context.account, peer: peer, height: .generic, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: false), revealOptions: nil, switchValue: ItemListPeerItemSwitch(value: selected, style: .check), enabled: true, selectable: true, sectionId: self.section, action: { + arguments.updateSettings { $0.withUpdatedAccount(peer.id) } + }, setPeerIdWithRevealedOptions: { _, _ in}, removePeer: { _ in }) return ItemListTextItem(presentationData: presentationData, text: .plain(""), sectionId: self.section) case let .accountInfo(theme, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) @@ -232,18 +232,18 @@ private enum IntentsSettingsControllerEntry: ItemListNodeEntry { } } -private func intentsSettingsControllerEntries(context: AccountContext, presentationData: PresentationData, settings: IntentsSettings) -> [IntentsSettingsControllerEntry] { +private func intentsSettingsControllerEntries(context: AccountContext, presentationData: PresentationData, settings: IntentsSettings, accounts: [(Account, Peer)]) -> [IntentsSettingsControllerEntry] { var entries: [IntentsSettingsControllerEntry] = [] - entries.append(.accountHeader(presentationData.theme, presentationData.strings.IntentsSettings_MainAccount.uppercased())) - - var index: Int32 = 0 -// for option in options { -// entries.append(.browser(presentationData.theme, option.title, option.application, option.identifier, option.identifier == selectedBrowser, index)) -// index += 1 -// } - - //entries.append(.accountInfo(presentationData.theme, presentationData.strings.IntentsSettings_MainAccountInfo)) + if accounts.count > 1 { + entries.append(.accountHeader(presentationData.theme, presentationData.strings.IntentsSettings_MainAccount.uppercased())) + var index: Int32 = 0 + for (_, peer) in accounts { + entries.append(.account(presentationData.theme, peer, peer.id == settings.account, index)) + index += 1 + } + entries.append(.accountInfo(presentationData.theme, presentationData.strings.IntentsSettings_MainAccountInfo)) + } entries.append(.chatsHeader(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedChats.uppercased())) entries.append(.contacts(presentationData.theme, presentationData.strings.IntentsSettings_SuggestedChatsContacts, settings.contacts)) @@ -286,13 +286,13 @@ public func intentsSettingsController(context: AccountContext) -> ViewController presentControllerImpl?(actionSheet) }) - let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.intentsSettings])) + let signal = combineLatest(context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.intentsSettings]), activeAccountsAndPeers(context: context, includePrimary: true)) |> deliverOnMainQueue - |> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, sharedData, accounts -> (ItemListControllerState, (ItemListNodeState, Any)) in let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.intentsSettings] as? IntentsSettings) ?? IntentsSettings.defaultSettings let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.IntentsSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: intentsSettingsControllerEntries(context: context, presentationData: presentationData, settings: settings), style: .blocks, animateChanges: false) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: intentsSettingsControllerEntries(context: context, presentationData: presentationData, settings: settings, accounts: accounts.1.map { ($0.0, $0.1) }), style: .blocks, animateChanges: false) return (controllerState, (listState, arguments)) } diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index 1f5bfd5785..9a1a4a3920 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -540,7 +540,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } if let account = self.account { - donateSendMessageIntent(account: account, sharedContext: self.sharedContext, peerIds: peerIds) + donateSendMessageIntent(account: account, sharedContext: self.sharedContext, intentContext: .share, peerIds: peerIds) } if let signal = self.share?(self.inputFieldNode.text, peerIds) { diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index ac22258210..d563a10680 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -2812,7 +2812,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - donateSendMessageIntent(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, peerIds: [peerId]) + donateSendMessageIntent(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, intentContext: .chat, peerIds: [peerId]) } } @@ -6021,7 +6021,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, peerIds: [peerId]) + donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, intentContext: .chat, peerIds: [peerId]) } else { self.presentScheduleTimePicker(dismissByTapOutside: false, completion: { [weak self] time in if let strongSelf = self {