diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index c0386381a0..e2c860f831 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -13601,3 +13601,7 @@ Sorry for the inconvenience."; "Gift.View.Self.Title" = "Saved Gift"; "Gift.View.Self.Description" = "You can display this gift on your page or turn it into a unique collectible and send to others."; + +"BotVerification.ChooseChat" = "Choose Chat to Verify"; +"BotVerification.Added" = "**%@** has been notified and will receive your verification mark and description upon accepting."; +"BotVerification.Removed" = "You have removed **%@'s** verification."; diff --git a/submodules/AccountContext/Sources/PeerSelectionController.swift b/submodules/AccountContext/Sources/PeerSelectionController.swift index 8fb3a006aa..aef3c6d9ff 100644 --- a/submodules/AccountContext/Sources/PeerSelectionController.swift +++ b/submodules/AccountContext/Sources/PeerSelectionController.swift @@ -28,7 +28,6 @@ public struct ChatListNodePeersFilter: OptionSet { public static let removeSearchHeader = ChatListNodePeersFilter(rawValue: 1 << 9) public static let excludeDisabled = ChatListNodePeersFilter(rawValue: 1 << 10) - public static let includeSavedMessages = ChatListNodePeersFilter(rawValue: 1 << 11) public static let excludeChannels = ChatListNodePeersFilter(rawValue: 1 << 12) public static let onlyGroupsAndChannels = ChatListNodePeersFilter(rawValue: 1 << 13) @@ -36,6 +35,8 @@ public struct ChatListNodePeersFilter: OptionSet { public static let excludeGroups = ChatListNodePeersFilter(rawValue: 1 << 14) public static let excludeUsers = ChatListNodePeersFilter(rawValue: 1 << 15) public static let excludeBots = ChatListNodePeersFilter(rawValue: 1 << 16) + + public static let includeSelf = ChatListNodePeersFilter(rawValue: 1 << 7) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 1e6b12fa59..e0976a8e4a 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -439,7 +439,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { case topic(EnginePeer, ChatListItemContent.ThreadInfo, Int, PresentationTheme, PresentationStrings, ChatListSearchSectionExpandType) case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PeerStoryStats?, Bool) - case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool) + case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, Bool) case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, String?) case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, EngineMessageHistoryThread.Info?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool, PeerStoryStats?, Bool, TelegramSearchPeersScope) case messagePlaceholder(Int32, ChatListPresentationData, TelegramSearchPeersScope) @@ -452,7 +452,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { return .threadId(threadInfo.id) case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _, _, _): return .localPeerId(peer.id) - case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _): + case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _, _): return .localPeerId(peer.id) case let .globalPeer(peer, _, _, _, _, _, _, _, _, _, _): return .globalPeerId(peer.peer.id) @@ -481,8 +481,8 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { return false } - case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging): - if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { + case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging, lhsIsSelf): + if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging, rhsIsSelf) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging && lhsIsSelf == rhsIsSelf { return true } else { return false @@ -614,11 +614,11 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { return true } - case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _, _, _): + case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _, _, _, _): switch rhs { case .topic, .recentlySearchedPeer: return false - case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _, _): + case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _, _, _): return lhsIndex <= rhsIndex case .globalPeer, .message, .messagePlaceholder, .emptyMessagesFooter, .addContact: return true @@ -808,7 +808,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { openStories(peer.id, sourceNode.avatarNode) } }) - case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging): + case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging, isSelf): let primaryPeer: EnginePeer var chatPeer: EnginePeer? if let associatedPeer = associatedPeer { @@ -916,7 +916,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { ) } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), buttonAction: buttonAction, index: nil, header: header, action: { contactPeer in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), aliasHandling: isSelf ? .standard : .treatSelfAsSaved, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), buttonAction: buttonAction, index: nil, header: header, action: { contactPeer in if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer { interaction.peerSelected(chatPeer, peer, nil, nil, false) } else { @@ -2783,7 +2783,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } return false } else { - guard !peersFilter.contains(.excludeSavedMessages) || peer.id != accountPeer.id else { return false } + guard !peersFilter.contains(.excludeSavedMessages) || peersFilter.contains(.includeSelf) || peer.id != accountPeer.id else { return false } guard !peersFilter.contains(.excludeSecretChats) || peer.id.namespace != Namespaces.Peer.SecretChat else { return false } guard !peersFilter.contains(.onlyPrivateChats) || peer.id.namespace == Namespaces.Peer.CloudUser else { return false } @@ -2821,7 +2821,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { var totalNumberOfLocalPeers = 0 for renderedPeer in foundLocalPeers.peers { - if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != context.account.peerId, filteredPeer(peer, EnginePeer(accountPeer)) { + if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != context.account.peerId || peersFilter.contains(.includeSelf), filteredPeer(peer, EnginePeer(accountPeer)) { if !existingPeerIds.contains(peer.id) { existingPeerIds.insert(peer.id) totalNumberOfLocalPeers += 1 @@ -2856,11 +2856,22 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if lowercasedQuery.count > 1 && (presentationData.strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery)) { if !existingPeerIds.contains(accountPeer.id), filteredPeer(EnginePeer(accountPeer), EnginePeer(accountPeer)) { existingPeerIds.insert(accountPeer.id) - entries.append(.localPeer(EnginePeer(accountPeer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) + entries.append(.localPeer(EnginePeer(accountPeer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false, false)) index += 1 } } + if peersFilter.contains(.includeSelf) { + for renderedPeer in foundLocalPeers.peers { + if renderedPeer.peerId == context.account.peerId, let peer = renderedPeer.peers[renderedPeer.peerId], filteredPeer(peer, EnginePeer(accountPeer)) { + if !existingPeerIds.contains(peer.id) { + entries.append(.localPeer(peer, nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false, true)) + } + break + } + } + } + for renderedPeer in foundLocalPeers.peers { if !foundLocalPeers.recentlySearchedPeerIds.contains(renderedPeer.peerId) { continue @@ -2899,7 +2910,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if matches { existingPeerIds.insert(peer.id) - entries.append(.localPeer(peer, nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) + entries.append(.localPeer(peer, nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false, false)) } } } @@ -2922,7 +2933,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { associatedPeer = renderedPeer.peers[associatedPeerId] } - entries.append(.localPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) + entries.append(.localPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false, false)) index += 1 numberOfLocalPeers += 1 } @@ -2936,7 +2947,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if !existingPeerIds.contains(peer.peer.id), filteredPeer(EnginePeer(peer.peer), EnginePeer(accountPeer)) { existingPeerIds.insert(peer.peer.id) - entries.append(.localPeer(EnginePeer(peer.peer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) + entries.append(.localPeer(EnginePeer(peer.peer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false, false)) index += 1 numberOfLocalPeers += 1 } @@ -3362,7 +3373,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if case let .user(user) = peer, user.flags.contains(.requirePremium) { requiresPremiumForMessagingPeerIds.append(peer.id) } - case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _): + case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _, _): storyStatsIds.append(peer.id) if case let .user(user) = peer, user.flags.contains(.requirePremium) { requiresPremiumForMessagingPeerIds.append(peer.id) @@ -3406,8 +3417,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { switch mappedItems[i] { case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, _, _): mappedItems[i] = .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false) - case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _): - mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false) + case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, isSelf): + mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false, isSelf) case let .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, searchQuery): mappedItems[i] = .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.peer.id] ?? nil, requiresPremiumForMessaging[peer.peer.id] ?? false, searchQuery) case let .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, _, _, searchScope): @@ -3441,7 +3452,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if let entries = entriesAndFlags { var filteredEntries: [ChatListSearchEntry] = [] for entry in entries { - if case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _) = entry { + if case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _, _) = entry { peers.append(peer) } else if case .globalPeer = entry { } else { diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 953fc62c63..42b2ea76bc 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -3105,7 +3105,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { if peer.isVerified { currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) - } else if let verificationIconFileId = peer.verificationIconFileId { + } + if let verificationIconFileId = peer.verificationIconFileId { currentVerifiedIconContent = .animation(content: .customEmoji(fileId: verificationIconFileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(0)) } } @@ -3132,7 +3133,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { if peer.isVerified { currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) - } else if let verificationIconFileId = peer.verificationIconFileId { + } + if let verificationIconFileId = peer.verificationIconFileId { currentVerifiedIconContent = .animation(content: .customEmoji(fileId: verificationIconFileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(0)) } } diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift index d385ecd5ff..e67e462239 100644 --- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift +++ b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift @@ -73,6 +73,11 @@ public enum ContactsPeerItemPeerMode: Equatable { case app(isPopular: Bool) } +public enum ContactsPeerItemAliasHandling { + case standard + case treatSelfAsSaved +} + public enum ContactsPeerItemBadgeType { case active case inactive @@ -176,6 +181,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { let displayOrder: PresentationPersonNameOrder let context: AccountContext let peerMode: ContactsPeerItemPeerMode + let aliasHandling: ContactsPeerItemAliasHandling public let peer: ContactsPeerItemPeer let status: ContactsPeerItemStatus let badge: ContactsPeerItemBadge? @@ -217,6 +223,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { displayOrder: PresentationPersonNameOrder, context: AccountContext, peerMode: ContactsPeerItemPeerMode, + aliasHandling: ContactsPeerItemAliasHandling = .treatSelfAsSaved, peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, @@ -252,6 +259,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { self.displayOrder = displayOrder self.context = context self.peerMode = peerMode + self.aliasHandling = aliasHandling self.peer = peer self.status = status self.badge = badge @@ -786,7 +794,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { var verifiedIcon: EmojiStatusComponent.Content? switch item.peer { case let .peer(peer, _): - if let peer = peer, (peer.id != item.context.account.peerId || item.peerMode == .memberList) { + if let peer = peer, (peer.id != item.context.account.peerId || item.peerMode == .memberList || item.aliasHandling == .treatSelfAsSaved) { if peer.isScam { credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased()) } else if peer.isFake { @@ -798,8 +806,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { } if peer.isVerified { - verifiedIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) - } else if let verificationIconFileId = peer.verificationIconFileId { + credibilityIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) + } + if let verificationIconFileId = peer.verificationIconFileId { verifiedIcon = .animation(content: .customEmoji(fileId: verificationIconFileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(0)) } } @@ -865,7 +874,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { textColor = item.presentationData.theme.list.itemPrimaryTextColor } if case let .user(user) = peer { - if peer.id == item.context.account.peerId, case let .generalSearch(isSavedMessages) = item.peerMode { + if peer.id == item.context.account.peerId, case let .generalSearch(isSavedMessages) = item.peerMode, case .treatSelfAsSaved = item.aliasHandling { if isSavedMessages { titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_MyNotes, font: titleBoldFont, textColor: textColor) } else { @@ -1171,7 +1180,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { case let .peer(peer, _): if let peer = peer { var overrideImage: AvatarNodeImageOverride? - if peer.id == item.context.account.peerId, case let .generalSearch(isSavedMessages) = item.peerMode { + if peer.id == item.context.account.peerId, case let .generalSearch(isSavedMessages) = item.peerMode, case .treatSelfAsSaved = item.aliasHandling { if isSavedMessages { overrideImage = .myNotesIcon } else { @@ -1433,6 +1442,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { if case .animation = verifiedIcon { titleLeftOffset += iconSize.width + 4.0 + nextIconX += iconSize.width } else { nextIconX += iconSize.width } diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index 3882bae635..2ad809fcf2 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -937,8 +937,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo } if item.peer.isVerified { - verifiedIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) - } else if let verificationIconFileId = item.peer.verificationIconFileId { + credibilityIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) + } + if let verificationIconFileId = item.peer.verificationIconFileId { verifiedIcon = .animation(content: .customEmoji(fileId: verificationIconFileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(0)) } } diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 2ed150b46c..89b8cc514b 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -1115,6 +1115,7 @@ private final class GiftViewSheetContent: CombinedComponent { text: .plain(value), horizontalAlignment: .center, maximumNumberOfLines: 0, + insets: id == "originalInfo" ? UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0) : .zero, handleSpoilers: true ) ) @@ -1306,6 +1307,7 @@ private final class GiftViewSheetContent: CombinedComponent { placeholderColor: theme.list.mediaPlaceholderColor, text: .plain(attributedText), maximumNumberOfLines: 0, + insets: UIEdgeInsets(top: 1.0, left: 0.0, bottom: 1.0, right: 0.0), handleSpoilers: true ) ) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift index aa3cc094e2..2e3988ed49 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift @@ -521,7 +521,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.presentationData = presentationData let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 }) - let credibilityIcon: CredibilityIcon + var credibilityIcon: CredibilityIcon var verifiedIcon: CredibilityIcon = .none if let peer = peer { if peer.id == self.context.account.peerId && !self.isSettings && !self.isMyProfile { @@ -538,8 +538,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { credibilityIcon = .none } if peer.isVerified { - verifiedIcon = .verified - } else if let verificationIconFileId = peer.verificationIconFileId { + credibilityIcon = .verified + } + if let verificationIconFileId = peer.verificationIconFileId { verifiedIcon = .emojiStatus(PeerEmojiStatus(fileId: verificationIconFileId, expirationDate: nil)) } } else { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 51d7b0bbf1..b8ce73a7cd 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -8818,9 +8818,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro let controller = self.context.sharedContext.makePeerSelectionController( PeerSelectionControllerParams( context: self.context, - filter: [.excludeSecretChats, .excludeRecent, .excludeSavedMessages], + filter: [.excludeSecretChats, .excludeRecent, .excludeSavedMessages, .includeSelf, .doNotSearchMessages], hasContactSelector: false, - title: "Choose Chat to Verify" + title: self.presentationData.strings.BotVerification_ChooseChat ) ) controller.peerSelected = { [weak self, weak controller] peer, _ in @@ -8849,7 +8849,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } let undoController = UndoOverlayController( presentationData: self.presentationData, - content: .invitedToVoiceChat(context: self.context, peer: peer, title: nil, text: "You have removed **\(peer.compactDisplayTitle)'s** verification.", action: nil, duration: 5.0), + content: .invitedToVoiceChat(context: self.context, peer: peer, title: nil, text: self.presentationData.strings.BotVerification_Removed(peer.compactDisplayTitle).string, action: nil, duration: 5.0), elevatedLayout: false, action: { _ in return true } ) @@ -8878,7 +8878,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } let undoController = UndoOverlayController( presentationData: self.presentationData, - content: .invitedToVoiceChat(context: self.context, peer: peer, title: nil, text: "**\(peer.compactDisplayTitle)** has been notified and will receive your verification mark and description upon accepting.", action: nil, duration: 5.0), + content: .invitedToVoiceChat(context: self.context, peer: peer, title: nil, text: self.presentationData.strings.BotVerification_Added(peer.compactDisplayTitle).string, action: nil, duration: 5.0), elevatedLayout: false, action: { _ in return true } ) diff --git a/submodules/TelegramUI/Resources/Animations/GiftUpgrade.json b/submodules/TelegramUI/Resources/Animations/GiftUpgrade.json new file mode 100644 index 0000000000..2df158c31f --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/GiftUpgrade.json @@ -0,0 +1 @@ +{"v":"5.12.1","fr":60,"ip":0,"op":91,"w":90,"h":90,"nm":"upgrade","ddd":0,"assets":[{"id":"comp_0","nm":"arrows","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 203","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":45,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.34],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[32.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.66],"y":[0]},"t":20,"s":[27.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[34.25]},{"t":40,"s":[32.25]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[4,1.75],[0,-1.75],[-4,1.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 203","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector 202","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":45,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.34],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[44.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.66],"y":[0]},"t":15,"s":[39.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":25,"s":[46.25]},{"t":35,"s":[44.25]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[4,1.75],[0,-1.75],[-4,1.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 202","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector 201","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":45,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.34],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[56.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.66],"y":[0]},"t":10,"s":[51.25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[58.25]},{"t":30,"s":[56.25]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[4,1.75],[0,-1.75],[-4,1.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 201","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrows","td":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[45,45,0],"ix":2,"l":2},"a":{"a":0,"k":[45,45,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":90,"h":90,"ip":0,"op":1800,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 329","tt":2,"tp":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":45,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[45]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[40.5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[47.5]},{"t":40,"s":[45]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[20,20]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":20,"s":[19,22]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":30,"s":[21,19]},{"t":40,"s":[20,20]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":10,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 329","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1800,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift index 0951822b75..5ff4f37513 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift @@ -554,7 +554,7 @@ func moveReplyMessageToAnotherChat(selfController: ChatControllerImpl, replySubj guard let selfController else { return } - let filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages] + let filter: ChatListNodePeersFilter = [.onlyWriteable, .excludeDisabled, .doNotSearchMessages] var attemptSelectionImpl: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? let controller = selfController.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams( context: selfController.context, diff --git a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift index 42fb76fdd3..401c692bec 100644 --- a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift +++ b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift @@ -29,7 +29,7 @@ extension ChatControllerImpl { func forwardMessages(messages: [Message], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool) { let _ = self.presentVoiceMessageDiscardAlert(action: { - var filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages] + var filter: ChatListNodePeersFilter = [.onlyWriteable, .excludeDisabled, .doNotSearchMessages] var hasPublicPolls = false var hasPublicQuiz = false for message in messages {