From b69a0b6b3d0ff38c1f4984d35d6916fb1d9548a7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 5 Jun 2022 17:25:10 +0400 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/AccountContext.swift | 19 +++- .../Sources/PeerSelectionController.swift | 4 + .../Sources/Node/ChatListNode.swift | 34 ++++++- .../ApiUtils/StoreMessage_Telegram.swift | 4 +- .../Sources/ApiUtils/TelegramMediaFile.swift | 5 +- .../TelegramCore/Sources/ApiUtils/Theme.swift | 2 +- .../PendingMessageUploadedContent.swift | 14 +-- .../StandaloneUploadedMedia.swift | 4 +- .../Sources/State/AvailableReactions.swift | 4 +- .../ManagedSecretChatOutgoingOperations.swift | 6 ++ .../SyncCore/SyncCore_TelegramMediaFile.swift | 6 ++ .../TelegramUI/Sources/ChatController.swift | 6 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 95 +++++++++++++++++-- submodules/TelegramUI/Sources/OpenUrl.swift | 6 ++ .../UrlHandling/Sources/UrlHandling.swift | 40 +++++++- 16 files changed, 216 insertions(+), 35 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 0ba11fbb30..7e53e38a3c 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7692,3 +7692,5 @@ Sorry for the inconvenience."; "Chat.AudioTranscriptionFeedbackTip" = "Thank you for your feedback."; "Message.AudioTranscription.ErrorEmpty" = "No speech detected"; "Message.AudioTranscription.ErrorTooLong" = "The audio is too long"; + +"WebApp.SelectChat" = "Select Chat"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 3d2093292c..f8e10cb0a8 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -176,6 +176,23 @@ public enum ResolvedUrlSettingsSection { case devices } +public struct ResolvedBotChoosePeerTypes: OptionSet { + public var rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + public init() { + self.rawValue = 0 + } + + public static let users = ResolvedBotChoosePeerTypes(rawValue: 1) + public static let bots = ResolvedBotChoosePeerTypes(rawValue: 2) + public static let groups = ResolvedBotChoosePeerTypes(rawValue: 4) + public static let channels = ResolvedBotChoosePeerTypes(rawValue: 16) +} + public struct ResolvedBotAdminRights: OptionSet { public var rawValue: UInt32 @@ -263,7 +280,7 @@ public enum ResolvedUrl { case settings(ResolvedUrlSettingsSection) case joinVoiceChat(PeerId, String?) case importStickers - case startAttach(peerId: PeerId, payload: String?) + case startAttach(peerId: PeerId, payload: String?, choose: ResolvedBotChoosePeerTypes?) case invoice(slug: String, invoice: TelegramMediaInvoice) case premiumOffer(reference: String?) } diff --git a/submodules/AccountContext/Sources/PeerSelectionController.swift b/submodules/AccountContext/Sources/PeerSelectionController.swift index 8bd9683cb4..5d3a4e4307 100644 --- a/submodules/AccountContext/Sources/PeerSelectionController.swift +++ b/submodules/AccountContext/Sources/PeerSelectionController.swift @@ -30,6 +30,10 @@ public struct ChatListNodePeersFilter: OptionSet { public static let excludeChannels = ChatListNodePeersFilter(rawValue: 1 << 12) public static let onlyGroupsAndChannels = ChatListNodePeersFilter(rawValue: 1 << 13) + + public static let excludeGroups = ChatListNodePeersFilter(rawValue: 1 << 14) + public static let excludeUsers = ChatListNodePeersFilter(rawValue: 1 << 15) + public static let excludeBots = ChatListNodePeersFilter(rawValue: 1 << 16) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 5220892de5..515dbd6d2b 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -997,7 +997,39 @@ public final class ChatListNode: ListView { guard !filter.contains(.excludeSavedMessages) || !peer.peerId.isReplies else { return false } guard !filter.contains(.excludeSecretChats) || peer.peerId.namespace != Namespaces.Peer.SecretChat else { return false } guard !filter.contains(.onlyPrivateChats) || peer.peerId.namespace == Namespaces.Peer.CloudUser else { return false } - + + if let peer = peer.peer { + switch peer { + case let .user(user): + if user.botInfo != nil { + if filter.contains(.excludeBots) { + return false + } + } else { + if filter.contains(.excludeUsers) { + return false + } + } + case .legacyGroup: + if filter.contains(.excludeGroups) { + return false + } + case let .channel(channel): + switch channel.info { + case .broadcast: + if filter.contains(.excludeChannels) { + return false + } + case .group: + if filter.contains(.excludeGroups) { + return false + } + } + default: + break + } + } + if filter.contains(.onlyGroupsAndChannels) { if case .channel = peer.chatMainPeer { } else if case .legacyGroup = peer.chatMainPeer { diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 22b1f62a5f..d02ade20f0 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -280,9 +280,9 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI case let .messageMediaGeoLive(_, geo, heading, period, proximityNotificationRadius): let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: proximityNotificationRadius, heading: heading) return (mediaMap, nil) - case let .messageMediaDocument(_, document, ttlSeconds): + case let .messageMediaDocument(flags, document, ttlSeconds): if let document = document { - if let mediaFile = telegramMediaFileFromApiDocument(document) { + if let mediaFile = telegramMediaFileFromApiDocument(document, noPremium: (flags & (1 << 3)) != 0) { return (mediaFile, ttlSeconds) } } else { diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index e8517f499d..aeba4307ac 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift @@ -141,11 +141,14 @@ func telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: Int32, return (immediateThumbnailData, representations) } -func telegramMediaFileFromApiDocument(_ document: Api.Document) -> TelegramMediaFile? { +func telegramMediaFileFromApiDocument(_ document: Api.Document, noPremium: Bool = false) -> TelegramMediaFile? { switch document { case let .document(_, id, accessHash, fileReference, _, mimeType, size, thumbs, videoThumbs, dcId, attributes): var parsedAttributes = telegramMediaFileAttributesFromApiAttributes(attributes) parsedAttributes.append(.hintIsValidated) + if noPremium { + parsedAttributes.append(.NoPremium) + } let (immediateThumbnail, previewRepresentations) = telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: dcId, documentId: id, accessHash: accessHash, fileReference: fileReference.makeData(), sizes: thumbs ?? []) diff --git a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift index 378041e7da..38f4fb1421 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift @@ -8,7 +8,7 @@ extension TelegramTheme { convenience init(apiTheme: Api.Theme) { switch apiTheme { case let .theme(flags, id, accessHash, slug, title, document, settings, emoticon, installCount): - self.init(id: id, accessHash: accessHash, slug: slug, emoticon: emoticon, title: title, file: document.flatMap(telegramMediaFileFromApiDocument), settings: settings?.compactMap(TelegramThemeSettings.init(apiThemeSettings:)), isCreator: (flags & 1 << 0) != 0, isDefault: (flags & 1 << 1) != 0, installCount: installCount) + self.init(id: id, accessHash: accessHash, slug: slug, emoticon: emoticon, title: title, file: document.flatMap { telegramMediaFileFromApiDocument($0) }, settings: settings?.compactMap(TelegramThemeSettings.init(apiThemeSettings:)), isCreator: (flags & 1 << 0) != 0, isDefault: (flags & 1 << 1) != 0, installCount: installCount) } } } diff --git a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift index 450c066a22..e5eab30f3f 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift @@ -511,10 +511,6 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF attributes.append(.documentAttributeSticker(flags: flags, alt: displayText, stickerset: stickerSet, maskCoords: inputMaskCoords)) case .HasLinkedStickers: attributes.append(.documentAttributeHasStickers) - case .hintFileIsLarge: - break - case .hintIsValidated: - break case let .Video(duration, size, videoFlags): var flags: Int32 = 0 if videoFlags.contains(.instantRoundVideo) { @@ -542,6 +538,12 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF waveformBuffer = Buffer(data: waveform) } attributes.append(.documentAttributeAudio(flags: flags, duration: Int32(duration), title: title, performer: performer, waveform: waveformBuffer)) + case .hintFileIsLarge: + break + case .hintIsValidated: + break + case .NoPremium: + break } } return attributes @@ -782,8 +784,8 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili |> mapError { _ -> PendingMessageUploadError in return .generic } |> mapToSignal { result -> Signal in switch result { - case let .messageMediaDocument(_, document, _): - if let document = document, let mediaFile = telegramMediaFileFromApiDocument(document), let resource = mediaFile.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference { + case let .messageMediaDocument(flags, document, _): + if let document = document, let mediaFile = telegramMediaFileFromApiDocument(document, noPremium: (flags & (1 << 3)) != 0), let resource = mediaFile.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference { return maybeCacheUploadedResource(postbox: postbox, key: referenceKey, result: .content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), ttlSeconds: nil, query: nil), text), reuploadInfo: nil)), media: mediaFile) } default: diff --git a/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift b/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift index 47d33f6db9..c1e49909a2 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift @@ -162,9 +162,9 @@ public func standaloneUploadedFile(account: Account, peerId: PeerId, text: Strin |> mapError { _ -> StandaloneUploadMediaError in return .generic } |> mapToSignal { media -> Signal in switch media { - case let .messageMediaDocument(_, document, _): + case let .messageMediaDocument(flags, document, _): if let document = document { - if let mediaFile = telegramMediaFileFromApiDocument(document) { + if let mediaFile = telegramMediaFileFromApiDocument(document, noPremium: (flags & (1 << 3)) != 0) { return .single(.result(.media(.standalone(media: mediaFile)))) } } diff --git a/submodules/TelegramCore/Sources/State/AvailableReactions.swift b/submodules/TelegramCore/Sources/State/AvailableReactions.swift index 105613876a..724dc5c18f 100644 --- a/submodules/TelegramCore/Sources/State/AvailableReactions.swift +++ b/submodules/TelegramCore/Sources/State/AvailableReactions.swift @@ -214,8 +214,8 @@ private extension AvailableReactions.Reaction { guard let effectAnimationFile = telegramMediaFileFromApiDocument(effectAnimation) else { return nil } - let aroundAnimationFile = aroundAnimation.flatMap(telegramMediaFileFromApiDocument) - let centerAnimationFile = centerIcon.flatMap(telegramMediaFileFromApiDocument) + let aroundAnimationFile = aroundAnimation.flatMap { telegramMediaFileFromApiDocument($0) } + let centerAnimationFile = centerIcon.flatMap { telegramMediaFileFromApiDocument($0) } let isEnabled = (flags & (1 << 0)) == 0 let isPremium = (flags & (1 << 2)) != 0 self.init( diff --git a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift index 46877da46c..8cd7216db5 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift @@ -542,6 +542,8 @@ private func decryptedAttributes46(_ attributes: [TelegramMediaFileAttribute], t break case .hintIsValidated: break + case .NoPremium: + break } } return result @@ -601,6 +603,8 @@ private func decryptedAttributes73(_ attributes: [TelegramMediaFileAttribute], t break case .hintIsValidated: break + case .NoPremium: + break } } return result @@ -660,6 +664,8 @@ private func decryptedAttributes101(_ attributes: [TelegramMediaFileAttribute], break case .hintIsValidated: break + case .NoPremium: + break } } return result diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 230ad8add6..f0eff5069c 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -10,6 +10,7 @@ private let typeAudio: Int32 = 5 private let typeHasLinkedStickers: Int32 = 6 private let typeHintFileIsLarge: Int32 = 7 private let typeHintIsValidated: Int32 = 8 +private let typeNoPremium: Int32 = 9 public enum StickerPackReference: PostboxCoding, Hashable, Equatable { case id(id: Int64, accessHash: Int64) @@ -144,6 +145,7 @@ public enum TelegramMediaFileAttribute: PostboxCoding { case HasLinkedStickers case hintFileIsLarge case hintIsValidated + case NoPremium public init(decoder: PostboxDecoder) { let type: Int32 = decoder.decodeInt32ForKey("t", orElse: 0) @@ -171,6 +173,8 @@ public enum TelegramMediaFileAttribute: PostboxCoding { self = .hintFileIsLarge case typeHintIsValidated: self = .hintIsValidated + case typeNoPremium: + self = .NoPremium default: preconditionFailure() } @@ -225,6 +229,8 @@ public enum TelegramMediaFileAttribute: PostboxCoding { encoder.encodeInt32(typeHintFileIsLarge, forKey: "t") case .hintIsValidated: encoder.encodeInt32(typeHintIsValidated, forKey: "t") + case .NoPremium: + encoder.encodeInt32(typeNoPremium, forKey: "t") } } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index d1c0836a78..187fd87099 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10778,11 +10778,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let peer = self.presentationInterfaceState.renderedPeer?.peer else { return } - - if botId != nil && peer.id.namespace != Namespaces.Peer.CloudUser { - return - } - + let context = self.context let inputIsActive = self.presentationInterfaceState.inputMode == .text diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 79648135f8..490c7bc021 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -553,7 +553,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur present(controller, nil) } } - case let .startAttach(peerId, payload): + case let .startAttach(peerId, payload, choose): let presentError: (String) -> Void = { errorText in present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: errorText), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return true @@ -561,23 +561,100 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur } let _ = (context.engine.messages.attachMenuBots() |> deliverOnMainQueue).start(next: { attachMenuBots in - if let _ = attachMenuBots.firstIndex(where: { $0.peer.id == peerId }) { - if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload), useExisting: true)) + func filterChooseTypes(_ chooseTypes: ResolvedBotChoosePeerTypes?, peerTypes: AttachMenuBots.Bot.PeerFlags) -> ResolvedBotChoosePeerTypes? { + var chooseTypes = chooseTypes + if chooseTypes != nil { + if !peerTypes.contains(.user) { + chooseTypes?.remove(.users) + } + if !peerTypes.contains(.bot) { + chooseTypes?.remove(.bots) + } + if !peerTypes.contains(.group) { + chooseTypes?.remove(.groups) + } + if !peerTypes.contains(.channel) { + chooseTypes?.remove(.channels) + } + } + return (chooseTypes?.isEmpty ?? true) ? nil : chooseTypes + } + + if let bot = attachMenuBots.first(where: { $0.peer.id == peerId }) { + let choose = filterChooseTypes(choose, peerTypes: bot.peerTypes) + + if let choose = choose { + var filters: ChatListNodePeersFilter = [] + filters.insert(.onlyWriteable) + filters.insert(.excludeDisabled) + + if !choose.contains(.users) { + filters.insert(.excludeUsers) + } + if !choose.contains(.bots) { + filters.insert(.excludeBots) + } + if !choose.contains(.groups) { + filters.insert(.excludeGroups) + } + if !choose.contains(.channels) { + filters.insert(.excludeChannels) + } + + if let navigationController = navigationController { + let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, updatedPresentationData: updatedPresentationData, filter: filters, hasChatListSelector: true, hasContactSelector: false, title: presentationData.strings.WebApp_SelectChat)) + controller.peerSelected = { peer in + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: bot.peer.id, payload: payload), useExisting: true)) + } + navigationController.pushViewController(controller) + } } else { - presentError(presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError) + if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload), useExisting: true)) + } else { + presentError(presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError) + } } } else { let _ = (context.engine.messages.getAttachMenuBot(botId: peerId) |> deliverOnMainQueue).start(next: { bot in - let peer = EnginePeer(bot.peer) - let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), icons: bot.icons, completion: { + let choose = filterChooseTypes(choose, peerTypes: bot.peerTypes) + + let botPeer = EnginePeer(bot.peer) + let controller = addWebAppToAttachmentController(context: context, peerName: botPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), icons: bot.icons, completion: { let _ = (context.engine.messages.addBotToAttachMenu(botId: peerId) |> deliverOnMainQueue).start(error: { _ in presentError(presentationData.strings.WebApp_AddToAttachmentUnavailableError) }, completed: { - if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peer.id, payload: payload), useExisting: true)) + if let choose = choose { + var filters: ChatListNodePeersFilter = [] + filters.insert(.onlyWriteable) + filters.insert(.excludeDisabled) + + if !choose.contains(.users) { + filters.insert(.excludeUsers) + } + if !choose.contains(.bots) { + filters.insert(.excludeBots) + } + if !choose.contains(.groups) { + filters.insert(.excludeGroups) + } + if !choose.contains(.channels) { + filters.insert(.excludeChannels) + } + + if let navigationController = navigationController { + let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, updatedPresentationData: updatedPresentationData, filter: filters, hasChatListSelector: true, hasContactSelector: false, title: presentationData.strings.WebApp_SelectChat)) + controller.peerSelected = { peer in + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload), useExisting: true)) + } + navigationController.pushViewController(controller) + } + } else { + if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload), useExisting: true)) + } } }) }) diff --git a/submodules/TelegramUI/Sources/OpenUrl.swift b/submodules/TelegramUI/Sources/OpenUrl.swift index 307ea06577..310c76af18 100644 --- a/submodules/TelegramUI/Sources/OpenUrl.swift +++ b/submodules/TelegramUI/Sources/OpenUrl.swift @@ -635,6 +635,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur var voiceChat: String? var attach: String? var startAttach: String? + var choose: String? if let queryItems = components.queryItems { for queryItem in queryItems { if let value = queryItem.value { @@ -658,6 +659,8 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur attach = value } else if queryItem.name == "startattach" { startAttach = value + } else if queryItem.name == "choose" { + choose = value } } else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) { voiceChat = "" @@ -697,6 +700,9 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur } else { result += "?startattach" } + if let choose = choose { + result += "&choose=\(choose)" + } } convertedUrl = result } diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index 79f5ec7066..1e7392d6b5 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -88,7 +88,7 @@ public enum ParsedInternalUrl { case wallpaper(WallpaperUrlParameter) case theme(String) case phone(String, String?, String?) - case startAttach(String, String?) + case startAttach(String, String?, String?) } private enum ParsedUrl { @@ -210,12 +210,26 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? { } else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) { return .peerName(peerName, .voiceChat(value)) } else if queryItem.name == "startattach" { - return .startAttach(peerName, value) + var choose: String? + for queryItem in queryItems { + if queryItem.name == "choose", let value = queryItem.value { + choose = value + break + } + } + return .startAttach(peerName, value, choose) } } else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) { return .peerName(peerName, .voiceChat(nil)) } else if queryItem.name == "startattach" { - return .startAttach(peerName, nil) + var choose: String? + for queryItem in queryItems { + if queryItem.name == "choose", let value = queryItem.value { + choose = value + break + } + } + return .startAttach(peerName, nil, choose) } } } @@ -591,7 +605,23 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl) return .single(.wallpaper(parameter)) case let .theme(slug): return .single(.theme(slug)) - case let .startAttach(name, payload): + case let .startAttach(name, payload, chooseValue): + var choose: ResolvedBotChoosePeerTypes = [] + if let chooseValue = chooseValue?.lowercased() { + let components = chooseValue.components(separatedBy: "+") + if components.contains("users") { + choose.insert(.users) + } + if components.contains("bots") { + choose.insert(.bots) + } + if components.contains("groups") { + choose.insert(.groups) + } + if components.contains("channels") { + choose.insert(.channels) + } + } return context.engine.peers.resolvePeerByName(name: name) |> take(1) |> mapToSignal { peer -> Signal in @@ -599,7 +629,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl) } |> mapToSignal { peer -> Signal in if let peer = peer { - return .single(.startAttach(peerId: peer.id, payload: payload)) + return .single(.startAttach(peerId: peer.id, payload: payload, choose: !choose.isEmpty ? choose : nil)) } else { return .single(.inaccessiblePeer) }