From 9f0dc8c1d8cc12d2a2cde0e2ba0824ae8b34cdb4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 3 Oct 2022 16:45:43 +0300 Subject: [PATCH] Update API [skip ci] --- submodules/ChatListUI/BUILD | 1 + .../Sources/ChatListController.swift | 8 +- .../Sources/ChatListControllerNode.swift | 2 +- .../Sources/ChatListSearchListPaneNode.swift | 2 +- .../Sources/ViewControllerComponent.swift | 14 + .../InviteContactsControllerNode.swift | 2 +- .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/InviteLinkViewController.swift | 4 +- .../Sources/MediaPickerSelectedListNode.swift | 2 +- .../Sources/DeviceContactInfoController.swift | 2 +- .../Sources/PremiumLimitsListScreen.swift | 2 + .../BubbleSettingsController.swift | 4 +- .../ForwardPrivacyChatPreviewItem.swift | 2 +- .../Reactions/ReactionChatPreviewItem.swift | 2 +- .../TextSizeSelectionController.swift | 20 +- .../ThemeAccentColorControllerNode.swift | 16 +- .../Themes/ThemePreviewControllerNode.swift | 22 +- .../Themes/ThemeSettingsChatPreviewItem.swift | 4 +- .../Sources/Themes/WallpaperGalleryItem.swift | 4 +- .../Sources/UsernameSetupController.swift | 16 +- submodules/TelegramApi/Sources/Api0.swift | 7 +- submodules/TelegramApi/Sources/Api21.swift | 134 +++- submodules/TelegramApi/Sources/Api29.swift | 79 +- submodules/TelegramApi/Sources/Api3.swift | 88 ++- .../Account/AccountIntermediateState.swift | 4 +- .../Sources/Account/AccountManager.swift | 1 + .../Sources/ApiUtils/ApiGroupOrChannel.swift | 12 +- .../Sources/ApiUtils/TelegramUser.swift | 21 +- .../ApiUtils/TelegramUserPresence.swift | 2 +- .../State/AccountStateManagementUtils.swift | 2 +- .../Sources/State/UpdatesApiUtils.swift | 4 +- .../SyncCore/SyncCore_TelegramChannel.swift | 19 +- .../SyncCore/SyncCore_TelegramUser.swift | 64 +- .../TelegramEngine/Calls/GroupCalls.swift | 2 +- .../TelegramEngine/Messages/AdMessages.swift | 3 +- .../TelegramEngine/Messages/SendAsPeers.swift | 2 +- .../TelegramEngine/Peers/AddressNames.swift | 118 +++ .../Peers/InactiveChannels.swift | 2 +- .../TelegramEngine/Peers/SearchPeers.swift | 2 +- .../Peers/TelegramEnginePeers.swift | 10 +- .../UpdatedAccountPrivacySettings.swift | 2 +- submodules/TelegramCore/Sources/Themes.swift | 8 +- .../TelegramCore/Sources/UpdatePeers.swift | 4 +- submodules/TelegramUI/BUILD | 1 + .../Sources/EmojiStatusComponent.swift | 62 ++ .../Sources/EmojiPagerContentComponent.swift | 120 ++- .../Components/ForumCreateTopicScreen/BUILD | 37 + .../Sources/ForumCreateTopicScreen.swift | 710 ++++++++++++++++++ .../PhoneCall.imageset/Contents.json | 12 + .../PhoneCall.imageset/phonecall_24.pdf | 424 +++++++++++ .../TelegramUI/Sources/ChatBotInfoItem.swift | 2 +- .../Sources/ChatControllerNode.swift | 50 ++ .../ChatMessageActionButtonsNode.swift | 31 +- .../Sources/ChatMessageBubbleItemNode.swift | 4 +- .../TelegramUI/Sources/ChatMessageItem.swift | 2 +- .../ChatRecentActionsControllerNode.swift | 1 + .../ChatRecentActionsHistoryTransition.swift | 2 +- .../Sources/ChatRestrictedNode.swift | 1 - .../PeerInfoScreenLabeledValueItem.swift | 4 +- .../PeerInfo/PeerInfoPaneContainerNode.swift | 8 + .../Sources/PeerInfo/PeerInfoScreen.swift | 75 +- .../Sources/PollResultsController.swift | 2 +- .../TranslateUI/Sources/TranslateScreen.swift | 2 + .../Sources/WallpaperBackgroundNode.swift | 22 +- 64 files changed, 2047 insertions(+), 246 deletions(-) create mode 100644 submodules/TelegramUI/Components/ForumCreateTopicScreen/BUILD create mode 100644 submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/phonecall_24.pdf delete mode 100644 submodules/TelegramUI/Sources/ChatRestrictedNode.swift diff --git a/submodules/ChatListUI/BUILD b/submodules/ChatListUI/BUILD index 1a338b0ca4..4692925d8e 100644 --- a/submodules/ChatListUI/BUILD +++ b/submodules/ChatListUI/BUILD @@ -78,6 +78,7 @@ swift_library( "//submodules/TelegramUI/Components/EmojiStatusComponent", "//submodules/TelegramUI/Components/EmojiStatusSelectionComponent", "//submodules/TelegramUI/Components/EntityKeyboard", + "//submodules/TelegramUI/Components/ForumCreateTopicScreen:ForumCreateTopicScreen", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 0944a9d917..06afd9705a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -36,6 +36,7 @@ import MultiAnimationRenderer import EmojiStatusSelectionComponent import EntityKeyboard import TelegramStringFormatting +import ForumCreateTopicScreen private func fixListNodeScrolling(_ listNode: ListView, searchNode: NavigationBarSearchContentNode) -> Bool { if listNode.scroller.isDragging { @@ -2020,8 +2021,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } @objc private func editPressed() { - if case .forum = self.location { - self.forumChannelTracker?.createTopic(title: "Topic#\(Int.random(in: 0 ..< 100000))") + if case let .forum(peerId) = self.location { + let controller = ForumCreateTopicScreen(context: self.context, peerId: peerId, mode: .create) + controller.navigationPresentation = .modal + self.push(controller) +// self.forumChannelTracker?.createTopic(title: "Topic#\(Int.random(in: 0 ..< 100000))") return } diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 4e04159d39..18d6d693f0 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -179,7 +179,7 @@ private final class ChatListShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 04572586cc..ae333dd4b5 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -2946,7 +2946,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) let timestamp1: Int32 = 100000 var peers: [EnginePeer.Id: EnginePeer] = [:] peers[peer1.id] = peer1 diff --git a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift index b635d9e54f..156f4aab63 100644 --- a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift +++ b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift @@ -24,7 +24,9 @@ open class ViewControllerComponentContainer: ViewController { public let statusBarHeight: CGFloat public let navigationHeight: CGFloat public let safeInsets: UIEdgeInsets + public let inputHeight: CGFloat public let metrics: LayoutMetrics + public let deviceMetrics: DeviceMetrics public let isVisible: Bool public let theme: PresentationTheme public let strings: PresentationStrings @@ -35,7 +37,9 @@ open class ViewControllerComponentContainer: ViewController { statusBarHeight: CGFloat, navigationHeight: CGFloat, safeInsets: UIEdgeInsets, + inputHeight: CGFloat, metrics: LayoutMetrics, + deviceMetrics: DeviceMetrics, isVisible: Bool, theme: PresentationTheme, strings: PresentationStrings, @@ -45,7 +49,9 @@ open class ViewControllerComponentContainer: ViewController { self.statusBarHeight = statusBarHeight self.navigationHeight = navigationHeight self.safeInsets = safeInsets + self.inputHeight = inputHeight self.metrics = metrics + self.deviceMetrics = deviceMetrics self.isVisible = isVisible self.theme = theme self.strings = strings @@ -67,9 +73,15 @@ open class ViewControllerComponentContainer: ViewController { if lhs.safeInsets != rhs.safeInsets { return false } + if lhs.inputHeight != rhs.inputHeight { + return false + } if lhs.metrics != rhs.metrics { return false } + if lhs.deviceMetrics != rhs.deviceMetrics { + return false + } if lhs.isVisible != rhs.isVisible { return false } @@ -125,7 +137,9 @@ open class ViewControllerComponentContainer: ViewController { statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right), + inputHeight: layout.inputHeight ?? 0.0, metrics: layout.metrics, + deviceMetrics: layout.deviceMetrics, isVisible: self.currentIsVisible, theme: self.theme ?? self.presentationData.theme, strings: self.presentationData.strings, diff --git a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift index 37ef8dbb1e..faba0442e6 100644 --- a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift @@ -56,7 +56,7 @@ private enum InviteContactsEntry: Comparable, Identifiable { } else { status = .none } - let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: status, enabled: true, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: ChatListSearchItemHeader(type: .contacts, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in interaction.toggleContact(id) }) diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 45ddae7822..d3e37e1c43 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1403,7 +1403,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { }, openUrl: { _ in }, openPeer: { _ in }, showAll: false) - let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let controller = LocationViewController(context: self.context, subject: message, params: controllerParams) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index 223167f092..c0ef30c836 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -690,7 +690,7 @@ public final class InviteLinkViewController: ViewController { if requestsState.importers.isEmpty && requestsState.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) for i in 0 ..< count { entries.append(.request(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true)) } @@ -724,7 +724,7 @@ public final class InviteLinkViewController: ViewController { if state.importers.isEmpty && state.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) for i in 0 ..< count { entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true)) } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index 757be8df63..36e33fc96e 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -728,7 +728,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) var peers = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview diff --git a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift index 25312f5cae..f38b84554a 100644 --- a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift +++ b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift @@ -652,7 +652,7 @@ private func deviceContactInfoEntries(account: Account, engine: TelegramEngine, firstName = presentationData.strings.Message_Contact } - entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare)) + entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare)) if !selecting { if let _ = peer { diff --git a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift index 9c083cf901..7eef3f2c21 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift @@ -630,7 +630,9 @@ public class PremimLimitsListScreen: ViewController { statusBarHeight: 0.0, navigationHeight: navigationHeight, safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: footerHeight, right: layout.safeInsets.right), + inputHeight: layout.inputHeight ?? 0.0, metrics: layout.metrics, + deviceMetrics: layout.deviceMetrics, isVisible: self.currentIsVisible, theme: self.theme ?? self.presentationData.theme, strings: self.presentationData.strings, diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index e224cbabe3..c94c8c1b81 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -163,8 +163,8 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index 9bdbbc0ab4..bc6b2838c6 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -145,7 +145,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) diff --git a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift index 4a918adcc9..eb238e4687 100644 --- a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift @@ -274,7 +274,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let messageText = item.strings.Settings_QuickReactionSetup_DemoMessageText diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index f312e97552..7680d6b85b 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -294,14 +294,14 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView ) } - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [])) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [])) + let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) let timestamp = self.referenceTimestamp @@ -417,8 +417,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index a71488a3af..7edece8831 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -914,12 +914,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate ) } - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [])) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) let timestamp = self.referenceTimestamp @@ -1007,8 +1007,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) var sampleMessages: [Message] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 7bf64fec62..5ef9cc12e9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -439,15 +439,15 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let chatListPresentationData = ChatListPresentationData(theme: self.previewTheme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true) - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) - let peer7: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [])) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [])) + let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) + let peer7: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])) let timestamp = self.referenceTimestamp @@ -568,8 +568,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) var sampleMessages: [Message] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index 92fc5df5ed..31082bf2d9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -155,11 +155,11 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) if let (author, text) = messageItem.reply { - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) + let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)) } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index 2745591f84..5625a33427 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -1033,8 +1033,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) var topMessageText = "" var bottomMessageText = "" diff --git a/submodules/SettingsUI/Sources/UsernameSetupController.swift b/submodules/SettingsUI/Sources/UsernameSetupController.swift index ab13d69db1..b2d5c3341a 100644 --- a/submodules/SettingsUI/Sources/UsernameSetupController.swift +++ b/submodules/SettingsUI/Sources/UsernameSetupController.swift @@ -268,10 +268,20 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, } var infoText = presentationData.strings.Username_Help - infoText += "\n\n" - let hintText = presentationData.strings.Username_LinkHint(currentAddressName.replacingOccurrences(of: "[", with: "").replacingOccurrences(of: "]", with: "")).string.replacingOccurrences(of: "]", with: "]()") - infoText += hintText + + let otherUsernames = peer.usernames.filter { !$0.flags.contains(.isEditable) } + + if otherUsernames.isEmpty { + infoText += "\n\n" + let hintText = presentationData.strings.Username_LinkHint(currentAddressName.replacingOccurrences(of: "[", with: "").replacingOccurrences(of: "]", with: "")).string.replacingOccurrences(of: "]", with: "]()") + infoText += hintText + } entries.append(.publicLinkInfo(presentationData.theme, infoText)) + + if !otherUsernames.isEmpty { + entries.append(.additionalLinkHeader(presentationData.theme, presentationData.strings.Username_LinksOrder)) + entries.append(.additionalLinkInfo(presentationData.theme, presentationData.strings.Username_LinksOrderInfo)) + } } return entries diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index dc9b72b62f..0311b7ccfb 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -143,7 +143,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-531931925] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsMentions($0) } dict[-566281095] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsRecent($0) } dict[106343499] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsSearch($0) } - dict[-2107528095] = { return Api.Chat.parse_channel($0) } + dict[-2094689180] = { return Api.Chat.parse_channel($0) } dict[399807445] = { return Api.Chat.parse_channelForbidden($0) } dict[1103884886] = { return Api.Chat.parse_chat($0) } dict[693512293] = { return Api.Chat.parse_chatEmpty($0) } @@ -869,7 +869,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1886646706] = { return Api.UrlAuthResult.parse_urlAuthResultAccepted($0) } dict[-1445536993] = { return Api.UrlAuthResult.parse_urlAuthResultDefault($0) } dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) } - dict[1570352622] = { return Api.User.parse_user($0) } + dict[-1885878744] = { return Api.User.parse_user($0) } dict[-742634630] = { return Api.User.parse_userEmpty($0) } dict[-994968513] = { return Api.UserFull.parse_userFull($0) } dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) } @@ -880,6 +880,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[9203775] = { return Api.UserStatus.parse_userStatusOffline($0) } dict[-306628279] = { return Api.UserStatus.parse_userStatusOnline($0) } dict[-496024847] = { return Api.UserStatus.parse_userStatusRecently($0) } + dict[-1274595769] = { return Api.Username.parse_username($0) } dict[-567037804] = { return Api.VideoSize.parse_videoSize($0) } dict[-1539849235] = { return Api.WallPaper.parse_wallPaper($0) } dict[-528465642] = { return Api.WallPaper.parse_wallPaperNoFile($0) } @@ -1624,6 +1625,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.UserStatus: _1.serialize(buffer, boxed) + case let _1 as Api.Username: + _1.serialize(buffer, boxed) case let _1 as Api.VideoSize: _1.serialize(buffer, boxed) case let _1 as Api.WallPaper: diff --git a/submodules/TelegramApi/Sources/Api21.swift b/submodules/TelegramApi/Sources/Api21.swift index 9b04790c3e..1e7d3e5c54 100644 --- a/submodules/TelegramApi/Sources/Api21.swift +++ b/submodules/TelegramApi/Sources/Api21.swift @@ -452,16 +452,17 @@ public extension Api { } public extension Api { enum User: TypeConstructorDescription { - case user(flags: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?) + case user(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?, usernames: [Api.Username]?) case userEmpty(id: Int64) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus): + case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames): if boxed { - buffer.appendInt32(1570352622) + buffer.appendInt32(-1885878744) } serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(flags2, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt64(accessHash!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(firstName!, buffer: buffer, boxed: false)} @@ -479,6 +480,11 @@ public extension Api { if Int(flags) & Int(1 << 19) != 0 {serializeString(botInlinePlaceholder!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 22) != 0 {serializeString(langCode!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 30) != 0 {emojiStatus!.serialize(buffer, true)} + if Int(flags2) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(usernames!.count)) + for item in usernames! { + item.serialize(buffer, true) + }} break case .userEmpty(let id): if boxed { @@ -491,8 +497,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus): - return ("user", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username)), ("phone", String(describing: phone)), ("photo", String(describing: photo)), ("status", String(describing: status)), ("botInfoVersion", String(describing: botInfoVersion)), ("restrictionReason", String(describing: restrictionReason)), ("botInlinePlaceholder", String(describing: botInlinePlaceholder)), ("langCode", String(describing: langCode)), ("emojiStatus", String(describing: emojiStatus))]) + case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames): + return ("user", [("flags", String(describing: flags)), ("flags2", String(describing: flags2)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username)), ("phone", String(describing: phone)), ("photo", String(describing: photo)), ("status", String(describing: status)), ("botInfoVersion", String(describing: botInfoVersion)), ("restrictionReason", String(describing: restrictionReason)), ("botInlinePlaceholder", String(describing: botInlinePlaceholder)), ("langCode", String(describing: langCode)), ("emojiStatus", String(describing: emojiStatus)), ("usernames", String(describing: usernames))]) case .userEmpty(let id): return ("userEmpty", [("id", String(describing: id))]) } @@ -501,56 +507,64 @@ public extension Api { public static func parse_user(_ reader: BufferReader) -> User? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() var _3: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt64() } - var _4: String? - if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } + _3 = reader.readInt64() + var _4: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt64() } var _5: String? - if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) } + if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) } var _6: String? - if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } + if Int(_1!) & Int(1 << 2) != 0 {_6 = parseString(reader) } var _7: String? - if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) } - var _8: Api.UserProfilePhoto? + if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) } + var _8: String? + if Int(_1!) & Int(1 << 4) != 0 {_8 = parseString(reader) } + var _9: Api.UserProfilePhoto? if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto + _9 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto } } - var _9: Api.UserStatus? + var _10: Api.UserStatus? if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.UserStatus + _10 = Api.parse(reader, signature: signature) as? Api.UserStatus } } - var _10: Int32? - if Int(_1!) & Int(1 << 14) != 0 {_10 = reader.readInt32() } - var _11: [Api.RestrictionReason]? + var _11: Int32? + if Int(_1!) & Int(1 << 14) != 0 {_11 = reader.readInt32() } + var _12: [Api.RestrictionReason]? if Int(_1!) & Int(1 << 18) != 0 {if let _ = reader.readInt32() { - _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) + _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) } } - var _12: String? - if Int(_1!) & Int(1 << 19) != 0 {_12 = parseString(reader) } var _13: String? - if Int(_1!) & Int(1 << 22) != 0 {_13 = parseString(reader) } - var _14: Api.EmojiStatus? + if Int(_1!) & Int(1 << 19) != 0 {_13 = parseString(reader) } + var _14: String? + if Int(_1!) & Int(1 << 22) != 0 {_14 = parseString(reader) } + var _15: Api.EmojiStatus? if Int(_1!) & Int(1 << 30) != 0 {if let signature = reader.readInt32() { - _14 = Api.parse(reader, signature: signature) as? Api.EmojiStatus + _15 = Api.parse(reader, signature: signature) as? Api.EmojiStatus + } } + var _16: [Api.Username]? + if Int(_2!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self) } } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 18) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 19) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 22) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 30) == 0) || _14 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { - return Api.User.user(flags: _1!, id: _2!, accessHash: _3, firstName: _4, lastName: _5, username: _6, phone: _7, photo: _8, status: _9, botInfoVersion: _10, restrictionReason: _11, botInlinePlaceholder: _12, langCode: _13, emojiStatus: _14) + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 5) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 6) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 14) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 18) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 19) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 22) == 0) || _14 != nil + let _c15 = (Int(_1!) & Int(1 << 30) == 0) || _15 != nil + let _c16 = (Int(_2!) & Int(1 << 0) == 0) || _16 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 { + return Api.User.user(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, firstName: _5, lastName: _6, username: _7, phone: _8, photo: _9, status: _10, botInfoVersion: _11, restrictionReason: _12, botInlinePlaceholder: _13, langCode: _14, emojiStatus: _15, usernames: _16) } else { return nil @@ -848,6 +862,46 @@ public extension Api { } } +public extension Api { + enum Username: TypeConstructorDescription { + case username(flags: Int32, username: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .username(let flags, let username): + if boxed { + buffer.appendInt32(-1274595769) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(username, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .username(let flags, let username): + return ("username", [("flags", String(describing: flags)), ("username", String(describing: username))]) + } + } + + public static func parse_username(_ reader: BufferReader) -> Username? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Username.username(flags: _1!, username: _2!) + } + else { + return nil + } + } + + } +} public extension Api { enum VideoSize: TypeConstructorDescription { case videoSize(flags: Int32, type: String, w: Int32, h: Int32, size: Int32, videoStartTs: Double?) diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index 5069b67b53..bcf12c0e28 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -518,13 +518,12 @@ public extension Api.functions.account { } } public extension Api.functions.account { - static func getTheme(format: String, theme: Api.InputTheme, documentId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func getTheme(format: String, theme: Api.InputTheme) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1919060949) + buffer.appendInt32(978872812) serializeString(format, buffer: buffer, boxed: false) theme.serialize(buffer, true) - serializeInt64(documentId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getTheme", parameters: [("format", String(describing: format)), ("theme", String(describing: theme)), ("documentId", String(describing: documentId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in + return (FunctionDescription(name: "account.getTheme", parameters: [("format", String(describing: format)), ("theme", String(describing: theme))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in let reader = BufferReader(buffer) var result: Api.Theme? if let signature = reader.readInt32() { @@ -685,6 +684,25 @@ public extension Api.functions.account { }) } } +public extension Api.functions.account { + static func reorderUsernames(order: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-279966037) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "account.reorderUsernames", parameters: [("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.account { static func reportPeer(peer: Api.InputPeer, reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -1065,6 +1083,22 @@ public extension Api.functions.account { }) } } +public extension Api.functions.account { + static func toggleUsername(username: String, active: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1490465654) + serializeString(username, buffer: buffer, boxed: false) + active.serialize(buffer, true) + return (FunctionDescription(name: "account.toggleUsername", parameters: [("username", String(describing: username)), ("active", String(describing: active))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.account { static func unregisterDevice(tokenType: Int32, token: String, otherUids: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -2391,6 +2425,26 @@ public extension Api.functions.channels { }) } } +public extension Api.functions.channels { + static func reorderUsernames(channel: Api.InputChannel, order: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1268978403) + channel.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "channels.reorderUsernames", parameters: [("channel", String(describing: channel)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.channels { static func reportSpam(channel: Api.InputChannel, participant: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -2540,6 +2594,23 @@ public extension Api.functions.channels { }) } } +public extension Api.functions.channels { + static func toggleUsername(channel: Api.InputChannel, username: String, active: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1358053637) + channel.serialize(buffer, true) + serializeString(username, buffer: buffer, boxed: false) + active.serialize(buffer, true) + return (FunctionDescription(name: "channels.toggleUsername", parameters: [("channel", String(describing: channel)), ("username", String(describing: username)), ("active", String(describing: active))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.channels { static func updateUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index e4d56e4997..0c497a877f 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -522,7 +522,7 @@ public extension Api { } public extension Api { indirect enum Chat: TypeConstructorDescription { - case channel(flags: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?) + case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?) case channelForbidden(flags: Int32, id: Int64, accessHash: Int64, title: String, untilDate: Int32?) case chat(flags: Int32, id: Int64, title: String, photo: Api.ChatPhoto, participantsCount: Int32, date: Int32, version: Int32, migratedTo: Api.InputChannel?, adminRights: Api.ChatAdminRights?, defaultBannedRights: Api.ChatBannedRights?) case chatEmpty(id: Int64) @@ -530,11 +530,12 @@ public extension Api { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .channel(let flags, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount): + case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames): if boxed { - buffer.appendInt32(-2107528095) + buffer.appendInt32(-2094689180) } serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(flags2, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 13) != 0 {serializeInt64(accessHash!, buffer: buffer, boxed: false)} serializeString(title, buffer: buffer, boxed: false) @@ -550,6 +551,11 @@ public extension Api { if Int(flags) & Int(1 << 15) != 0 {bannedRights!.serialize(buffer, true)} if Int(flags) & Int(1 << 18) != 0 {defaultBannedRights!.serialize(buffer, true)} if Int(flags) & Int(1 << 17) != 0 {serializeInt32(participantsCount!, buffer: buffer, boxed: false)} + if Int(flags2) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(usernames!.count)) + for item in usernames! { + item.serialize(buffer, true) + }} break case .channelForbidden(let flags, let id, let accessHash, let title, let untilDate): if boxed { @@ -594,8 +600,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .channel(let flags, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount): - return ("channel", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("title", String(describing: title)), ("username", String(describing: username)), ("photo", String(describing: photo)), ("date", String(describing: date)), ("restrictionReason", String(describing: restrictionReason)), ("adminRights", String(describing: adminRights)), ("bannedRights", String(describing: bannedRights)), ("defaultBannedRights", String(describing: defaultBannedRights)), ("participantsCount", String(describing: participantsCount))]) + case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames): + return ("channel", [("flags", String(describing: flags)), ("flags2", String(describing: flags2)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("title", String(describing: title)), ("username", String(describing: username)), ("photo", String(describing: photo)), ("date", String(describing: date)), ("restrictionReason", String(describing: restrictionReason)), ("adminRights", String(describing: adminRights)), ("bannedRights", String(describing: bannedRights)), ("defaultBannedRights", String(describing: defaultBannedRights)), ("participantsCount", String(describing: participantsCount)), ("usernames", String(describing: usernames))]) case .channelForbidden(let flags, let id, let accessHash, let title, let untilDate): return ("channelForbidden", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("title", String(describing: title)), ("untilDate", String(describing: untilDate))]) case .chat(let flags, let id, let title, let photo, let participantsCount, let date, let version, let migratedTo, let adminRights, let defaultBannedRights): @@ -610,52 +616,60 @@ public extension Api { public static func parse_channel(_ reader: BufferReader) -> Chat? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() var _3: Int64? - if Int(_1!) & Int(1 << 13) != 0 {_3 = reader.readInt64() } - var _4: String? - _4 = parseString(reader) + _3 = reader.readInt64() + var _4: Int64? + if Int(_1!) & Int(1 << 13) != 0 {_4 = reader.readInt64() } var _5: String? - if Int(_1!) & Int(1 << 6) != 0 {_5 = parseString(reader) } - var _6: Api.ChatPhoto? + _5 = parseString(reader) + var _6: String? + if Int(_1!) & Int(1 << 6) != 0 {_6 = parseString(reader) } + var _7: Api.ChatPhoto? if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.ChatPhoto + _7 = Api.parse(reader, signature: signature) as? Api.ChatPhoto } - var _7: Int32? - _7 = reader.readInt32() - var _8: [Api.RestrictionReason]? + var _8: Int32? + _8 = reader.readInt32() + var _9: [Api.RestrictionReason]? if Int(_1!) & Int(1 << 9) != 0 {if let _ = reader.readInt32() { - _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) + _9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) } } - var _9: Api.ChatAdminRights? + var _10: Api.ChatAdminRights? if Int(_1!) & Int(1 << 14) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights - } } - var _10: Api.ChatBannedRights? - if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.ChatBannedRights + _10 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights } } var _11: Api.ChatBannedRights? - if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { + if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() { _11 = Api.parse(reader, signature: signature) as? Api.ChatBannedRights } } - var _12: Int32? - if Int(_1!) & Int(1 << 17) != 0 {_12 = reader.readInt32() } + var _12: Api.ChatBannedRights? + if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { + _12 = Api.parse(reader, signature: signature) as? Api.ChatBannedRights + } } + var _13: Int32? + if Int(_1!) & Int(1 << 17) != 0 {_13 = reader.readInt32() } + var _14: [Api.Username]? + if Int(_2!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self) + } } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 13) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 6) == 0) || _5 != nil - let _c6 = _6 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 13) == 0) || _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 6) == 0) || _6 != nil let _c7 = _7 != nil - let _c8 = (Int(_1!) & Int(1 << 9) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 14) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 15) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 18) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 17) == 0) || _12 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 { - return Api.Chat.channel(flags: _1!, id: _2!, accessHash: _3, title: _4!, username: _5, photo: _6!, date: _7!, restrictionReason: _8, adminRights: _9, bannedRights: _10, defaultBannedRights: _11, participantsCount: _12) + let _c8 = _8 != nil + let _c9 = (Int(_1!) & Int(1 << 9) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 15) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 18) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 17) == 0) || _13 != nil + let _c14 = (Int(_2!) & Int(1 << 0) == 0) || _14 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { + return Api.Chat.channel(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, title: _5!, username: _6, photo: _7!, date: _8!, restrictionReason: _9, adminRights: _10, bannedRights: _11, defaultBannedRights: _12, participantsCount: _13, usernames: _14) } else { return nil diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index 03a63afb33..c5b3708e7e 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -366,7 +366,7 @@ struct AccountMutableState { for chat in chats { switch chat { - case let .channel(_, _, _, _, _, _, _, _, _, _, _, participantsCount): + case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _): if let participantsCount = participantsCount { self.addOperation(.UpdateCachedPeerData(chat.peerId, { current in var previous: CachedChannelData @@ -426,7 +426,7 @@ struct AccountMutableState { var presences: [PeerId: Api.UserStatus] = [:] for user in users { switch user { - case let .user(_, id, _, _, _, _, _, _, status, _, _, _, _, _): + case let .user(_, _, id, _, _, _, _, _, _, status, _, _, _, _, _, _): if let status = status { presences[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] = status } diff --git a/submodules/TelegramCore/Sources/Account/AccountManager.swift b/submodules/TelegramCore/Sources/Account/AccountManager.swift index af52500d12..a90d00bcfd 100644 --- a/submodules/TelegramCore/Sources/Account/AccountManager.swift +++ b/submodules/TelegramCore/Sources/Account/AccountManager.swift @@ -190,6 +190,7 @@ private var declaredEncodables: Void = { declareEncodable(AudioTranscriptionMessageAttribute.self, f: { AudioTranscriptionMessageAttribute(decoder: $0) }) declareEncodable(NonPremiumMessageAttribute.self, f: { NonPremiumMessageAttribute(decoder: $0) }) declareEncodable(TelegramExtendedMedia.self, f: { TelegramExtendedMedia(decoder: $0) }) + declareEncodable(TelegramPeerUsername.self, f: { TelegramPeerUsername(decoder: $0) }) return }() diff --git a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift index 58dc7cdd94..fd6363820e 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift @@ -60,7 +60,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0) case let .chatForbidden(id, title): return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0) - case let .channel(flags, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, _): + case let .channel(flags, _, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, _, usernames): let isMin = (flags & (1 << 12)) != 0 let participationStatus: TelegramChannelParticipationStatus @@ -143,7 +143,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { } } - return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: 0, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init)) + return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: 0, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? []) case let .channelForbidden(flags, id, accessHash, title, untilDate): let info: TelegramChannelInfo if (flags & Int32(1 << 8)) != 0 { @@ -152,7 +152,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { info = .broadcast(TelegramChannelBroadcastInfo(flags: [])) } - return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil) + return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil, usernames: []) } } @@ -160,7 +160,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? { switch rhs { case .chat, .chatEmpty, .chatForbidden, .channelForbidden: return parseTelegramGroupOrChannel(chat: rhs) - case let .channel(flags, _, accessHash, title, username, photo, _, _, _, _, defaultBannedRights, _): + case let .channel(flags, _, _, accessHash, title, username, photo, _, _, _, _, defaultBannedRights, _, usernames): let isMin = (flags & (1 << 12)) != 0 if accessHash != nil && !isMin { return parseTelegramGroupOrChannel(chat: rhs) @@ -193,7 +193,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? { info = .group(TelegramChannelGroupInfo(flags: infoFlags)) } - return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init)) + return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? []) } else { return parseTelegramGroupOrChannel(chat: rhs) } @@ -244,6 +244,6 @@ func mergeChannel(lhs: TelegramChannel?, rhs: TelegramChannel) -> TelegramChanne accessHash = rhs.accessHash ?? lhs.accessHash } - return TelegramChannel(id: lhs.id, accessHash: accessHash, title: rhs.title, username: rhs.username, photo: rhs.photo, creationDate: rhs.creationDate, version: rhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: rhs.restrictionInfo, adminRights: rhs.adminRights, bannedRights: rhs.bannedRights, defaultBannedRights: rhs.defaultBannedRights) + return TelegramChannel(id: lhs.id, accessHash: accessHash, title: rhs.title, username: rhs.username, photo: rhs.photo, creationDate: rhs.creationDate, version: rhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: rhs.restrictionInfo, adminRights: rhs.adminRights, bannedRights: rhs.bannedRights, defaultBannedRights: rhs.defaultBannedRights, usernames: rhs.usernames) } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift index 668e275a21..4d7457af96 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift @@ -23,10 +23,19 @@ func parsedTelegramProfilePhoto(_ photo: Api.UserProfilePhoto) -> [TelegramMedia return representations } +extension TelegramPeerUsername { + init(apiUsername: Api.Username) { + switch apiUsername { + case let .username(flags, username): + self.init(flags: Flags(rawValue: flags), username: username) + } + } +} + extension TelegramUser { convenience init(user: Api.User) { switch user { - case let .user(flags, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus): + case let .user(flags, _, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames): let representations: [TelegramMediaImageRepresentation] = photo.flatMap(parsedTelegramProfilePhoto) ?? [] let isMin = (flags & (1 << 20)) != 0 @@ -75,15 +84,15 @@ extension TelegramUser { let restrictionInfo: PeerAccessRestrictionInfo? = restrictionReason.flatMap(PeerAccessRestrictionInfo.init(apiReasons:)) - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:))) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? []) case let .userEmpty(id): - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) } } static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? { switch rhs { - case let .user(flags, _, rhsAccessHash, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus): + case let .user(flags, _, _, rhsAccessHash, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames): let isMin = (flags & (1 << 20)) != 0 if !isMin { return TelegramUser(user: rhs) @@ -150,7 +159,7 @@ extension TelegramUser { accessHash = lhs.accessHash ?? rhsAccessHashValue } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:))) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? []) } else { return TelegramUser(user: rhs) } @@ -197,7 +206,7 @@ extension TelegramUser { accessHash = lhs.accessHash ?? rhs.accessHash } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: rhs.username, phone: lhs.phone, photo: rhs.photo.isEmpty ? lhs.photo : rhs.photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: rhs.username, phone: lhs.phone, photo: rhs.photo.isEmpty ? lhs.photo : rhs.photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: rhs.usernames.isEmpty ? lhs.usernames : rhs.usernames) } } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift index 47a188b2fa..4e5614b081 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift @@ -23,7 +23,7 @@ extension TelegramUserPresence { convenience init?(apiUser: Api.User) { switch apiUser { - case let .user(_, _, _, _, _, _, _, _, status, _, _, _, _, _): + case let .user(_, _, _, _, _, _, _, _, _, status, _, _, _, _, _, _): if let status = status { self.init(apiStatus: status) } else { diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 01fdb26065..e3a096dfc3 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1020,7 +1020,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo if updatedState.peers[peerId] == nil { updatedState.updatePeer(peerId, { peer in if peer == nil { - return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil) + return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil, usernames: []) } else { return peer } diff --git a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift index 679b713a3f..8217124be9 100644 --- a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift @@ -146,7 +146,7 @@ extension Api.Chat { return PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)) case let .chatForbidden(id, _): return PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)) - case let .channel(_, id, _, _, _, _, _, _, _, _, _, _): + case let .channel(_, _, id, _, _, _, _, _, _, _, _, _, _, _): return PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)) case let .channelForbidden(_, id, _, _, _): return PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)) @@ -157,7 +157,7 @@ extension Api.Chat { extension Api.User { var peerId: PeerId { switch self { - case .user(_, let id, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _): return PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)) case let .userEmpty(id): return PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift index dad575fa0e..a6f9a3f9ea 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift @@ -165,6 +165,7 @@ public final class TelegramChannel: Peer, Equatable { public let adminRights: TelegramChatAdminRights? public let bannedRights: TelegramChatBannedRights? public let defaultBannedRights: TelegramChatBannedRights? + public let usernames: [TelegramPeerUsername] public var indexName: PeerIndexNameRepresentation { return .title(title: self.title, addressName: self.username) @@ -177,7 +178,7 @@ public final class TelegramChannel: Peer, Equatable { public var timeoutAttribute: UInt32? { return nil } - public init(id: PeerId, accessHash: TelegramPeerAccessHash?, title: String, username: String?, photo: [TelegramMediaImageRepresentation], creationDate: Int32, version: Int32, participationStatus: TelegramChannelParticipationStatus, info: TelegramChannelInfo, flags: TelegramChannelFlags, restrictionInfo: PeerAccessRestrictionInfo?, adminRights: TelegramChatAdminRights?, bannedRights: TelegramChatBannedRights?, defaultBannedRights: TelegramChatBannedRights?) { + public init(id: PeerId, accessHash: TelegramPeerAccessHash?, title: String, username: String?, photo: [TelegramMediaImageRepresentation], creationDate: Int32, version: Int32, participationStatus: TelegramChannelParticipationStatus, info: TelegramChannelInfo, flags: TelegramChannelFlags, restrictionInfo: PeerAccessRestrictionInfo?, adminRights: TelegramChatAdminRights?, bannedRights: TelegramChatBannedRights?, defaultBannedRights: TelegramChatBannedRights?, usernames: [TelegramPeerUsername]) { self.id = id self.accessHash = accessHash self.title = title @@ -192,6 +193,7 @@ public final class TelegramChannel: Peer, Equatable { self.adminRights = adminRights self.bannedRights = bannedRights self.defaultBannedRights = defaultBannedRights + self.usernames = usernames } public init(decoder: PostboxDecoder) { @@ -219,6 +221,7 @@ public final class TelegramChannel: Peer, Equatable { self.adminRights = decoder.decodeObjectForKey("ar", decoder: { TelegramChatAdminRights(decoder: $0) }) as? TelegramChatAdminRights self.bannedRights = decoder.decodeObjectForKey("br", decoder: { TelegramChatBannedRights(decoder: $0) }) as? TelegramChatBannedRights self.defaultBannedRights = decoder.decodeObjectForKey("dbr", decoder: { TelegramChatBannedRights(decoder: $0) }) as? TelegramChatBannedRights + self.usernames = decoder.decodeObjectArrayForKey("uns") } public func encode(_ encoder: PostboxEncoder) { @@ -267,6 +270,7 @@ public final class TelegramChannel: Peer, Equatable { } else { encoder.encodeNil(forKey: "dbr") } + encoder.encodeObjectArray(self.usernames, forKey: "uns") } public func isEqual(_ other: Peer) -> Bool { @@ -301,19 +305,26 @@ public final class TelegramChannel: Peer, Equatable { if lhs.defaultBannedRights != rhs.defaultBannedRights { return false } + if lhs.usernames != rhs.usernames { + return false + } return true } public func withUpdatedAddressName(_ addressName: String?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: addressName, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: addressName, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames) + } + + public func withUpdatedAddressNames(_ addressNames: [TelegramPeerUsername]) -> TelegramChannel { + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: addressNames) } public func withUpdatedDefaultBannedRights(_ defaultBannedRights: TelegramChatBannedRights?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: defaultBannedRights) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: defaultBannedRights, usernames: self.usernames) } public func withUpdatedFlags(_ flags: TelegramChannelFlags) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift index 5d9a5b0ed8..3ec0a6f8d5 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift @@ -59,6 +59,41 @@ public struct BotUserInfo: PostboxCoding, Equatable { } } +public struct TelegramPeerUsername: PostboxCoding, Equatable { + public struct Flags: OptionSet { + public var rawValue: Int32 + + public init() { + self.rawValue = 0 + } + + public init(rawValue: Int32) { + self.rawValue = rawValue + } + + public static let isEditable = Flags(rawValue: (1 << 0)) + public static let isActive = Flags(rawValue: (1 << 1)) + } + + public let flags: Flags + public let username: String + + public init(flags: Flags, username: String) { + self.flags = flags + self.username = username + } + + public init(decoder: PostboxDecoder) { + self.flags = Flags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0)) + self.username = decoder.decodeStringForKey("un", orElse: "") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.flags.rawValue, forKey: "f") + encoder.encodeString(self.username, forKey: "un") + } +} + public final class TelegramUser: Peer, Equatable { public let id: PeerId public let accessHash: TelegramPeerAccessHash? @@ -71,6 +106,7 @@ public final class TelegramUser: Peer, Equatable { public let restrictionInfo: PeerAccessRestrictionInfo? public let flags: UserInfoFlags public let emojiStatus: PeerEmojiStatus? + public let usernames: [TelegramPeerUsername] public var nameOrPhone: String { if let firstName = self.firstName { @@ -127,7 +163,7 @@ public final class TelegramUser: Peer, Equatable { } } - public init(id: PeerId, accessHash: TelegramPeerAccessHash?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: [TelegramMediaImageRepresentation], botInfo: BotUserInfo?, restrictionInfo: PeerAccessRestrictionInfo?, flags: UserInfoFlags, emojiStatus: PeerEmojiStatus?) { + public init(id: PeerId, accessHash: TelegramPeerAccessHash?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: [TelegramMediaImageRepresentation], botInfo: BotUserInfo?, restrictionInfo: PeerAccessRestrictionInfo?, flags: UserInfoFlags, emojiStatus: PeerEmojiStatus?, usernames: [TelegramPeerUsername]) { self.id = id self.accessHash = accessHash self.firstName = firstName @@ -139,6 +175,7 @@ public final class TelegramUser: Peer, Equatable { self.restrictionInfo = restrictionInfo self.flags = flags self.emojiStatus = emojiStatus + self.usernames = usernames } public init(decoder: PostboxDecoder) { @@ -175,6 +212,8 @@ public final class TelegramUser: Peer, Equatable { self.flags = UserInfoFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0)) self.emojiStatus = decoder.decode(PeerEmojiStatus.self, forKey: "emjs") + + self.usernames = decoder.decodeObjectArrayForKey("uns") } public func encode(_ encoder: PostboxEncoder) { @@ -226,6 +265,8 @@ public final class TelegramUser: Peer, Equatable { } else { encoder.encodeNil(forKey: "emjs") } + + encoder.encodeObjectArray(self.usernames, forKey: "uns") } public func isEqual(_ other: Peer) -> Bool { @@ -275,27 +316,34 @@ public final class TelegramUser: Peer, Equatable { if lhs.emojiStatus != rhs.emojiStatus { return false } - + if lhs.usernames != rhs.usernames { + return false + } + return true } - public func withUpdatedUsername(_ username:String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus) + public func withUpdatedUsername(_ username: String?) -> TelegramUser { + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames) + } + + public func withUpdatedUsernames(_ usernames: [TelegramPeerUsername]) -> TelegramUser { + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: usernames) } public func withUpdatedNames(firstName: String?, lastName: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames) } public func withUpdatedPhone(_ phone: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames) } public func withUpdatedPhoto(_ representations: [TelegramMediaImageRepresentation]) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames) } public func withUpdatedEmojiStatus(_ emojiStatus: PeerEmojiStatus?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus, usernames: self.usernames) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index c0f5431130..644ca73fa9 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -2298,7 +2298,7 @@ func _internal_groupCallDisplayAsAvailablePeers(network: Network, postbox: Postb for chat in chats { if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { switch chat { - case let .channel(_, _, _, _, _, _, _, _, _, _, _, participantsCount): + case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _): if let participantsCount = participantsCount { subscribers[groupOrChannel.id] = participantsCount } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index 3ab8de154a..363008598d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -221,7 +221,8 @@ private class AdMessagesHistoryContextImpl { restrictionInfo: nil, adminRights: nil, bannedRights: nil, - defaultBannedRights: nil + defaultBannedRights: nil, + usernames: [] ) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift index c4836afdf7..7323d49f9a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift @@ -126,7 +126,7 @@ func _internal_peerSendAsAvailablePeers(network: Network, postbox: Postbox, peer for chat in chats { if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { switch chat { - case let .channel(_, _, _, _, _, _, _, _, _, _, _, participantsCount): + case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _): if let participantsCount = participantsCount { subscribers[groupOrChannel.id] = participantsCount } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift index 49bcd36685..5ac2645ec5 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift @@ -172,6 +172,124 @@ func _internal_updateAddressName(account: Account, domain: AddressNameDomain, na } |> mapError { _ -> UpdateAddressNameError in } |> switchToLatest } +public enum ToggleAddressNameActiveError { + case generic +} + +func _internal_toggleAddressNameActive(account: Account, domain: AddressNameDomain, name: String, active: Bool) -> Signal { + return account.postbox.transaction { transaction -> Signal in + switch domain { + case .account: + return account.network.request(Api.functions.account.toggleUsername(username: name, active: active ? .boolTrue : .boolFalse), automaticFloodWait: false) + |> mapError { _ -> ToggleAddressNameActiveError in + return .generic + } + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction -> Void in + if case .boolTrue = result, let peer = transaction.getPeer(account.peerId) as? TelegramUser { + var updatedNames = peer.usernames + if let index = updatedNames.firstIndex(where: { $0.username == name }) { + var updatedFlags = updatedNames[index].flags + if active { + updatedFlags.insert(.isActive) + } else { + updatedFlags.remove(.isActive) + } + let updatedName = TelegramPeerUsername(flags: updatedFlags, username: name) + updatedNames.remove(at: index) + updatedNames.insert(updatedName, at: index) + } + let updatedUser = peer.withUpdatedUsernames(updatedNames) + updatePeers(transaction: transaction, peers: [updatedUser], update: { _, updated in + return updated + }) + } + } |> mapError { _ -> ToggleAddressNameActiveError in } + } + case let .peer(peerId): + if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) { + return account.network.request(Api.functions.channels.toggleUsername(channel: inputChannel, username: name, active: active ? .boolTrue : .boolFalse), automaticFloodWait: false) + |> mapError { _ -> ToggleAddressNameActiveError in + return .generic + } + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction -> Void in + if case .boolTrue = result, let peer = transaction.getPeer(peerId) as? TelegramChannel { + var updatedNames = peer.usernames + if let index = updatedNames.firstIndex(where: { $0.username == name }) { + var updatedFlags = updatedNames[index].flags + if active { + updatedFlags.insert(.isActive) + } else { + updatedFlags.remove(.isActive) + } + let updatedName = TelegramPeerUsername(flags: updatedFlags, username: name) + updatedNames.remove(at: index) + updatedNames.insert(updatedName, at: index) + } + let updatedPeer = peer.withUpdatedAddressNames(updatedNames) + updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in + return updated + }) + } + } |> mapError { _ -> ToggleAddressNameActiveError in } + } + } else { + return .fail(.generic) + } + case .theme: + return .complete() + } + } |> mapError { _ -> ToggleAddressNameActiveError in } |> switchToLatest +} + +public enum ReorderAddressNamesError { + case generic +} + +func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain, names: [TelegramPeerUsername]) -> Signal { + return account.postbox.transaction { transaction -> Signal in + switch domain { + case .account: + return account.network.request(Api.functions.account.reorderUsernames(order: names.map { $0.username }), automaticFloodWait: false) + |> mapError { _ -> ReorderAddressNamesError in + return .generic + } + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction -> Void in + if case .boolTrue = result, let peer = transaction.getPeer(account.peerId) as? TelegramUser { + let updatedUser = peer.withUpdatedUsernames(names) + updatePeers(transaction: transaction, peers: [updatedUser], update: { _, updated in + return updated + }) + } + } |> mapError { _ -> ReorderAddressNamesError in } + } + case let .peer(peerId): + if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) { + return account.network.request(Api.functions.channels.reorderUsernames(channel: inputChannel, order: names.map { $0.username }), automaticFloodWait: false) + |> mapError { _ -> ReorderAddressNamesError in + return .generic + } + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction -> Void in + if case .boolTrue = result, let peer = transaction.getPeer(peerId) as? TelegramChannel { + let updatedPeer = peer.withUpdatedAddressNames(names) + updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in + return updated + }) + } + } |> mapError { _ -> ReorderAddressNamesError in } + } + } else { + return .fail(.generic) + } + case .theme: + return .complete() + } + } |> mapError { _ -> ReorderAddressNamesError in } |> switchToLatest +} + func _internal_checkPublicChannelCreationAvailability(account: Account, location: Bool = false) -> Signal { var flags: Int32 = (1 << 1) if location { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift index da0d646349..c7c1b2c786 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift @@ -31,7 +31,7 @@ func _internal_inactiveChannelList(network: Network) -> Signal<[InactiveChannel] var participantsCounts: [PeerId: Int32] = [:] for chat in chats { switch chat { - case let .channel(_, _, _, _, _, _, _, _, _, _, _, participantsCountValue): + case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCountValue, _): if let participantsCountValue = participantsCountValue { participantsCounts[chat.peerId] = participantsCountValue } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift index c6bc6cd994..1157f25495 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift @@ -44,7 +44,7 @@ func _internal_searchPeers(account: Account, query: String) -> Signal<([FoundPee peers[groupOrChannel.id] = groupOrChannel switch chat { /*feed*/ - case let .channel(_, _, _, _, _, _, _, _, _, _, _, participantsCount): + case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _): if let participantsCount = participantsCount { subscribers[groupOrChannel.id] = participantsCount } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 51c0ce62ea..8e0ff74014 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -46,7 +46,15 @@ public extension TelegramEngine { public func updateAddressName(domain: AddressNameDomain, name: String?) -> Signal { return _internal_updateAddressName(account: self.account, domain: domain, name: name) } - + + public func toggleAddressNameActive(domain: AddressNameDomain, name: String, active: Bool) -> Signal { + return _internal_toggleAddressNameActive(account: self.account, domain: domain, name: name, active: active) + } + + public func reorderAddressNames(domain: AddressNameDomain, names: [TelegramPeerUsername]) -> Signal { + return _internal_reorderAddressNames(account: self.account, domain: domain, names: names) + } + public func checkPublicChannelCreationAvailability(location: Bool = false) -> Signal { return _internal_checkPublicChannelCreationAvailability(account: self.account, location: location) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift index 468b557688..433cdeeda7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift @@ -115,7 +115,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal Signal { - return account.network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputThemeSlug(slug: slug), documentId: 0)) + return account.network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputThemeSlug(slug: slug))) |> mapError { error -> GetThemeError in if error.errorDescription == "THEME_FORMAT_INVALID" { return .unsupported @@ -114,11 +114,7 @@ public enum ThemeUpdatedResult { } private func checkThemeUpdated(network: Network, theme: TelegramTheme) -> Signal { - let id = theme.settings != nil ? 0 : theme.file?.id?.id - guard let documentId = id else { - return .fail(.generic) - } - return network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash), documentId: documentId)) + return network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash))) |> mapError { _ -> GetThemeError in return .generic } |> map { theme -> ThemeUpdatedResult in return .updated(TelegramTheme(apiTheme: theme)) diff --git a/submodules/TelegramCore/Sources/UpdatePeers.swift b/submodules/TelegramCore/Sources/UpdatePeers.swift index ed09bec470..27c3271085 100644 --- a/submodules/TelegramCore/Sources/UpdatePeers.swift +++ b/submodules/TelegramCore/Sources/UpdatePeers.swift @@ -117,7 +117,7 @@ func updatePeerPresences(transaction: Transaction, accountPeerId: PeerId, peerPr parsedPresences[peerId] = presence default: switch user { - case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): let isMin = (flags & (1 << 20)) != 0 if isMin, let _ = transaction.getPeerPresence(peerId: peerId) { } else { @@ -185,7 +185,7 @@ func updateContacts(transaction: Transaction, apiUsers: [Api.User]) { for user in apiUsers { var isContact: Bool? switch user { - case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 20)) == 0 { isContact = (flags & (1 << 11)) != 0 } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index fbf8af2f5a..43ac6f9139 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -298,6 +298,7 @@ swift_library( "//submodules/Components/PagerComponent:PagerComponent", "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", "//submodules/TelegramUI/Components/ForumTopicListScreen:ForumTopicListScreen", + "//submodules/TelegramUI/Components/ForumCreateTopicScreen:ForumCreateTopicScreen", ] + select({ "@build_bazel_rules_apple//apple:ios_armv7": [], "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, diff --git a/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift b/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift index 1716525d34..18b9dbb76f 100644 --- a/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift +++ b/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift @@ -48,6 +48,7 @@ public final class EmojiStatusComponent: Component { case verified(fillColor: UIColor, foregroundColor: UIColor, sizeType: SizeType) case text(color: UIColor, string: String) case animation(content: AnimationContent, size: CGSize, placeholderColor: UIColor, themeColor: UIColor?, loopMode: LoopMode) + case topic(title: String) } public let context: AccountContext @@ -222,6 +223,67 @@ public final class EmojiStatusComponent: Component { } else { iconImage = nil } + case let .topic(title): + func generateTopicIcon(backgroundColors: [UIColor], strokeColors: [UIColor]) -> UIImage? { + return generateImage(CGSize(width: 44.0, height: 44.0), rotatedContext: { size, context in + context.clear(CGRect(origin: .zero, size: size)) + + context.saveGState() + + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.scaleBy(x: 1.333, y: 1.333) + context.translateBy(x: -14.0 - UIScreenPixel, y: -14.0 - UIScreenPixel) + + let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ") + context.closePath() + context.clip() + + let colorsArray = backgroundColors.map { $0.cgColor } as NSArray + var locations: [CGFloat] = [0.0, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + + context.resetClip() + + let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ") + context.closePath() + if let path = context.path { + let strokePath = path.copy(strokingWithWidth: 1.0, lineCap: .round, lineJoin: .round, miterLimit: 0.0) + context.beginPath() + context.addPath(strokePath) + context.clip() + + let colorsArray = strokeColors.map { $0.cgColor } as NSArray + var locations: [CGFloat] = [0.0, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + } + + context.restoreGState() + + let attributedString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.font: Font.with(size: 19.0, design: .round, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.white]) + + let line = CTLineCreateWithAttributedString(attributedString) + let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds) + + let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: 0.0) + let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + 2.0) + + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.scaleBy(x: 1.0, y: -1.0) + context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + + context.translateBy(x: lineOrigin.x, y: lineOrigin.y) + CTLineDraw(line, context) + context.translateBy(x: -lineOrigin.x, y: -lineOrigin.y) + }) + } + + if let image = generateTopicIcon(backgroundColors: [UIColor(rgb: 0x6FB9F0), UIColor(rgb: 0x0261E4)], strokeColors: [UIColor(rgb: 0x026CB5), UIColor(rgb: 0x064BB7)]) { + iconImage = image + } else { + iconImage = nil + } case let .verified(fillColor, foregroundColor, sizeType): let imageNamePrefix: String switch sizeType { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index f547374e75..13253c81d5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -2143,8 +2143,9 @@ public final class EmojiPagerContentComponent: Component { case icon(Icon) } - public enum Icon: Equatable { + public enum Icon: Equatable, Hashable { case premiumStar + case topic(String) } case animation(EntityKeyboardAnimationData) @@ -2942,6 +2943,11 @@ public final class EmojiPagerContentComponent: Component { let imageSize = image.size.aspectFitted(CGSize(width: size.width - 6.0, height: size.height - 6.0)) image.draw(in: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) } + case let .topic(title): + if let image = generateTopicIcon(backgroundColors: [UIColor(rgb: 0x6FB9F0), UIColor(rgb: 0x0261E4)], strokeColors: [UIColor(rgb: 0x026CB5), UIColor(rgb: 0x064BB7)], title: title) { + let imageSize = image.size//.aspectFitted(CGSize(width: size.width - 6.0, height: size.height - 6.0)) + image.draw(in: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) + } } UIGraphicsPopContext() @@ -2986,6 +2992,26 @@ public final class EmojiPagerContentComponent: Component { return nullAction } + func update(content: ItemContent) { + if self.content != content { + if case let .icon(icon) = content, case let .topic(title) = icon { + let image = generateImage(self.size, opaque: false, scale: min(UIScreenScale, 3.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + UIGraphicsPushContext(context) + + if let image = generateTopicIcon(backgroundColors: [UIColor(rgb: 0x6FB9F0), UIColor(rgb: 0x0261E4)], strokeColors: [UIColor(rgb: 0x026CB5), UIColor(rgb: 0x064BB7)], title: title) { + let imageSize = image.size//.aspectFitted(CGSize(width: size.width - 6.0, height: size.height - 6.0)) + image.draw(in: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: floor((size.height - imageSize.height) / 2.0)), size: imageSize)) + } + + UIGraphicsPopContext() + }) + self.contents = image?.cgImage + } + } + } + func update(transition: Transition, size: CGSize, badge: Badge?, blurredBadgeColor: UIColor, blurredBadgeBackgroundColor: UIColor) { if self.badge != badge || self.validSize != size { self.badge = badge @@ -5244,6 +5270,11 @@ public final class EmojiPagerContentComponent: Component { badge = .premium } } + + if case .icon = item.content { + itemLayer.update(content: item.content) + } + itemLayer.update(transition: transition, size: itemFrame.size, badge: badge, blurredBadgeColor: UIColor(white: 0.0, alpha: 0.1), blurredBadgeBackgroundColor: keyboardChildEnvironment.theme.list.plainBackgroundColor) if item.accentTint { @@ -5263,7 +5294,13 @@ public final class EmojiPagerContentComponent: Component { } } + var isSelected = false if let itemFile = item.itemFile, component.selectedItems.contains(itemFile.fileId) { + isSelected = true + } else if case let .icon(icon) = item.content.id, case .topic = icon, component.selectedItems.isEmpty { + } + + if isSelected { let itemSelectionLayer: ItemSelectionLayer if let current = self.visibleItemSelectionLayers[itemId] { itemSelectionLayer = current @@ -5406,7 +5443,8 @@ public final class EmojiPagerContentComponent: Component { default: break } - if let fileId = fileId, component.selectedItems.contains(fileId) { + if case let .icon(icon) = id.itemId, case .topic = icon, component.selectedItems.isEmpty { + } else if let fileId = fileId, component.selectedItems.contains(fileId) { } else { itemSelectionLayer.removeFromSuperlayer() removedItemSelectionLayerIds.append(id) @@ -6149,13 +6187,15 @@ public final class EmojiPagerContentComponent: Component { isStandalone: Bool, isStatusSelection: Bool, isReactionSelection: Bool, + isTopicIconSelection: Bool = false, isQuickReactionSelection: Bool = false, topReactionItems: [EmojiComponentReactionItem], areUnicodeEmojiEnabled: Bool, areCustomEmojiEnabled: Bool, chatPeerId: EnginePeer.Id?, selectedItems: Set = Set(), - topStatusTitle: String? = nil + topStatusTitle: String? = nil, + topicTitle: String? = nil ) -> Signal { let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) let isPremiumDisabled = premiumConfiguration.isPremiumDisabled @@ -6236,7 +6276,24 @@ public final class EmojiPagerContentComponent: Component { } } - if isStatusSelection { + if isTopicIconSelection { + let resultItem = EmojiPagerContentComponent.Item( + animationData: nil, + content: .icon(.topic(String((topicTitle ?? "").prefix(1)))), + itemFile: nil, + subgroupId: nil, + icon: .none, + accentTint: false + ) + + let groupId = "recent" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem])) + } + } else if isStatusSelection { let resultItem = EmojiPagerContentComponent.Item( animationData: nil, content: .icon(.premiumStar), @@ -6848,3 +6905,58 @@ public final class EmojiPagerContentComponent: Component { return emojiItems } } + +func generateTopicIcon(backgroundColors: [UIColor], strokeColors: [UIColor], title: String) -> UIImage? { + return generateImage(CGSize(width: 44.0, height: 44.0), rotatedContext: { size, context in + context.clear(CGRect(origin: .zero, size: size)) + + context.saveGState() + + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.scaleBy(x: 1.2, y: 1.2) + context.translateBy(x: -14.0 - UIScreenPixel, y: -14.0 - UIScreenPixel) + + let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ") + context.closePath() + context.clip() + + let colorsArray = backgroundColors.map { $0.cgColor } as NSArray + var locations: [CGFloat] = [0.0, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + + context.resetClip() + + let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ") + context.closePath() + if let path = context.path { + let strokePath = path.copy(strokingWithWidth: 1.0, lineCap: .round, lineJoin: .round, miterLimit: 0.0) + context.beginPath() + context.addPath(strokePath) + context.clip() + + let colorsArray = strokeColors.map { $0.cgColor } as NSArray + var locations: [CGFloat] = [0.0, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + } + + context.restoreGState() + + let attributedString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.font: Font.with(size: 19.0, design: .round, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.white]) + + let line = CTLineCreateWithAttributedString(attributedString) + let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds) + + let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: 0.0) + let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + 1.0) + + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.scaleBy(x: 1.0, y: -1.0) + context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + + context.translateBy(x: lineOrigin.x, y: lineOrigin.y) + CTLineDraw(line, context) + context.translateBy(x: -lineOrigin.x, y: -lineOrigin.y) + }) +} diff --git a/submodules/TelegramUI/Components/ForumCreateTopicScreen/BUILD b/submodules/TelegramUI/Components/ForumCreateTopicScreen/BUILD new file mode 100644 index 0000000000..ae06114d1b --- /dev/null +++ b/submodules/TelegramUI/Components/ForumCreateTopicScreen/BUILD @@ -0,0 +1,37 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ForumCreateTopicScreen", + module_name = "ForumCreateTopicScreen", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + "//submodules/Display:Display", + "//submodules/Postbox:Postbox", + "//submodules/TelegramCore:TelegramCore", + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/ComponentFlow:ComponentFlow", + "//submodules/Components/ViewControllerComponent:ViewControllerComponent", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", + "//submodules/Components/MultilineTextComponent:MultilineTextComponent", + "//submodules/TelegramPresentationData:TelegramPresentationData", + "//submodules/AccountContext:AccountContext", + "//submodules/AppBundle:AppBundle", + "//submodules/TelegramStringFormatting:TelegramStringFormatting", + "//submodules/PresentationDataUtils:PresentationDataUtils", + "//submodules/TelegramUI/Components/EmojiStatusComponent", + "//submodules/TelegramUI/Components/EntityKeyboard:EntityKeyboard", + "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", + "//submodules/Components/PagerComponent:PagerComponent", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift b/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift new file mode 100644 index 0000000000..123fd603b8 --- /dev/null +++ b/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift @@ -0,0 +1,710 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import ComponentFlow +import SwiftSignalKit +import ViewControllerComponent +import ComponentDisplayAdapters +import TelegramPresentationData +import AccountContext +import TelegramCore +import EntityKeyboard +import PagerComponent +import MultilineTextComponent +import EmojiStatusComponent +import Postbox + +private final class TitleFieldComponent: Component { + typealias EnvironmentType = Empty + + let context: AccountContext + let textColor: UIColor + let accentColor: UIColor + let placeholderColor: UIColor + let fileId: Int64 + let text: String + let textUpdated: (String) -> Void + + init( + context: AccountContext, + textColor: UIColor, + accentColor: UIColor, + placeholderColor: UIColor, + fileId: Int64, + text: String, + textUpdated: @escaping (String) -> Void + ) { + self.context = context + self.textColor = textColor + self.accentColor = accentColor + self.placeholderColor = placeholderColor + self.fileId = fileId + self.text = text + self.textUpdated = textUpdated + } + + static func ==(lhs: TitleFieldComponent, rhs: TitleFieldComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.textColor != rhs.textColor { + return false + } + if lhs.accentColor != rhs.accentColor { + return false + } + if lhs.placeholderColor != rhs.placeholderColor { + return false + } + if lhs.fileId != rhs.fileId { + return false + } + if lhs.text != rhs.text { + return false + } + return true + } + + final class View: UIView { + private let iconView: ComponentView + private let textField: TextFieldNodeView + + private var component: TitleFieldComponent? + private weak var state: EmptyComponentState? + + override init(frame: CGRect) { + self.iconView = ComponentView() + self.textField = TextFieldNodeView(frame: .zero) + + super.init(frame: frame) + + self.textField.placeholder = "What do you want to discuss?" + self.textField.addTarget(self, action: #selector(self.textChanged(_:)), for: .editingChanged) + + self.addSubview(self.textField) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + } + + @objc func textChanged(_ sender: Any) { + self.component?.textUpdated(self.textField.text ?? "") + } + + func update(component: TitleFieldComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.textField.textColor = component.textColor + self.textField.text = component.text + self.textField.font = Font.regular(17.0) + + self.component = component + self.state = state + + let titleCredibilityContent: EmojiStatusComponent.Content + if component.fileId == 0 { + titleCredibilityContent = .topic(title: String(component.text.prefix(1))) + } else { + titleCredibilityContent = .animation(content: .customEmoji(fileId: component.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: component.placeholderColor, themeColor: component.accentColor, loopMode: .count(2)) + } + + let iconSize = self.iconView.update( + transition: .easeInOut(duration: 0.2), + component: AnyComponent(EmojiStatusComponent( + context: component.context, + animationCache: component.context.animationCache, + animationRenderer: component.context.animationRenderer, + content: titleCredibilityContent, + isVisibleForAnimations: true, + action: nil + )), + environment: {}, + containerSize: CGSize(width: 32.0, height: 32.0) + ) + + if let iconComponentView = self.iconView.view { + if iconComponentView.superview == nil { + self.addSubview(iconComponentView) + } + + iconComponentView.frame = CGRect(origin: CGPoint(x: 15.0, y: floorToScreenPixels((availableSize.height - iconSize.height) / 2.0)), size: iconSize) + + self.textField.becomeFirstResponder() + } + + self.textField.frame = CGRect(x: 15.0 + iconSize.width + 15.0, y: 0.0, width: availableSize.width - 46.0 - iconSize.width, height: 44.0) + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +private final class TopicIconSelectionComponent: Component { + public typealias EnvironmentType = Empty + + public let theme: PresentationTheme + public let strings: PresentationStrings + public let deviceMetrics: DeviceMetrics + public let emojiContent: EmojiPagerContentComponent + public let backgroundColor: UIColor + public let separatorColor: UIColor + + public init( + theme: PresentationTheme, + strings: PresentationStrings, + deviceMetrics: DeviceMetrics, + emojiContent: EmojiPagerContentComponent, + backgroundColor: UIColor, + separatorColor: UIColor + ) { + self.theme = theme + self.strings = strings + self.deviceMetrics = deviceMetrics + self.emojiContent = emojiContent + self.backgroundColor = backgroundColor + self.separatorColor = separatorColor + } + + public static func ==(lhs: TopicIconSelectionComponent, rhs: TopicIconSelectionComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings != rhs.strings { + return false + } + if lhs.deviceMetrics != rhs.deviceMetrics { + return false + } + if lhs.emojiContent != rhs.emojiContent { + return false + } + if lhs.backgroundColor != rhs.backgroundColor { + return false + } + if lhs.separatorColor != rhs.separatorColor { + return false + } + return true + } + + public final class View: UIView { + private let keyboardView: ComponentView + private let keyboardClippingView: UIView + private let panelHostView: PagerExternalTopPanelContainer + private let panelBackgroundView: BlurredBackgroundView + private let panelSeparatorView: UIView + + private var component: TopicIconSelectionComponent? + private weak var state: EmptyComponentState? + + override init(frame: CGRect) { + self.keyboardView = ComponentView() + self.keyboardClippingView = UIView() + self.panelHostView = PagerExternalTopPanelContainer() + self.panelBackgroundView = BlurredBackgroundView(color: .clear, enableBlur: true) + self.panelSeparatorView = UIView() + + super.init(frame: frame) + + self.addSubview(self.keyboardClippingView) + self.addSubview(self.panelBackgroundView) + self.addSubview(self.panelSeparatorView) + self.addSubview(self.panelHostView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + } + + func update(component: TopicIconSelectionComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.backgroundColor = component.backgroundColor + let panelBackgroundColor = component.backgroundColor.withMultipliedAlpha(0.85) + self.panelBackgroundView.updateColor(color: panelBackgroundColor, transition: .immediate) + self.panelSeparatorView.backgroundColor = component.separatorColor + + self.component = component + self.state = state + + let topPanelHeight: CGFloat = 42.0 + + let keyboardSize = self.keyboardView.update( + transition: transition.withUserData(EmojiPagerContentComponent.SynchronousLoadBehavior(isDisabled: true)), + component: AnyComponent(EntityKeyboardComponent( + theme: component.theme, + strings: component.strings, + isContentInFocus: true, + containerInsets: UIEdgeInsets(top: topPanelHeight - 34.0, left: 0.0, bottom: 0.0, right: 0.0), + topPanelInsets: UIEdgeInsets(top: 0.0, left: 4.0, bottom: 0.0, right: 4.0), + emojiContent: component.emojiContent, + stickerContent: nil, + gifContent: nil, + hasRecentGifs: false, + availableGifSearchEmojies: [], + defaultToEmojiTab: true, + externalTopPanelContainer: self.panelHostView, + topPanelExtensionUpdated: { _, _ in }, + hideInputUpdated: { _, _, _ in }, + hideTopPanelUpdated: { _, _ in }, + switchToTextInput: {}, + switchToGifSubject: { _ in }, + reorderItems: { _, _ in }, + makeSearchContainerNode: { _ in return nil }, + deviceMetrics: component.deviceMetrics, + hiddenInputHeight: 0.0, + displayBottomPanel: false, + isExpanded: false + )), + environment: {}, + containerSize: availableSize + ) + if let keyboardComponentView = self.keyboardView.view { + if keyboardComponentView.superview == nil { + self.keyboardClippingView.addSubview(keyboardComponentView) + } + + if panelBackgroundColor.alpha < 0.01 { + self.keyboardClippingView.clipsToBounds = true + } else { + self.keyboardClippingView.clipsToBounds = false + } + + transition.setFrame(view: self.keyboardClippingView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight), size: CGSize(width: availableSize.width, height: availableSize.height - topPanelHeight))) + + transition.setFrame(view: keyboardComponentView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topPanelHeight), size: keyboardSize)) + transition.setFrame(view: self.panelHostView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight - 34.0), size: CGSize(width: keyboardSize.width, height: 0.0))) + + transition.setFrame(view: self.panelBackgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: keyboardSize.width, height: topPanelHeight))) + self.panelBackgroundView.update(size: self.panelBackgroundView.bounds.size, transition: transition.containedViewLayoutTransition) + + transition.setFrame(view: self.panelSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight), size: CGSize(width: keyboardSize.width, height: UIScreenPixel))) + transition.setAlpha(view: self.panelSeparatorView, alpha: 1.0) + } + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +private final class ForumCreateTopicScreenComponent: CombinedComponent { + typealias EnvironmentType = ViewControllerComponentContainer.Environment + + let context: AccountContext + let peerId: EnginePeer.Id + let mode: ForumCreateTopicScreen.Mode + let titleUpdated: (String) -> Void + + init(context: AccountContext, peerId: EnginePeer.Id, mode: ForumCreateTopicScreen.Mode, titleUpdated: @escaping (String) -> Void) { + self.context = context + self.peerId = peerId + self.mode = mode + self.titleUpdated = titleUpdated + } + + static func ==(lhs: ForumCreateTopicScreenComponent, rhs: ForumCreateTopicScreenComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.peerId != rhs.peerId { + return false + } + if lhs.mode != rhs.mode { + return false + } + return true + } + + final class State: ComponentState { + private let context: AccountContext + private let titleUpdated: (String) -> Void + + var emojiContent: EmojiPagerContentComponent? + private let emojiContentDisposable = MetaDisposable() + + var title: String + var fileId: Int64 + + init(context: AccountContext, mode: ForumCreateTopicScreen.Mode, titleUpdated: @escaping (String) -> Void) { + self.context = context + self.titleUpdated = titleUpdated + + switch mode { + case .create: + self.title = "" + self.fileId = 0 + case let .edit(topic): + self.title = topic.info.title + self.fileId = topic.info.icon ?? 0 + } + + super.init() + + self.emojiContentDisposable.set(( + EmojiPagerContentComponent.emojiInputData( + context: self.context, + animationCache: self.context.animationCache, + animationRenderer: self.context.animationRenderer, + isStandalone: false, + isStatusSelection: false, + isReactionSelection: false, + isTopicIconSelection: true, + topReactionItems: [], + areUnicodeEmojiEnabled: false, + areCustomEmojiEnabled: true, + chatPeerId: self.context.account.peerId, + selectedItems: Set(), + topicTitle: self.title + ) + |> deliverOnMainQueue).start(next: { [weak self] content in + self?.emojiContent = content + self?.updated(transition: .immediate) + })) + } + + deinit { + self.emojiContentDisposable.dispose() + } + + func updateTitle(_ text: String) { + self.title = text + self.updated(transition: .immediate) + + self.titleUpdated(text) + + self.emojiContentDisposable.set(( + EmojiPagerContentComponent.emojiInputData( + context: self.context, + animationCache: self.context.animationCache, + animationRenderer: self.context.animationRenderer, + isStandalone: false, + isStatusSelection: false, + isReactionSelection: false, + isTopicIconSelection: true, + topReactionItems: [], + areUnicodeEmojiEnabled: false, + areCustomEmojiEnabled: true, + chatPeerId: self.context.account.peerId, + selectedItems: Set([MediaId(namespace: Namespaces.Media.CloudFile, id: self.fileId)]), + topicTitle: self.title + ) + |> deliverOnMainQueue).start(next: { [weak self] content in + self?.emojiContent = content + self?.updated(transition: .immediate) + })) + } + + func applyItem(groupId: AnyHashable, item: EmojiPagerContentComponent.Item?) { + guard let item = item else { + return + } + + self.fileId = item.itemFile?.fileId.id ?? 0 + self.updated(transition: .immediate) + + self.emojiContentDisposable.set(( + EmojiPagerContentComponent.emojiInputData( + context: self.context, + animationCache: self.context.animationCache, + animationRenderer: self.context.animationRenderer, + isStandalone: false, + isStatusSelection: false, + isReactionSelection: false, + isTopicIconSelection: true, + topReactionItems: [], + areUnicodeEmojiEnabled: false, + areCustomEmojiEnabled: true, + chatPeerId: self.context.account.peerId, + selectedItems: Set([MediaId(namespace: Namespaces.Media.CloudFile, id: self.fileId)]), + topicTitle: self.title + ) + |> deliverOnMainQueue).start(next: { [weak self] content in + self?.emojiContent = content + self?.updated(transition: .immediate) + })) + } + } + + func makeState() -> State { + return State( + context: self.context, + mode: self.mode, + titleUpdated: self.titleUpdated + ) + } + + static var body: Body { + let background = Child(Rectangle.self) + let titleHeader = Child(MultilineTextComponent.self) + let titleBackground = Child(RoundedRectangle.self) + let titleField = Child(TitleFieldComponent.self) + + let iconHeader = Child(MultilineTextComponent.self) + let iconBackground = Child(RoundedRectangle.self) + let iconSelector = Child(TopicIconSelectionComponent.self) + + return { context in + let environment = context.environment[EnvironmentType.self].value + let state = context.state + + let background = background.update( + component: Rectangle( + color: environment.theme.list.blocksBackgroundColor + ), + environment: {}, + availableSize: context.availableSize, + transition: context.transition + ) + + context.add(background + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) + ) + + let sideInset: CGFloat = 16.0 + let topInset: CGFloat = 16.0 + environment.navigationHeight + let headerSpacing: CGFloat = 6.0 + let sectionSpacing: CGFloat = 30.0 + + var contentHeight = topInset + + let titleHeader = titleHeader.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString( + string: "ENTER TOPIC TITLE", + font: Font.regular(13.0), + textColor: environment.theme.list.freeTextColor, + paragraphAlignment: .natural) + ), + horizontalAlignment: .natural, + maximumNumberOfLines: 1 + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude), + transition: .immediate + ) + context.add(titleHeader + .position(CGPoint(x: sideInset * 2.0 + titleHeader.size.width / 2.0, y: contentHeight + titleHeader.size.height / 2.0)) + ) + contentHeight += titleHeader.size.height + headerSpacing + + let titleBackground = titleBackground.update( + component: RoundedRectangle( + color: environment.theme.list.itemBlocksBackgroundColor, + cornerRadius: 10.0 + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 44.0), + transition: context.transition + ) + context.add(titleBackground + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + titleBackground.size.height / 2.0)) + ) + + let titleField = titleField.update( + component: TitleFieldComponent( + context: context.component.context, + textColor: environment.theme.list.itemPrimaryTextColor, + accentColor: environment.theme.list.itemAccentColor, + placeholderColor: environment.theme.list.disclosureArrowColor, + fileId: state.fileId, + text: state.title, + textUpdated: { [weak state] text in + state?.updateTitle(text) + } + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 44.0), + transition: context.transition + ) + context.add(titleField + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + titleBackground.size.height / 2.0)) + ) + + contentHeight += titleBackground.size.height + sectionSpacing + + let iconHeader = iconHeader.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString( + string: "SELECT TOPIC ICON", + font: Font.regular(13.0), + textColor: environment.theme.list.freeTextColor, + paragraphAlignment: .natural) + ), + horizontalAlignment: .natural, + maximumNumberOfLines: 1 + ), + availableSize: CGSize( + width: context.availableSize.width - sideInset * 2.0, + height: CGFloat.greatestFiniteMagnitude + ), + transition: .immediate + ) + context.add(iconHeader + .position(CGPoint(x: sideInset * 2.0 + iconHeader.size.width / 2.0, y: contentHeight + iconHeader.size.height / 2.0)) + ) + contentHeight += iconHeader.size.height + headerSpacing + + let iconBackground = iconBackground.update( + component: RoundedRectangle( + color: environment.theme.list.itemBlocksBackgroundColor, + cornerRadius: 10.0 + ), + availableSize: CGSize( + width: context.availableSize.width - sideInset * 2.0, + height: context.availableSize.height - topInset - titleHeader.size.height - titleBackground.size.height + ), + transition: context.transition + ) + context.add(iconBackground + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + iconBackground.size.height / 2.0)) + ) + + if let emojiContent = state.emojiContent { + let availableHeight = context.availableSize.height - contentHeight - environment.inputHeight + + let iconSelector = iconSelector.update( + component: TopicIconSelectionComponent( + theme: environment.theme, + strings: environment.strings, + deviceMetrics: environment.deviceMetrics, + emojiContent: emojiContent, + backgroundColor: .clear, + separatorColor: environment.theme.list.blocksBackgroundColor + ), + environment: {}, + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: availableHeight), + transition: context.transition + ) + context.add(iconSelector + .position(CGPoint(x: context.availableSize.width / 2.0, y: contentHeight + iconSelector.size.height / 2.0)) + ) + + let accountContext = context.component.context + emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak state] groupId, item, _, _, _, _ in + state?.applyItem(groupId: groupId, item: item) + }, + deleteBackwards: { + }, + openStickerSettings: { + }, + openFeatured: { + }, + addGroupAction: { groupId, isPremiumLocked in + guard let collectionId = groupId.base as? ItemCollectionId else { + return + } + + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) + let _ = (accountContext.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { views in + guard let view = views.views[viewKey] as? OrderedItemListView else { + return + } + for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + if featuredEmojiPack.info.id == collectionId { +// if let strongSelf = self { +// strongSelf.scheduledEmojiContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId)) +// } + let _ = accountContext.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start() + + break + } + } + }) + }, + clearGroup: { _ in + }, + pushController: { c in + }, + presentController: { c in + }, + presentGlobalOverlayController: { c in + }, + navigationController: { + return nil + }, + requestUpdate: { _ in + }, + updateSearchQuery: { _, _ in + }, + chatPeerId: nil, + peekBehavior: nil, + customLayout: nil, + externalBackground: nil, + externalExpansionView: nil, + useOpaqueTheme: true + ) + } + + return context.availableSize + } + } +} + +public class ForumCreateTopicScreen: ViewControllerComponentContainer { + public enum Mode: Equatable { + case create + case edit(topic: ForumChannelTopics.Item) + } + + public init(context: AccountContext, peerId: EnginePeer.Id, mode: ForumCreateTopicScreen.Mode) { + var titleUpdatedImpl: ((String) -> Void)? + super.init(context: context, component: ForumCreateTopicScreenComponent(context: context, peerId: peerId, mode: mode, titleUpdated: { title in + titleUpdatedImpl?(title) + }), navigationBarAppearance: .transparent) + + let title: String + let doneTitle: String + switch mode { + case .create: + title = "New Topic" + doneTitle = "Create" + case .edit: + title = "Edit Topic" + doneTitle = "Done" + } + + self.title = title + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)) + + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: doneTitle, style: .done, target: self, action: #selector(self.createPressed)) + self.navigationItem.rightBarButtonItem?.isEnabled = false + + titleUpdatedImpl = { [weak self] title in + self?.navigationItem.rightBarButtonItem?.isEnabled = !title.isEmpty + } + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func cancelPressed() { + self.dismiss() + } + + @objc private func createPressed() { + self.dismiss() + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/Contents.json new file mode 100644 index 0000000000..248b5e5859 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "phonecall_24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/phonecall_24.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/phonecall_24.pdf new file mode 100644 index 0000000000..bb3744733a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/PhoneCall.imageset/phonecall_24.pdf @@ -0,0 +1,424 @@ +%PDF-1.7 + +1 0 obj + << /Type /XObject + /Length 2 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 24.000000 24.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +1.000000 0.000000 -0.000000 1.000000 4.500000 1.839966 cm +2.336997 17.660034 m +2.662117 17.660034 2.919991 17.531717 3.113886 17.260115 c +4.585419 14.879068 l +4.920160 14.337935 4.887798 13.646688 4.503964 13.139196 c +3.449515 11.745041 l +3.304240 11.606829 3.209649 11.367731 3.209649 11.106469 c +3.209649 10.919914 3.258480 10.760313 3.345299 10.569205 c +3.613995 10.003538 4.318002 9.122787 5.191207 8.228218 c +5.368025 8.049210 l +6.244456 7.163609 7.244257 6.357477 7.850526 6.038754 c +8.070224 5.937879 8.234513 5.889532 8.432807 5.889532 c +8.701159 5.889532 8.948185 5.981611 9.144370 6.177905 c +10.453788 7.178677 l +10.962485 7.569689 11.660256 7.604506 12.205351 7.266076 c +14.664220 5.739452 l +14.893296 5.579560 15.000061 5.360890 15.000061 5.068824 c +15.000061 4.668618 14.761724 4.178541 14.364333 3.757545 c +13.671964 3.012113 12.839583 2.659973 11.811339 2.659973 c +9.637396 2.659973 6.759635 4.298767 4.190047 6.869761 c +1.619593 9.441620 0.000000 12.297401 0.000000 14.478063 c +0.000000 15.496849 0.341778 16.351761 1.049306 17.037554 c +1.462726 17.444048 1.928928 17.660034 2.336997 17.660034 c +h +0.000000 0.000000 0.000000 scn +f +n + +endstream +endobj + +2 0 obj + 1177 +endobj + +3 0 obj + << /Length 4 0 R + /FunctionType 4 + /Domain [ 0.000000 1.000000 ] + /Range [ 0.000000 1.000000 ] + >> +stream +{ 0 gt { 0 } { 1 } ifelse } +endstream +endobj + +4 0 obj + 27 +endobj + +5 0 obj + << /ExtGState << /E1 << /SMask << /Type /Mask + /G 1 0 R + /S /Alpha + /TR 3 0 R + >> + /Type /ExtGState + >> >> >> +endobj + +6 0 obj + << /Length 7 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +/E1 gs +q +1.000000 0.000000 -0.000000 1.000000 4.500000 1.839966 cm +0.000000 0.000000 0.000000 scn +3.113886 17.260115 m +4.245259 17.959326 l +4.222027 17.996916 l +4.196352 18.032883 l +3.113886 17.260115 l +h +4.585419 14.879068 m +3.454046 14.179857 l +3.454337 14.179388 l +4.585419 14.879068 l +h +4.503964 13.139196 m +3.443199 13.941491 l +3.443199 13.941490 l +4.503964 13.139196 l +h +3.449515 11.745041 m +4.366253 10.781459 l +4.444844 10.856229 l +4.510280 10.942745 l +3.449515 11.745041 l +h +3.345299 10.569205 m +2.134399 10.019096 l +2.139083 10.008785 l +2.143943 9.998554 l +3.345299 10.569205 l +h +5.191207 8.228218 m +4.239443 7.299183 l +4.244984 7.293574 l +5.191207 8.228218 l +h +5.368025 8.049210 m +4.421801 7.114565 l +4.422691 7.113666 l +5.368025 8.049210 l +h +7.850526 6.038754 m +7.231641 4.861520 l +7.263175 4.844942 l +7.295551 4.830077 l +7.850526 6.038754 l +h +9.144370 6.177905 m +8.336740 7.234614 l +8.266318 7.180791 l +8.203662 7.118100 l +9.144370 6.177905 l +h +10.453788 7.178677 m +11.261421 6.121964 l +11.264320 6.124193 l +10.453788 7.178677 l +h +12.205351 7.266076 m +12.906886 8.396009 l +12.906886 8.396009 l +12.205351 7.266076 l +h +14.664220 5.739452 m +15.425447 6.830063 l +15.396130 6.850527 l +15.365755 6.869386 l +14.664220 5.739452 l +h +14.364333 3.757545 m +13.397125 4.670519 l +13.389837 4.662673 l +14.364333 3.757545 l +h +4.190047 6.869761 m +5.130756 7.809957 l +5.130756 7.809957 l +4.190047 6.869761 l +h +1.049306 17.037554 m +1.974998 16.082523 l +1.981782 16.089191 l +1.049306 17.037554 l +h +2.336997 16.330034 m +2.320346 16.330034 2.253638 16.334621 2.169936 16.377350 c +2.085590 16.420408 2.041937 16.472618 2.031421 16.487349 c +4.196352 18.032883 l +3.748895 18.659664 3.084965 18.990034 2.336997 18.990034 c +2.336997 16.330034 l +h +1.982513 16.560905 m +3.454046 14.179857 l +5.716792 15.578279 l +4.245259 17.959326 l +1.982513 16.560905 l +h +3.454337 14.179388 m +3.500106 14.105397 3.495682 14.010881 3.443199 13.941491 c +5.564729 12.336901 l +6.279915 13.282494 6.340214 14.570473 5.716501 15.578749 c +3.454337 14.179388 l +h +3.443199 13.941490 m +2.388749 12.547336 l +4.510280 10.942745 l +5.564729 12.336901 l +3.443199 13.941490 l +h +2.532776 12.708622 m +2.068971 12.267365 1.879649 11.648950 1.879649 11.106469 c +4.539649 11.106469 l +4.539649 11.079510 4.535252 11.043770 4.517922 10.998292 c +4.502114 10.956808 4.462042 10.872591 4.366253 10.781459 c +2.532776 12.708622 l +h +1.879649 11.106469 m +1.879649 10.656174 2.006887 10.299776 2.134399 10.019096 c +4.556200 11.119314 l +4.543678 11.146877 4.536608 11.164371 4.532750 11.174656 c +4.529046 11.184531 4.529113 11.185631 4.530626 11.179913 c +4.532265 11.173723 4.534810 11.162544 4.536798 11.147743 c +4.538805 11.132805 4.539649 11.118605 4.539649 11.106469 c +1.879649 11.106469 l +h +2.143943 9.998554 m +2.513995 9.219506 3.354690 8.205615 4.239460 7.299199 c +6.142955 9.157238 l +5.281314 10.039959 4.713994 10.787569 4.546656 11.139856 c +2.143943 9.998554 l +h +4.244984 7.293574 m +4.421802 7.114566 l +6.314249 8.983854 l +6.137431 9.162863 l +4.244984 7.293574 l +h +4.422691 7.113666 m +5.333439 6.193388 6.446281 5.274392 7.231641 4.861520 c +8.469412 7.215989 l +8.042233 7.440562 7.155473 8.133829 6.313359 8.984755 c +4.422691 7.113666 l +h +7.295551 4.830077 m +7.610502 4.685464 7.971885 4.559532 8.432807 4.559532 c +8.432807 7.219532 l +8.438139 7.219532 8.448376 7.219153 8.461496 7.217438 c +8.474616 7.215722 8.484693 7.213446 8.489946 7.212055 c +8.494530 7.210842 8.491272 7.211398 8.477601 7.216578 c +8.463371 7.221971 8.440556 7.231338 8.405501 7.247433 c +7.295551 4.830077 l +h +8.432807 4.559532 m +9.024679 4.559532 9.619445 4.771820 10.085079 5.237710 c +8.203662 7.118100 l +8.232141 7.146595 8.273987 7.176050 8.325019 7.196304 c +8.374480 7.215935 8.413715 7.219532 8.432807 7.219532 c +8.432807 4.559532 l +h +9.952001 5.121196 m +11.261418 6.121968 l +9.646158 8.235386 l +8.336740 7.234614 l +9.952001 5.121196 l +h +11.264320 6.124193 m +11.333877 6.177657 11.429284 6.182418 11.503816 6.136144 c +12.906886 8.396009 l +11.891228 9.026595 10.591094 8.961720 9.643255 8.233161 c +11.264320 6.124193 l +h +11.503816 6.136144 m +13.962685 4.609520 l +15.365755 6.869386 l +12.906886 8.396009 l +11.503816 6.136144 l +h +13.902991 4.648842 m +13.857372 4.680683 13.782755 4.749804 13.727364 4.861100 c +13.674102 4.968115 13.670061 5.050985 13.670061 5.068824 c +16.330061 5.068824 l +16.330061 5.757030 16.041370 6.400160 15.425447 6.830063 c +13.902991 4.648842 l +h +13.670061 5.068824 m +13.670061 5.122084 13.682167 5.099532 13.634643 5.001590 c +13.590631 4.910884 13.513090 4.793310 13.397157 4.670489 c +15.331510 2.844599 l +15.856868 3.401164 16.330061 4.202022 16.330061 5.068824 c +13.670061 5.068824 l +h +13.389837 4.662673 m +12.957663 4.197376 12.482564 3.989973 11.811339 3.989973 c +11.811339 1.329973 l +13.196602 1.329973 14.386265 1.826848 15.338829 2.852416 c +13.389837 4.662673 l +h +11.811339 3.989973 m +11.034931 3.989973 10.000110 4.292040 8.796299 4.962632 c +7.609632 5.623674 6.344436 6.595613 5.130756 7.809957 c +3.249338 5.929566 l +4.605247 4.572916 6.063725 3.439960 7.501822 2.638857 c +8.922773 1.847304 10.413804 1.329973 11.811339 1.329973 c +11.811339 3.989973 l +h +5.130756 7.809957 m +3.916355 9.025021 2.949746 10.284932 2.293909 11.466198 c +1.629269 12.663321 1.330000 13.695452 1.330000 14.478063 c +-1.330000 14.478063 l +-1.330000 13.080011 -0.819472 11.593922 -0.031702 10.175023 c +0.764871 8.740269 1.893285 7.286361 3.249338 5.929566 c +5.130756 7.809957 l +h +1.330000 14.478063 m +1.330000 15.163555 1.544419 15.665218 1.974975 16.082546 c +0.123637 17.992559 l +-0.860863 17.038303 -1.330000 15.830142 -1.330000 14.478063 c +1.330000 14.478063 l +h +1.981782 16.089191 m +2.096122 16.201618 2.197214 16.267076 2.268798 16.301296 c +2.342271 16.336422 2.365401 16.330034 2.336997 16.330034 c +2.336997 18.990034 l +1.477759 18.990034 0.695014 18.554413 0.116830 17.985914 c +1.981782 16.089191 l +h +f +n +Q +Q +q +1.000000 0.000000 -0.000000 1.000000 13.000000 13.000000 cm +0.000000 0.000000 0.000000 scn +1.000000 6.000000 m +1.552285 6.000000 2.000000 6.447715 2.000000 7.000000 c +2.000000 7.552285 1.552285 8.000000 1.000000 8.000000 c +0.447715 8.000000 0.000000 7.552285 0.000000 7.000000 c +0.000000 6.447715 0.447715 6.000000 1.000000 6.000000 c +h +5.000000 7.000000 m +5.000000 6.447715 4.552284 6.000000 4.000000 6.000000 c +3.447716 6.000000 3.000000 6.447715 3.000000 7.000000 c +3.000000 7.552285 3.447716 8.000000 4.000000 8.000000 c +4.552284 8.000000 5.000000 7.552285 5.000000 7.000000 c +h +8.000000 7.000000 m +8.000000 6.447715 7.552284 6.000000 7.000000 6.000000 c +6.447716 6.000000 6.000000 6.447715 6.000000 7.000000 c +6.000000 7.552285 6.447716 8.000000 7.000000 8.000000 c +7.552284 8.000000 8.000000 7.552285 8.000000 7.000000 c +h +8.000000 4.000000 m +8.000000 3.447715 7.552284 3.000000 7.000000 3.000000 c +6.447716 3.000000 6.000000 3.447715 6.000000 4.000000 c +6.000000 4.552285 6.447716 5.000000 7.000000 5.000000 c +7.552284 5.000000 8.000000 4.552285 8.000000 4.000000 c +h +4.000000 3.000000 m +4.552284 3.000000 5.000000 3.447715 5.000000 4.000000 c +5.000000 4.552285 4.552284 5.000000 4.000000 5.000000 c +3.447716 5.000000 3.000000 4.552285 3.000000 4.000000 c +3.000000 3.447715 3.447716 3.000000 4.000000 3.000000 c +h +2.000000 4.000000 m +2.000000 3.447715 1.552285 3.000000 1.000000 3.000000 c +0.447715 3.000000 0.000000 3.447715 0.000000 4.000000 c +0.000000 4.552285 0.447715 5.000000 1.000000 5.000000 c +1.552285 5.000000 2.000000 4.552285 2.000000 4.000000 c +h +7.000000 0.000000 m +7.552284 0.000000 8.000000 0.447715 8.000000 1.000000 c +8.000000 1.552285 7.552284 2.000000 7.000000 2.000000 c +6.447716 2.000000 6.000000 1.552285 6.000000 1.000000 c +6.000000 0.447715 6.447716 0.000000 7.000000 0.000000 c +h +5.000000 1.000000 m +5.000000 0.447715 4.552284 0.000000 4.000000 0.000000 c +3.447716 0.000000 3.000000 0.447715 3.000000 1.000000 c +3.000000 1.552285 3.447716 2.000000 4.000000 2.000000 c +4.552284 2.000000 5.000000 1.552285 5.000000 1.000000 c +h +1.000000 0.000000 m +1.552285 0.000000 2.000000 0.447715 2.000000 1.000000 c +2.000000 1.552285 1.552285 2.000000 1.000000 2.000000 c +0.447715 2.000000 0.000000 1.552285 0.000000 1.000000 c +0.000000 0.447715 0.447715 0.000000 1.000000 0.000000 c +h +f* +n +Q + +endstream +endobj + +7 0 obj + 8188 +endobj + +8 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 5 0 R + /Contents 6 0 R + /Parent 9 0 R + >> +endobj + +9 0 obj + << /Kids [ 8 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +10 0 obj + << /Pages 9 0 R + /Type /Catalog + >> +endobj + +xref +0 11 +0000000000 65535 f +0000000010 00000 n +0000001435 00000 n +0000001458 00000 n +0000001633 00000 n +0000001654 00000 n +0000001966 00000 n +0000010210 00000 n +0000010233 00000 n +0000010406 00000 n +0000010480 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +10540 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift index 393597ee46..52aad3bd1a 100644 --- a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift @@ -316,7 +316,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { backgroundContent.clipsToBounds = true strongSelf.backgroundContent = backgroundContent - strongSelf.insertSubnode(backgroundContent, at: 0) + strongSelf.offsetContainer.insertSubnode(backgroundContent, at: 0) } } else { strongSelf.backgroundContent?.removeFromSupernode() diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index cd06e81307..52c9198f45 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -108,6 +108,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private let inputPanelOverlayNode: SparseNode private let inputPanelClippingNode: SparseNode private let inputPanelBackgroundNode: NavigationBackgroundNode + + private var navigationBarBackgroundContent: WallpaperBubbleBackgroundNode? + private var inputPanelBackgroundContent: WallpaperBubbleBackgroundNode? + private var intrinsicInputPanelBackgroundNodeSize: CGSize? private let inputPanelBackgroundSeparatorNode: ASDisplayNode private var inputPanelBottomBackgroundSeparatorBaseOffset: CGFloat = 0.0 @@ -1670,6 +1674,18 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.updatePosition(node: self.inputPanelOverlayNode, position: CGRect(origin: apparentInputBackgroundFrame.origin, size: layout.size).center, beginWithCurrentState: true) transition.updateBounds(node: self.inputPanelOverlayNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: layout.size), beginWithCurrentState: true) transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame, beginWithCurrentState: true) + + if let navigationBarBackgroundContent = self.navigationBarBackgroundContent { + transition.updateFrame(node: navigationBarBackgroundContent, frame: CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0))), beginWithCurrentState: true) + navigationBarBackgroundContent.update(rect: CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0))), within: layout.size, transition: transition) + } + + if let inputPanelBackgroundContent = self.inputPanelBackgroundContent { + var apparentInputBackgroundFrame = apparentInputBackgroundFrame + apparentInputBackgroundFrame.size.height += 34.0 + transition.updateFrame(node: inputPanelBackgroundContent, frame: CGRect(origin: .zero, size: apparentInputBackgroundFrame.size), beginWithCurrentState: true) + inputPanelBackgroundContent.update(rect: apparentInputBackgroundFrame, within: layout.size, transition: transition) + } transition.updateFrame(node: self.contentDimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: apparentInputBackgroundFrame.origin.y))) @@ -2069,6 +2085,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + extensionValue), transition: transition) transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBottomBackgroundSeparatorBaseOffset + extensionValue), size: CGSize(width: self.inputPanelBottomBackgroundSeparatorNode.bounds.width, height: UIScreenPixel)), beginWithCurrentState: true) + + if let inputPanelBackgroundContent = self.inputPanelBackgroundContent, let (layout, _) = self.validLayout { + var inputPanelBackgroundFrame = self.inputPanelBackgroundNode.frame + inputPanelBackgroundFrame.size.height = intrinsicInputPanelBackgroundNodeSize.height + extensionValue + + transition.updateFrame(node: inputPanelBackgroundContent, frame: CGRect(origin: .zero, size: inputPanelBackgroundFrame.size)) + inputPanelBackgroundContent.update(rect: inputPanelBackgroundFrame, within: layout.size, transition: transition) + } } private var storedHideInputExpanded: Bool? @@ -2171,11 +2195,37 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.usePlainInputSeparator = false self.plainInputSeparatorAlpha = nil } + self.updatePlainInputSeparator(transition: .immediate) self.inputPanelBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputPanel.panelSeparatorColor self.inputPanelBottomBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputMediaPanel.panelSeparatorColor self.backgroundNode.updateBubbleTheme(bubbleTheme: chatPresentationInterfaceState.theme, bubbleCorners: chatPresentationInterfaceState.bubbleCorners) + + if self.backgroundNode.hasExtraBubbleBackground() { + if self.navigationBarBackgroundContent == nil { + if let navigationBarBackgroundContent = self.backgroundNode.makeBubbleBackground(for: .free), + let inputPanelBackgroundContent = self.backgroundNode.makeBubbleBackground(for: .free) { + self.navigationBarBackgroundContent = navigationBarBackgroundContent + self.inputPanelBackgroundContent = inputPanelBackgroundContent + + navigationBarBackgroundContent.allowsGroupOpacity = true + navigationBarBackgroundContent.implicitContentUpdate = false + navigationBarBackgroundContent.alpha = 0.2 + self.navigationBar?.insertSubnode(navigationBarBackgroundContent, at: 1) + + inputPanelBackgroundContent.allowsGroupOpacity = true + inputPanelBackgroundContent.implicitContentUpdate = false + inputPanelBackgroundContent.alpha = 0.2 + self.inputPanelBackgroundNode.addSubnode(inputPanelBackgroundContent) + } + } + } else { + self.navigationBarBackgroundContent?.removeFromSupernode() + self.navigationBarBackgroundContent = nil + self.inputPanelBackgroundContent?.removeFromSupernode() + self.inputPanelBackgroundContent = nil + } } let keepSendButtonEnabled = chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil || chatPresentationInterfaceState.interfaceState.editMessage != nil diff --git a/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift index 6d0606d162..90b4f99192 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift @@ -223,16 +223,31 @@ private final class ChatMessageActionButtonNode: ASDisplayNode { node.backgroundBlurNode.isHidden = false } - if position == .bottomSingle { - let rect = node.backgroundBlurNode.bounds - let maskPath = UIBezierPath(roundRect: rect, topLeftRadius: bubbleCorners.auxiliaryRadius, topRightRadius: bubbleCorners.auxiliaryRadius, bottomLeftRadius: bubbleCorners.mainRadius, bottomRightRadius: bubbleCorners.mainRadius) - let shape = CAShapeLayer() - shape.path = maskPath.cgPath - node.layer.mask = shape - } else { - node.layer.mask = nil + + let rect = node.backgroundBlurNode.bounds + let maskPath: CGPath? + switch position { + case .bottomSingle: + maskPath = UIBezierPath(roundRect: rect, topLeftRadius: bubbleCorners.auxiliaryRadius, topRightRadius: bubbleCorners.auxiliaryRadius, bottomLeftRadius: bubbleCorners.mainRadius, bottomRightRadius: bubbleCorners.mainRadius).cgPath + case .bottomLeft: + maskPath = UIBezierPath(roundRect: rect, topLeftRadius: bubbleCorners.auxiliaryRadius, topRightRadius: bubbleCorners.auxiliaryRadius, bottomLeftRadius: bubbleCorners.mainRadius, bottomRightRadius: bubbleCorners.auxiliaryRadius).cgPath + case .bottomRight: + maskPath = UIBezierPath(roundRect: rect, topLeftRadius: bubbleCorners.auxiliaryRadius, topRightRadius: bubbleCorners.auxiliaryRadius, bottomLeftRadius: bubbleCorners.auxiliaryRadius, bottomRightRadius: bubbleCorners.mainRadius).cgPath + default: + maskPath = nil } + let currentMaskPath = (node.layer.mask as? CAShapeLayer)?.path + if currentMaskPath != maskPath { + if let maskPath = maskPath { + let shapeLayer = CAShapeLayer() + shapeLayer.path = maskPath + node.layer.mask = shapeLayer + } else { + node.layer.mask = nil + } + } + if iconImage != nil { if node.iconNode == nil { let iconNode = ASImageNode() diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 025bbccd7c..9b0c04b56a 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -1133,7 +1133,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode ignoreForward = true effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) } } displayAuthorInfo = !mergedTop.merged && incoming && effectiveAuthor != nil @@ -1149,7 +1149,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode displayAuthorInfo = !mergedTop.merged && incoming } else if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature { ignoreForward = true - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) displayAuthorInfo = !mergedTop.merged && incoming } else if let _ = item.content.firstMessage.adAttribute, let author = item.content.firstMessage.author { ignoreForward = true diff --git a/submodules/TelegramUI/Sources/ChatMessageItem.swift b/submodules/TelegramUI/Sources/ChatMessageItem.swift index df65a72313..89436c8a97 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageItem.swift @@ -305,7 +305,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { if let forwardInfo = content.firstMessage.forwardInfo { effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) } } displayAuthorInfo = incoming && effectiveAuthor != nil diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 05c523dcbe..b8c99d6a02 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -659,6 +659,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { let emptyFrame = CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight), size: CGSize(width: layout.size.width, height: layout.size.height - navigationBarHeight - panelHeight)) transition.updateFrame(node: self.emptyNode, frame: emptyFrame) + self.emptyNode.update(rect: emptyFrame, within: layout.size) self.emptyNode.updateLayout(backgroundNode: self.backgroundNode, size: emptyFrame.size, transition: transition) let contentBottomInset: CGFloat = panelHeight + 4.0 diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index d4f7922556..10d06ed9a1 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -66,7 +66,7 @@ private func filterOriginalMessageFlags(_ message: Message) -> Message { private func filterMessageChannelPeer(_ peer: Peer) -> Peer { if let peer = peer as? TelegramChannel { - return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, defaultBannedRights: peer.defaultBannedRights) + return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, defaultBannedRights: peer.defaultBannedRights, usernames: peer.usernames) } return peer } diff --git a/submodules/TelegramUI/Sources/ChatRestrictedNode.swift b/submodules/TelegramUI/Sources/ChatRestrictedNode.swift deleted file mode 100644 index 8b13789179..0000000000 --- a/submodules/TelegramUI/Sources/ChatRestrictedNode.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift index 244eed07ea..9dfb49fd67 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -530,7 +530,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { self.containerNode.frame = CGRect(origin: CGPoint(), size: contentSize) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: contentSize) self.contextSourceNode.contentNode.frame = CGRect(origin: CGPoint(), size: contentSize) - self.containerNode.isGestureEnabled = false + self.containerNode.isGestureEnabled = item.contextAction != nil let nonExtractedRect = CGRect(origin: CGPoint(), size: CGSize(width: contentSize.width, height: contentSize.height)) let extractedRect = nonExtractedRect @@ -627,7 +627,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { } else { linkHighlightingNode = LinkHighlightingNode(color: theme.list.itemAccentColor.withAlphaComponent(0.5)) self.linkHighlightingNode = linkHighlightingNode - self.insertSubnode(linkHighlightingNode, belowSubnode: textNode) + self.contextSourceNode.contentNode.insertSubnode(linkHighlightingNode, belowSubnode: textNode) } linkHighlightingNode.frame = textNode.frame linkHighlightingNode.updateRects(rects) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift index 1633da1ec1..3ad85bb14e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift @@ -457,6 +457,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat weak var parentController: ViewController? private let coveringBackgroundNode: NavigationBackgroundNode + private let additionalBackgroundNode: ASDisplayNode private let separatorNode: ASDisplayNode private let tabsContainerNode: PeerInfoPaneTabsContainerNode private let tabsSeparatorNode: ASDisplayNode @@ -514,6 +515,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat self.peerId = peerId self.isMediaOnly = isMediaOnly + self.additionalBackgroundNode = ASDisplayNode() + self.separatorNode = ASDisplayNode() self.separatorNode.isLayerBacked = true @@ -528,6 +531,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat super.init() // self.addSubnode(self.separatorNode) + self.addSubnode(self.additionalBackgroundNode) self.addSubnode(self.coveringBackgroundNode) self.addSubnode(self.tabsContainerNode) self.addSubnode(self.tabsSeparatorNode) @@ -745,9 +749,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction) +// transition.updateAlpha(node: self.additionalBackgroundNode, alpha: 1.0 - expansionFraction) + self.backgroundColor = presentationData.theme.list.plainBackgroundColor self.coveringBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor, transition: .immediate) self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.additionalBackgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor self.tabsSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor let isScrollingLockedAtTop = expansionFraction < 1.0 - CGFloat.ulpOfOne @@ -955,6 +962,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel - tabsOffset), size: CGSize(width: size.width, height: UIScreenPixel))) transition.updateFrame(node: self.coveringBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel - tabsOffset), size: CGSize(width: size.width, height: tabsHeight + UIScreenPixel))) + transition.updateFrame(node: self.additionalBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel - tabsOffset), size: CGSize(width: size.width, height: tabsHeight + UIScreenPixel))) self.coveringBackgroundNode.update(size: self.coveringBackgroundNode.bounds.size, transition: transition) transition.updateFrame(node: self.tabsSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: tabsHeight - tabsOffset), size: CGSize(width: size.width, height: UIScreenPixel))) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 18206af031..f1ce66ac3a 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -951,12 +951,18 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese })) } if let username = user.username { + var additionalUsernames: String? + let usernames = user.usernames.filter { !$0.flags.contains(.isEditable) && $0.flags.contains(.isActive) } + if !usernames.isEmpty { + additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string + } + items[.peerInfo]!.append( PeerInfoScreenLabeledValueItem( id: 1, label: presentationData.strings.Profile_Username, text: "@\(username)", - additionalText: nil, //presentationData.strings.Profile_AdditionalUsernames("@username1, @username2, @username3, @username4"), + additionalText: additionalUsernames, textColor: .accent, icon: .qrCode, action: { _ in @@ -1076,15 +1082,32 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } if let username = channel.username { - items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: ItemUsername, label: presentationData.strings.Channel_LinkItem, text: "https://t.me/\(username)", textColor: .accent, icon: .qrCode, action: { _ in - interaction.openUsername(username) - }, longTapAction: { sourceNode in - interaction.openPeerInfoContextMenu(.link, sourceNode) - }, iconAction: { - interaction.openQrCode() - }, requestLayout: { - interaction.requestLayout(false) - })) + var additionalUsernames: String? + let usernames = channel.usernames.filter { !$0.flags.contains(.isEditable) && $0.flags.contains(.isActive) } + if !usernames.isEmpty { + additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string + } + + + items[.peerInfo]!.append( + PeerInfoScreenLabeledValueItem( + id: ItemUsername, + label: presentationData.strings.Channel_LinkItem, + text: "https://t.me/\(username)", + additionalText: additionalUsernames, + textColor: .accent, + icon: .qrCode, + action: { _ in + interaction.openUsername(username) + }, longTapAction: { sourceNode in + interaction.openPeerInfoContextMenu(.link, sourceNode) + }, iconAction: { + interaction.openQrCode() + }, requestLayout: { + interaction.requestLayout(false) + } + ) + ) } if let cachedData = data.cachedData as? CachedChannelData { let aboutText: String? @@ -4902,34 +4925,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate guard let strongSelf = self else { return } -// if case let .user(peer) = peer, let peerPhoneNumber = peer.phone, formatPhoneNumber(value) == formatPhoneNumber(peerPhoneNumber) { -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// let dismissAction: () -> Void = { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// } -// actionSheet.setItemGroups([ -// ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.UserInfo_TelegramCall, action: { -// dismissAction() -// self?.requestCall(isVideo: false) -// }), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.UserInfo_PhoneCall, action: { -// dismissAction() -// -// guard let strongSelf = self else { -// return -// } -// strongSelf.context.sharedContext.applicationBindings.openUrl("tel:\(formatPhoneNumber(value).replacingOccurrences(of: " ", with: ""))") -// }), -// ]), -// ActionSheetItemGroup(items: [ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, action: { dismissAction() })]) -// ]) -// strongSelf.view.endEditing(true) -// strongSelf.controller?.present(actionSheet, in: .window(.root)) -// } else { -// strongSelf.context.sharedContext.applicationBindings.openUrl("tel:\(formatPhoneNumber(value).replacingOccurrences(of: " ", with: ""))") -// } -// let presentationData = strongSelf.presentationData let telegramCallAction: (Bool) -> Void = { [weak self] isVideo in @@ -4968,7 +4963,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } }))) - items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_PhoneCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: ""), color: theme.contextMenu.primaryColor) }, action: { c, _ in + items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_PhoneCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/PhoneCall"), color: theme.contextMenu.primaryColor) }, action: { c, _ in c.dismiss { phoneCallAction() } @@ -4980,7 +4975,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } else { items = [ - .action(ContextMenuActionItem(text: presentationData.strings.UserInfo_PhoneCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: ""), color: theme.contextMenu.primaryColor) }, action: { c, _ in + .action(ContextMenuActionItem(text: presentationData.strings.UserInfo_PhoneCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/PhoneCall"), color: theme.contextMenu.primaryColor) }, action: { c, _ in c.dismiss { phoneCallAction() } diff --git a/submodules/TelegramUI/Sources/PollResultsController.swift b/submodules/TelegramUI/Sources/PollResultsController.swift index 22ab7806ae..8e486a83c7 100644 --- a/submodules/TelegramUI/Sources/PollResultsController.swift +++ b/submodules/TelegramUI/Sources/PollResultsController.swift @@ -251,7 +251,7 @@ private func pollResultsControllerEntries(presentationData: PresentationData, po displayCount = Int(voterCount) } for peerIndex in 0 ..< displayCount { - let fakeUser = TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil) + let fakeUser = TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) let peer = RenderedPeer(peer: fakeUser) entries.append(.optionPeer(optionId: i, index: peerIndex, peer: peer, optionText: optionTextHeader, optionAdditionalText: optionAdditionalTextHeader, optionCount: voterCount, optionExpanded: false, opaqueIdentifier: option.opaqueIdentifier, shimmeringAlternation: peerIndex % 2, isFirstInOption: peerIndex == 0)) } diff --git a/submodules/TranslateUI/Sources/TranslateScreen.swift b/submodules/TranslateUI/Sources/TranslateScreen.swift index 65a7dd83b9..d51fc4f99b 100644 --- a/submodules/TranslateUI/Sources/TranslateScreen.swift +++ b/submodules/TranslateUI/Sources/TranslateScreen.swift @@ -720,7 +720,9 @@ public class TranslateScreen: ViewController { statusBarHeight: 0.0, navigationHeight: navigationHeight, safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right), + inputHeight: layout.inputHeight ?? 0.0, metrics: layout.metrics, + deviceMetrics: layout.deviceMetrics, isVisible: self.currentIsVisible, theme: self.theme ?? self.presentationData.theme, strings: self.presentationData.strings, diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index 5f4b0af304..ed7626e528 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -41,7 +41,9 @@ public enum WallpaperBubbleType { public protocol WallpaperBubbleBackgroundNode: ASDisplayNode { var frame: CGRect { get set } - + + var implicitContentUpdate: Bool { get set } + func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) func update(rect: CGRect, within containerSize: CGSize, transition: CombinedTransition) func update(rect: CGRect, within containerSize: CGSize, animator: ControlledTransitionAnimator) @@ -292,6 +294,8 @@ private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOver final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode { final class BubbleBackgroundNodeImpl: ASDisplayNode, WallpaperBubbleBackgroundNode { + var implicitContentUpdate: Bool = true + private let bubbleType: WallpaperBubbleType private let contentNode: ASImageNode @@ -305,12 +309,14 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode override var frame: CGRect { didSet { if oldValue.size != self.bounds.size { - self.contentNode.frame = self.bounds - if let cleanWallpaperNode = self.cleanWallpaperNode { - cleanWallpaperNode.frame = self.bounds - } - if let gradientWallpaperNode = self.gradientWallpaperNode { - gradientWallpaperNode.frame = self.bounds + if self.implicitContentUpdate { + self.contentNode.frame = self.bounds + if let cleanWallpaperNode = self.cleanWallpaperNode { + cleanWallpaperNode.frame = self.bounds + } + if let gradientWallpaperNode = self.gradientWallpaperNode { + gradientWallpaperNode.frame = self.bounds + } } } } @@ -1204,6 +1210,8 @@ final class WallpaperBackgroundNodeMergedImpl: ASDisplayNode, WallpaperBackgroun } final class BubbleBackgroundNodeImpl: ASDisplayNode, WallpaperBubbleBackgroundNode { + var implicitContentUpdate = true + private let bubbleType: WallpaperBubbleType private let contentNode: ASImageNode