From 3cad999c75f3b4bb5789a817402f4ece41c1b48c Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Tue, 27 May 2025 18:41:24 +0800 Subject: [PATCH] Fix monoforum user unread counters --- .../Telegram-iOS/en.lproj/Localizable.strings | 14 + .../ChatListUI/Sources/ChatContextMenus.swift | 6 +- .../Sources/Node/ChatListItem.swift | 3 +- .../Postbox/Sources/ChatListIndexTable.swift | 41 +- submodules/Postbox/Sources/ChatListView.swift | 6 +- .../Postbox/Sources/ChatListViewState.swift | 16 +- submodules/Postbox/Sources/Postbox.swift | 1 - .../Postbox/Sources/SeedConfiguration.swift | 4 +- .../Sources/UnreadMessageCountsView.swift | 14 +- ...yncCore_StandaloneAccountTransaction.swift | 8 +- .../Sources/ServiceMessageStrings.swift | 3 +- .../Sources/AsyncListComponent.swift | 33 +- .../ChatChannelSubscriberInputPanelNode.swift | 5 +- .../Sources/ChatMessageBubbleItemNode.swift | 33 +- .../ChatMessageSuggestedPostInfoNode.swift | 169 ---- .../Sources/ChatMessageNotificationItem.swift | 3 +- .../Sources/ChatSideTopicsPanel.swift | 12 +- .../Sources/PeerInfoScreen.swift | 6 +- .../Chat/ChatControllerLoadDisplayNode.swift | 2 - .../Sources/ChatControllerContentData.swift | 1 - ...ChatTopicListTitleAccessoryPanelNode.swift | 721 ------------------ 21 files changed, 117 insertions(+), 984 deletions(-) delete mode 100644 submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageSuggestedPostInfoNode.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 07f4df206b..5253cd97f6 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -14382,3 +14382,17 @@ Sorry for the inconvenience."; "ChannelMessages.SwitchTitle" = "Allow Channel Messages"; "ChannelMessages.PriceSectionTitle" = "PRICE FOR EACH MESSAGE"; "ChannelMessages.PriceSectionFooter" = "Charge users for the ability to suggest one post for your channel. You're not required to publish any suggestions by charging this. You'll receive 85% of the selected fee for each incoming suggestion."; + +"ChatList.MonoforumLabel" = "MESSAGES"; +"ChatList.MonoforumEmptyText" = "No messages here yet..."; + +"Chat.InlineTopicMenu.Reorder" = "Reorder"; +"Chat.InlineTopicMenu.Edit" = "Edit"; +"Chat.InlineTopicMenu.AllTab" = "All"; +"Chat.ChannelMessagesHint" = "Tap here to send a message"; +"Chat.ChannelMessagesHintBadge" = "NEW"; + +"PeerInfo.AllowChannelMessages" = "Allow Channel Messages"; +"PeerInfo.AllowChannelMessages.On" = "On"; +"PeerInfo.AllowChannelMessages.Off" = "Off"; +"PeerInfo.ChannelMessages" = "Channel Messages"; diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index e9a3e09383..e909cc633c 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -632,8 +632,7 @@ public func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, thr }))) if isPinned, let reorder { - //TODO:localize - items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { c, _ in + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_InlineTopicMenu_Reorder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) }, action: { c, _ in c?.dismiss(completion: { }) reorder() @@ -664,8 +663,7 @@ public func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, thr } if threadId != 1, canOpenClose, let customEdit { - //TODO:localize - items.append(.action(ContextMenuActionItem(text: "Edit", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor) }, action: { c, f in + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_InlineTopicMenu_Edit, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor) }, action: { c, f in if let c = c as? ContextController { customEdit(c) } else { diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 38a13358b1..cad55bfac3 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -3014,8 +3014,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { textColor = theme.titleColor } if case let .channel(channel) = itemPeer.peer, channel.flags.contains(.isMonoforum) { - //TODO:localize - titleBadgeText = "MESSAGES" + titleBadgeText = item.presentationData.strings.ChatList_MonoforumLabel } titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: textColor) } diff --git a/submodules/Postbox/Sources/ChatListIndexTable.swift b/submodules/Postbox/Sources/ChatListIndexTable.swift index e672c4ced4..63c4179381 100644 --- a/submodules/Postbox/Sources/ChatListIndexTable.swift +++ b/submodules/Postbox/Sources/ChatListIndexTable.swift @@ -185,7 +185,31 @@ final class ChatListIndexTable: Table { var updatedPeerTags: [PeerId: (previous: PeerSummaryCounterTags, updated: PeerSummaryCounterTags)] = [:] var updatedIsThreadBasedUnreadCountCalculation: [PeerId: Bool] = [:] + var upatedPeerMap: [PeerId: (Peer?, Peer)] = [:] + for (previous, updated) in updatedPeers { + var needsAssociatedPeers = false + if let previous, previous.0.associatedPeerId != nil { + needsAssociatedPeers = true + } else if updated.0.associatedPeerId != nil { + needsAssociatedPeers = true + } + + if needsAssociatedPeers && upatedPeerMap.isEmpty { + for (previous, updated) in updatedPeers { + upatedPeerMap[updated.0.id] = (previous?.0, updated.0) + } + } + + var previousAssociatedPeer: Peer? + var updatedAssociatedPeer: Peer? + if let previous, let previousAssociatedPeerId = previous.0.associatedPeerId { + previousAssociatedPeer = upatedPeerMap[previousAssociatedPeerId]?.0 ?? postbox.peerTable.get(previousAssociatedPeerId) + } + if let updatedAssociatedPeerId = updated.0.associatedPeerId { + updatedAssociatedPeer = upatedPeerMap[updatedAssociatedPeerId]?.1 ?? postbox.peerTable.get(updatedAssociatedPeerId) + } + let previousTags: PeerSummaryCounterTags if let (previous, previousIsContact) = previous { previousTags = postbox.seedConfiguration.peerSummaryCounterTags(previous, previousIsContact) @@ -198,13 +222,13 @@ final class ChatListIndexTable: Table { } if let previous = previous { - var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(updated.0).value + var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(updated.0, updatedAssociatedPeer).value if let cachedData = updatedCachedPeerData[updated.0.id]?.1, postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) { isThreadBasedUnreadCalculation = false } var wasThreadBasedUnreadCalculation = false - if postbox.seedConfiguration.peerSummaryIsThreadBased(previous.0).value { + if postbox.seedConfiguration.peerSummaryIsThreadBased(previous.0, previousAssociatedPeer).value { if let cachedData = postbox.cachedPeerDataTable.get(previous.0.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) { } else { wasThreadBasedUnreadCalculation = true @@ -223,14 +247,15 @@ final class ChatListIndexTable: Table { guard let peer = postbox.peerTable.get(peerId) else { continue } + let associatedPeer = peer.associatedPeerId.flatMap(postbox.peerTable.get) - var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + var isThreadBasedUnreadCalculation = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, associatedPeer).value if postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedDataUpdate.1) { isThreadBasedUnreadCalculation = false } var wasThreadBasedUnreadCalculation = false - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if postbox.seedConfiguration.peerSummaryIsThreadBased(peer, associatedPeer).value { if let previousCachedData = cachedDataUpdate.0, postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(previousCachedData) { } else { wasThreadBasedUnreadCalculation = true @@ -439,7 +464,7 @@ final class ChatListIndexTable: Table { displayAsRegularChat = true } - if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat { + if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value, !displayAsRegularChat { let previousCount: Int32 if let previousSummary = alteredInitialPeerThreadsSummaries[peerId] { previousCount = previousSummary.effectiveUnreadCount @@ -458,7 +483,7 @@ final class ChatListIndexTable: Table { } let currentReadState: CombinedPeerReadState? - if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat { + if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value, !displayAsRegularChat { let count = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0 currentReadState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))]) } else { @@ -691,7 +716,7 @@ final class ChatListIndexTable: Table { } let combinedState: CombinedPeerReadState? - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0 combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))]) } else { @@ -788,7 +813,7 @@ final class ChatListIndexTable: Table { } let combinedState: CombinedPeerReadState? - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { let count: Int32 = postbox.peerThreadsSummaryTable.get(peerId: peerId)?.effectiveUnreadCount ?? 0 combinedState = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 1, maxKnownId: 0, count: count, markedUnread: false))]) } else { diff --git a/submodules/Postbox/Sources/ChatListView.swift b/submodules/Postbox/Sources/ChatListView.swift index c25f25fa95..2a3d47aca1 100644 --- a/submodules/Postbox/Sources/ChatListView.swift +++ b/submodules/Postbox/Sources/ChatListView.swift @@ -714,7 +714,7 @@ final class MutableChatListView { let renderedPeer = RenderedPeer(peerId: peer.id, peers: peers, associatedMedia: renderAssociatedMediaForPeers(postbox: postbox, peers: peers)) let isUnread: Bool - if postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { let hasUnmutedUnread = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.hasUnmutedUnread ?? false isUnread = hasUnmutedUnread } else { @@ -846,7 +846,7 @@ final class MutableChatListView { displayAsRegularChat = postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedData) } - if let peer = groupEntries[i].renderedPeers[j].peer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value, !displayAsRegularChat { + if let peer = groupEntries[i].renderedPeers[j].peer.peer, postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value, !displayAsRegularChat { isUnread = postbox.peerThreadsSummaryTable.get(peerId: peer.id)?.hasUnmutedUnread ?? false } else { isUnread = postbox.readStateTable.getCombinedState(groupEntries[i].renderedPeers[j].peer.peerId)?.isUnread ?? false @@ -942,7 +942,7 @@ final class MutableChatListView { var isThreadBased = false var threadsArePeers = false if let peer = renderedPeer.peer { - let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer) + let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)) isThreadBased = value.value threadsArePeers = value.threadsArePeers } diff --git a/submodules/Postbox/Sources/ChatListViewState.swift b/submodules/Postbox/Sources/ChatListViewState.swift index 29dc942b51..dd1b39962a 100644 --- a/submodules/Postbox/Sources/ChatListViewState.swift +++ b/submodules/Postbox/Sources/ChatListViewState.swift @@ -65,7 +65,7 @@ private func mappedChatListFilterPredicate(postbox: PostboxImpl, currentTransact if let cachedPeerData = postbox.cachedPeerDataTable.get(peer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -439,7 +439,7 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(peer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -577,7 +577,7 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(entryPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer, entryPeer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -630,7 +630,7 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(mainPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer, mainPeer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -816,7 +816,7 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(entryPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(entryPeer, entryPeer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -878,7 +878,7 @@ private final class ChatListViewSpaceState { if let cachedPeerData = postbox.cachedPeerDataTable.get(mainPeer.id), postbox.seedConfiguration.decodeDisplayPeerAsRegularChat(cachedPeerData) { displayAsRegularChat = true } - let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer).value + let isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(mainPeer, mainPeer.associatedPeerId.flatMap(postbox.peerTable.get)).value if !isThreadBased { displayAsRegularChat = true } @@ -978,7 +978,7 @@ private final class ChatListViewSpaceState { } let isThreadBased: Bool if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId) { - isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value + isThreadBased = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value } else { isThreadBased = false } @@ -1620,7 +1620,7 @@ struct ChatListViewState { var isThreadBased = false var threadsArePeers = false if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) { - let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer) + let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)) isThreadBased = value.value threadsArePeers = value.threadsArePeers } diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 893f784fec..c887e02cd2 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -3187,7 +3187,6 @@ final class PostboxImpl { let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal(userInteractive: true, { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: false) - //TODO:release jump to unread var anchor: HistoryViewInputAnchor = .upperBound switch peerIds { case let .single(peerId, threadId): diff --git a/submodules/Postbox/Sources/SeedConfiguration.swift b/submodules/Postbox/Sources/SeedConfiguration.swift index 260ee2b2c2..859186b969 100644 --- a/submodules/Postbox/Sources/SeedConfiguration.swift +++ b/submodules/Postbox/Sources/SeedConfiguration.swift @@ -66,7 +66,7 @@ public final class SeedConfiguration { public let existingGlobalMessageTags: GlobalMessageTags public let peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace] public let peerSummaryCounterTags: (Peer, Bool) -> PeerSummaryCounterTags - public let peerSummaryIsThreadBased: (Peer) -> (value: Bool, threadsArePeers: Bool) + public let peerSummaryIsThreadBased: (Peer, Peer?) -> (value: Bool, threadsArePeers: Bool) public let additionalChatListIndexNamespace: MessageId.Namespace? public let messageNamespacesRequiringGroupStatsValidation: Set public let defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState] @@ -97,7 +97,7 @@ public final class SeedConfiguration { existingGlobalMessageTags: GlobalMessageTags, peerNamespacesRequiringMessageTextIndex: [PeerId.Namespace], peerSummaryCounterTags: @escaping (Peer, Bool) -> PeerSummaryCounterTags, - peerSummaryIsThreadBased: @escaping (Peer) -> (value: Bool, threadsArePeers: Bool), + peerSummaryIsThreadBased: @escaping (Peer, Peer?) -> (value: Bool, threadsArePeers: Bool), additionalChatListIndexNamespace: MessageId.Namespace?, messageNamespacesRequiringGroupStatsValidation: Set, defaultMessageNamespaceReadStates: [MessageId.Namespace: PeerReadState], diff --git a/submodules/Postbox/Sources/UnreadMessageCountsView.swift b/submodules/Postbox/Sources/UnreadMessageCountsView.swift index 988f23b9b4..32c134ad71 100644 --- a/submodules/Postbox/Sources/UnreadMessageCountsView.swift +++ b/submodules/Postbox/Sources/UnreadMessageCountsView.swift @@ -64,7 +64,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { case let .totalInGroup(groupId): return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId)) case let .peer(peerId, handleThreads): - if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { var count: Int32 = 0 if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { count = summary.totalUnreadCount @@ -113,7 +113,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { } } case let .peer(peerId, handleThreads, _): - if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { if transaction.updatedPeerThreadsSummaries.contains(peerId) { var count: Int32 = 0 if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { @@ -143,7 +143,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { case let .totalInGroup(groupId): return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId)) case let .peer(peerId, handleThreads): - if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { var count: Int32 = 0 if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { count = summary.totalUnreadCount @@ -240,7 +240,7 @@ final class MutableCombinedReadStateView: MutablePostboxView { var updated = false if transaction.alteredInitialPeerCombinedReadStates[self.peerId] != nil || transaction.updatedPeerThreadCombinedStates.contains(self.peerId) { - if self.handleThreads, let peer = postbox.peerTable.get(self.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if self.handleThreads, let peer = postbox.peerTable.get(self.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { var count: Int32 = 0 if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { count = summary.totalUnreadCount @@ -260,14 +260,14 @@ final class MutableCombinedReadStateView: MutablePostboxView { func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool { let state: CombinedPeerReadState? - if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer).value { + if self.handleThreads, let peer = postbox.peerTable.get(self.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)).value { var count: Int32 = 0 - if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { + if let summary = postbox.peerThreadsSummaryTable.get(peerId: self.peerId) { count = summary.totalUnreadCount } state = CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]) } else { - state = postbox.readStateTable.getCombinedState(peerId) + state = postbox.readStateTable.getCombinedState(self.peerId) } if state != self.state { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift index b0accb28cf..6879891c8d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift @@ -73,7 +73,7 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = { return .nonContact } }, - peerSummaryIsThreadBased: { peer in + peerSummaryIsThreadBased: { peer, associatedPeer in if let channel = peer as? TelegramChannel { if channel.flags.contains(.isForum) { if channel.flags.contains(.displayForumAsTabs) { @@ -82,7 +82,11 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = { return (true, false) } } else if channel.flags.contains(.isMonoforum) { - return (true, true) + if let associatedPeer = associatedPeer as? TelegramChannel, associatedPeer.hasPermission(.sendSomething) { + return (true, true) + } else { + return (false, false) + } } else { return (false, false) } diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index bc58b58870..17874db695 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -140,8 +140,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } else { if forChatList { if isMonoforum { - //TODO:Localize - attributedString = NSAttributedString(string: "No messages here yet...", font: titleFont, textColor: primaryTextColor) + attributedString = NSAttributedString(string: strings.ChatList_MonoforumEmptyText, font: titleFont, textColor: primaryTextColor) } else { attributedString = NSAttributedString(string: strings.Notification_CreatedGroup, font: titleFont, textColor: primaryTextColor) } diff --git a/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift b/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift index ac981ff621..84052836fa 100644 --- a/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift +++ b/submodules/TelegramUI/Components/AsyncListComponent/Sources/AsyncListComponent.swift @@ -526,14 +526,29 @@ public final class AsyncListComponent: Component { var scrollToItem: ListViewScrollToItem? if let resetScrollingRequest = component.externalStateValue.resetScrollingRequest, previousComponent?.externalStateValue.resetScrollingRequest != component.externalStateValue.resetScrollingRequest { - //TODO:release calculate direction hint if let index = entries.firstIndex(where: { $0.id == resetScrollingRequest.id }) { + var directionHint: ListViewScrollToItemDirectionHint = .Down + var didSelectDirection = false + self.listNode.forEachItemNode { itemNode in + if didSelectDirection { + return + } + if let itemNode = itemNode as? ListItemNodeImpl, let itemIndex = itemNode.index { + if itemIndex <= index { + directionHint = .Up + } else { + directionHint = .Down + } + didSelectDirection = true + } + } + scrollToItem = ListViewScrollToItem( index: index, position: .visible, animated: animateTransition, curve: updateSizeAndInsets.curve, - directionHint: .Down + directionHint: directionHint ) } } @@ -548,13 +563,25 @@ public final class AsyncListComponent: Component { transactionOptions.insert(.Synchronous) + self.listNode.transaction( + deleteIndices: [], + insertIndicesAndItems: [], + updateIndicesAndItems: [], + options: transactionOptions, + scrollToItem: nil, + updateSizeAndInsets: updateSizeAndInsets, + stationaryItemRange: nil, + updateOpaqueState: nil, + completion: { _ in } + ) + self.listNode.transaction( deleteIndices: deletions, insertIndicesAndItems: insertions, updateIndicesAndItems: updates, options: transactionOptions, scrollToItem: scrollToItem, - updateSizeAndInsets: updateSizeAndInsets, + updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in } diff --git a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift index 65d6f1858e..42f1553f17 100644 --- a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift @@ -381,14 +381,13 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let _ = presentationData - //TODO:localize - let text: String = "Tap here to send a message" + let text: String = presentationData.strings.Chat_ChannelMessagesHint let tooltipController = TooltipScreen( account: context.account, sharedContext: context.sharedContext, text: .plain(text: text), - textBadge: "NEW", + textBadge: presentationData.strings.Chat_ChannelMessagesHintBadge, balancedTextLayout: false, style: .wide, arrowStyle: .small, diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index 163be10337..d75245bf29 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -619,8 +619,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI private let shadowNode: ChatMessageShadowNode private var clippingNode: ChatMessageBubbleClippingNode - private var suggestedPostInfoNode: ChatMessageSuggestedPostInfoNode? - override public var extractedBackgroundNode: ASDisplayNode? { return self.shadowNode } @@ -1427,8 +1425,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI let weakSelf = Weak(self) - let makeSuggestedPostInfoNodeLayout: ChatMessageSuggestedPostInfoNode.AsyncLayout = ChatMessageSuggestedPostInfoNode.asyncLayout(self.suggestedPostInfoNode) - return { item, params, mergedTop, mergedBottom, dateHeaderAtBottom in let layoutConstants = chatMessageItemLayoutConstants(layoutConstants, params: params, presentationData: item.presentationData) return ChatMessageBubbleItemNode.beginLayout( @@ -1451,7 +1447,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI unlockButtonLayout: unlockButtonLayout, mediaInfoLayout: mediaInfoLayout, mosaicStatusLayout: mosaicStatusLayout, - makeSuggestedPostInfoNodeLayout: makeSuggestedPostInfoNodeLayout, layoutConstants: layoutConstants, currentItem: currentItem, currentForwardInfo: currentForwardInfo, @@ -1480,7 +1475,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI unlockButtonLayout: (ChatMessageUnlockMediaNode.Arguments) -> (CGSize, (Bool) -> ChatMessageUnlockMediaNode), mediaInfoLayout: (ChatMessageStarsMediaInfoNode.Arguments) -> (CGSize, (Bool) -> ChatMessageStarsMediaInfoNode), mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)), - makeSuggestedPostInfoNodeLayout: ChatMessageSuggestedPostInfoNode.AsyncLayout, layoutConstants: ChatMessageItemLayoutConstants, currentItem: ChatMessageItem?, currentForwardInfo: (Peer?, String?)?, @@ -3000,7 +2994,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI var totalContentNodesHeight: CGFloat = 0.0 var currentContainerGroupOverlap: CGFloat = 0.0 var detachedContentNodesHeight: CGFloat = 0.0 - var additionalTopHeight: CGFloat = 0.0 + let additionalTopHeight: CGFloat = 0.0 var mosaicStatusOrigin: CGPoint? var unlockButtonPosition: CGPoint? @@ -3176,13 +3170,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI } reactionButtonsSizeAndApply = reactionButtonsFinalize(maxContentWidth) } - - var suggestedPostInfoNodeLayout: (CGSize, () -> ChatMessageSuggestedPostInfoNode)? - suggestedPostInfoNodeLayout = nil - - if let suggestedPostInfoNodeLayout { - additionalTopHeight += 4.0 + suggestedPostInfoNodeLayout.0.height + 8.0 - } let minimalContentSize: CGSize if hideBackground { @@ -3320,7 +3307,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI avatarOffset: avatarOffset, hidesHeaders: hidesHeaders, disablesComments: disablesComments, - suggestedPostInfoNodeLayout: suggestedPostInfoNodeLayout, alignment: alignment, isSidePanelOpen: isSidePanelOpen ) @@ -3384,7 +3370,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI avatarOffset: CGFloat?, hidesHeaders: Bool, disablesComments: Bool, - suggestedPostInfoNodeLayout: (CGSize, () -> ChatMessageSuggestedPostInfoNode)?, alignment: ChatMessageBubbleContentAlignment, isSidePanelOpen: Bool ) -> Void { @@ -3468,22 +3453,6 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI strongSelf.backgroundNode.backgroundFrame = backgroundFrame - if let (suggestedPostInfoSize, suggestedPostInfoApply) = suggestedPostInfoNodeLayout { - let suggestedPostInfoNode = suggestedPostInfoApply() - if suggestedPostInfoNode !== strongSelf.suggestedPostInfoNode { - strongSelf.suggestedPostInfoNode?.removeFromSupernode() - strongSelf.suggestedPostInfoNode = suggestedPostInfoNode - strongSelf.mainContextSourceNode.contentNode.addSubnode(suggestedPostInfoNode) - - let suggestedPostInfoFrame = CGRect(origin: CGPoint(x: floor((params.width - suggestedPostInfoSize.width) * 0.5), y: 4.0), size: suggestedPostInfoSize) - suggestedPostInfoNode.frame = suggestedPostInfoFrame - //animation.animator.updateFrame(layer: suggestedPostInfoNode.layer, frame: suggestedPostInfoFrame, completion: nil) - } - } else if let suggestedPostInfoNode = strongSelf.suggestedPostInfoNode { - strongSelf.suggestedPostInfoNode = nil - suggestedPostInfoNode.removeFromSupernode() - } - if let avatarOffset { strongSelf.updateAttachedAvatarNodeOffset(offset: avatarOffset, transition: .animated(duration: 0.3, curve: .spring)) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageSuggestedPostInfoNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageSuggestedPostInfoNode.swift deleted file mode 100644 index 210e0770b6..0000000000 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageSuggestedPostInfoNode.swift +++ /dev/null @@ -1,169 +0,0 @@ -import Foundation -import UIKit -import AsyncDisplayKit -import Display -import SwiftSignalKit -import Postbox -import TelegramCore -import TelegramPresentationData -import TelegramUIPreferences -import TextFormat -import AccountContext -import WallpaperBackgroundNode -import ChatMessageItem -import TelegramStringFormatting - -public final class ChatMessageSuggestedPostInfoNode: ASDisplayNode { - private var titleNode: TextNode? - private var priceLabelNode: TextNode? - private var priceValueNode: TextNode? - private var timeLabelNode: TextNode? - private var timeValueNode: TextNode? - - private var backgroundNode: WallpaperBubbleBackgroundNode? - - override public init() { - super.init() - } - - public typealias AsyncLayout = (ChatMessageItem, CGFloat) -> (CGSize, () -> ChatMessageSuggestedPostInfoNode) - - public static func asyncLayout(_ node: ChatMessageSuggestedPostInfoNode?) -> (ChatMessageItem, CGFloat) -> (CGSize, () -> ChatMessageSuggestedPostInfoNode) { - let makeTitleLayout = TextNode.asyncLayout(node?.titleNode) - let makePriceLabelLayout = TextNode.asyncLayout(node?.priceLabelNode) - let makePriceValueLayout = TextNode.asyncLayout(node?.priceValueNode) - let makeTimeLabelLayout = TextNode.asyncLayout(node?.timeLabelNode) - let makeTimeValueLayout = TextNode.asyncLayout(node?.timeValueNode) - - return { item, maxWidth in - let insets = UIEdgeInsets( - top: 12.0, - left: 12.0, - bottom: 12.0, - right: 12.0 - ) - - let titleSpacing: CGFloat = 8.0 - let labelSpacing: CGFloat = 8.0 - let valuesVerticalSpacing: CGFloat = 2.0 - - var amount: Int64 = 0 - var timestamp: Int32? - - if "".isEmpty { - amount = 0 - timestamp = nil - } - - /*for attribute in item.message.attributes { - if let attribute = attribute as? OutgoingSuggestedPostMessageAttribute { - amount = attribute.price.value - timestamp = attribute.timestamp - } - }*/ - - //TODO:localize - let amountString: String - if amount == 0 { - amountString = "Free" - } else if amount == 1 { - amountString = "1 Star" - } else { - amountString = "\(amount) Stars" - } - - var timestampString: String - if let timestamp { - timestampString = humanReadableStringForTimestamp(strings: item.presentationData.strings, dateTimeFormat: PresentationDateTimeFormat(), timestamp: timestamp, alwaysShowTime: true).string - if timestampString.count > 1 { - timestampString = String(timestampString[timestampString.startIndex]).capitalized + timestampString[timestampString.index(after: timestampString.startIndex)...] - } - } else { - timestampString = "Anytime" - } - - let serviceColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) - - //TODO:localize - let titleLayout = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "You suggest to post\nthis message.", font: Font.regular(13.0), textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxWidth - insets.left - insets.right, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) - - let priceLabelLayout = makePriceLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "Price", font: Font.regular(13.0), textColor: serviceColor.primaryText.withMultipliedAlpha(0.5)), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxWidth - insets.left - insets.right, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let timeLabelLayout = makeTimeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "Time", font: Font.regular(13.0), textColor: serviceColor.primaryText.withMultipliedAlpha(0.5)), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxWidth - insets.left - insets.right, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - - let priceValueLayout = makePriceValueLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: amountString, font: Font.semibold(13.0), textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxWidth - insets.left - insets.right, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let timeValueLayout = makeTimeValueLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: timestampString, font: Font.semibold(13.0), textColor: serviceColor.primaryText), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: maxWidth - insets.left - insets.right, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - - var maxContentWidth: CGFloat = 0.0 - var contentHeight: CGFloat = 0.0 - - maxContentWidth = max(maxContentWidth, titleLayout.0.size.width) - - contentHeight += titleLayout.0.size.height - contentHeight += titleSpacing - - maxContentWidth = max(maxContentWidth, priceLabelLayout.0.size.width + labelSpacing + priceValueLayout.0.size.width) - contentHeight += priceLabelLayout.0.size.height + valuesVerticalSpacing - - maxContentWidth = max(maxContentWidth, timeLabelLayout.0.size.width + labelSpacing + timeValueLayout.0.size.width) - contentHeight += timeLabelLayout.0.size.height - - let size = CGSize(width: insets.left + insets.right + maxContentWidth, height: insets.top + insets.bottom + contentHeight) - - return (size, { - let node = node ?? ChatMessageSuggestedPostInfoNode() - - if node.backgroundNode == nil { - if let backgroundNode = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { - node.backgroundNode = backgroundNode - backgroundNode.layer.masksToBounds = true - backgroundNode.layer.cornerRadius = 15.0 - node.insertSubnode(backgroundNode, at: 0) - } - } - - if let backgroundNode = node.backgroundNode { - backgroundNode.frame = CGRect(origin: CGPoint(), size: size) - } - - let titleNode = titleLayout.1() - if node.titleNode !== titleNode { - node.titleNode = titleNode - node.addSubnode(titleNode) - } - let priceLabelNode = priceLabelLayout.1() - if node.priceLabelNode !== priceLabelNode { - node.priceLabelNode = priceLabelNode - node.addSubnode(priceLabelNode) - } - let priceValueNode = priceValueLayout.1() - if node.priceValueNode !== priceValueNode { - node.priceValueNode = priceValueNode - node.addSubnode(priceValueNode) - } - let timeLabelNode = timeLabelLayout.1() - if node.timeLabelNode !== timeLabelNode { - node.timeLabelNode = timeLabelNode - node.addSubnode(timeLabelNode) - } - let timeValueNode = timeValueLayout.1() - if node.timeValueNode !== timeValueNode { - node.timeValueNode = timeValueNode - node.addSubnode(timeValueNode) - } - - let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleLayout.0.size.width) * 0.5), y: insets.top), size: titleLayout.0.size) - titleNode.frame = titleFrame - - let priceLabelFrame = CGRect(origin: CGPoint(x: insets.left, y: titleFrame.maxY + titleSpacing), size: priceLabelLayout.0.size) - priceLabelNode.frame = priceLabelFrame - priceValueNode.frame = CGRect(origin: CGPoint(x: priceLabelFrame.maxX + labelSpacing, y: priceLabelFrame.minY), size: priceValueLayout.0.size) - - let timeLabelFrame = CGRect(origin: CGPoint(x: insets.left, y: priceLabelFrame.maxY + valuesVerticalSpacing), size: timeLabelLayout.0.size) - timeLabelNode.frame = timeLabelFrame - timeValueNode.frame = CGRect(origin: CGPoint(x: timeLabelFrame.maxX + labelSpacing, y: timeLabelFrame.minY), size: timeValueLayout.0.size) - - return node - }) - } - } -} diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift index 386b50a569..5f65b540b3 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift @@ -139,8 +139,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { } if case let .channel(channel) = peer, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = firstMessage.peers[linkedMonoforumId] { - //TODO:localize - title = authorString + "@" + EnginePeer(mainChannel).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + " Messages" + title = authorString + "@" + EnginePeer(mainChannel).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } else { if let threadData = item.threadData { title = "\(authorString) → \(threadData.info.title)" diff --git a/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift b/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift index 9d5ff46ff3..a0996b2b03 100644 --- a/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift +++ b/submodules/TelegramUI/Components/Chat/ChatSideTopicsPanel/Sources/ChatSideTopicsPanel.swift @@ -417,8 +417,7 @@ public final class ChatSideTopicsPanel: Component { if let threadData = component.item.item.threadData { titleText = threadData.info.title } else { - //TODO:localize - titleText = "General" + titleText = " " } } else { titleText = component.item.item.renderedPeer.chatMainPeer?.compactDisplayTitle ?? " " @@ -847,8 +846,7 @@ public final class ChatSideTopicsPanel: Component { if let threadData = component.item.item.threadData { titleText = threadData.info.title } else { - //TODO:localize - titleText = "General" + titleText = " " } } else { titleText = component.item.item.renderedPeer.chatMainPeer?.compactDisplayTitle ?? " " @@ -1220,8 +1218,7 @@ public final class ChatSideTopicsPanel: Component { containerSize: CGSize(width: 100.0, height: 100.0) ) - //TODO:localize - let titleText: String = "All" + let titleText: String = component.strings.Chat_InlineTopicMenu_AllTab let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( @@ -1348,8 +1345,7 @@ public final class ChatSideTopicsPanel: Component { let leftInset: CGFloat = 6.0 let rightInset: CGFloat = 12.0 - //TODO:localize - let titleText: String = "All" + let titleText: String = component.strings.Chat_InlineTopicMenu_AllTab let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index cdb138e96b..0e207a473e 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -2219,8 +2219,7 @@ private func editingItems(data: PeerInfoScreenData?, boostStatus: ChannelBoostSt interaction.editingOpenDiscussionGroupSetup() })) - //TODO:localize - items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text(channel.linkedMonoforumId == nil ? "Off" : "On"), additionalBadgeLabel: presentationData.strings.Settings_New, text: "Allow Channel Messages", icon: UIImage(bundleImageName: "Chat/Info/PostSuggestionsIcon"), action: { + items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text(channel.linkedMonoforumId == nil ? presentationData.strings.PeerInfo_AllowChannelMessages_Off : presentationData.strings.PeerInfo_AllowChannelMessages_On), additionalBadgeLabel: presentationData.strings.Settings_New, text: presentationData.strings.PeerInfo_AllowChannelMessages, icon: UIImage(bundleImageName: "Chat/Info/PostSuggestionsIcon"), action: { interaction.editingOpenPostSuggestionsSetup() })) } @@ -2357,8 +2356,7 @@ private func editingItems(data: PeerInfoScreenData?, boostStatus: ChannelBoostSt })) if channel.linkedMonoforumId != nil { - //TODO:localize - items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemChannelMessages, label: .none, text: "Channel Messages", icon: UIImage(bundleImageName: "Chat/Info/RecentActionsIcon"), action: { + items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemChannelMessages, label: .none, text: presentationData.strings.PeerInfo_ChannelMessages, icon: UIImage(bundleImageName: "Chat/Info/RecentActionsIcon"), action: { interaction.openChannelMessages() })) } diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 8d12f0c738..051a1eb154 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -566,8 +566,6 @@ extension ChatControllerImpl { let initTimestamp = self.initTimestamp #endif - //TODO:release ready must include chat node - self.ready.set(combineLatest(queue: .mainQueue(), [ self.contentDataReady.get(), self.wallpaperReady.get(), diff --git a/submodules/TelegramUI/Sources/ChatControllerContentData.swift b/submodules/TelegramUI/Sources/ChatControllerContentData.swift index 0dc9f04990..ab3a8ecde7 100644 --- a/submodules/TelegramUI/Sources/ChatControllerContentData.swift +++ b/submodules/TelegramUI/Sources/ChatControllerContentData.swift @@ -547,7 +547,6 @@ extension ChatControllerImpl { strongSelf.state.chatTitleContent = .custom(strings.Chat_TitlePinnedMessages(Int32(displayedCount ?? 1)), nil, false) } else if let channel = peer as? TelegramChannel, channel.isMonoForum { if let linkedMonoforumId = channel.linkedMonoforumId, let mainPeer = peerView.peers[linkedMonoforumId] { - //TODO:localize strongSelf.state.chatTitleContent = .custom(mainPeer.debugDisplayTitle, nil, false) } else { strongSelf.state.chatTitleContent = .custom(channel.debugDisplayTitle, nil, false) diff --git a/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift index 3ceac34a9f..fa55bbeddc 100644 --- a/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTopicListTitleAccessoryPanelNode.swift @@ -49,486 +49,6 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C } } - /*private final class ItemView: UIView { - private let context: AccountContext - private let action: () -> Void - - private let extractedContainerNode: ContextExtractedContentContainingNode - private let containerNode: ContextControllerSourceNode - - private let containerButton: HighlightTrackingButton - - private var icon: ComponentView? - private var avatarNode: AvatarNode? - private let title = ComponentView() - private var badge: ComponentView? - - init(context: AccountContext, action: @escaping (() -> Void), contextGesture: @escaping (ContextGesture, ContextExtractedContentContainingNode) -> Void) { - self.context = context - self.action = action - - self.extractedContainerNode = ContextExtractedContentContainingNode() - self.containerNode = ContextControllerSourceNode() - - self.containerButton = HighlightTrackingButton() - - super.init(frame: CGRect()) - - self.extractedContainerNode.contentNode.view.addSubview(self.containerButton) - - self.containerNode.addSubnode(self.extractedContainerNode) - self.containerNode.targetNodeForActivationProgress = self.extractedContainerNode.contentNode - self.addSubview(self.containerNode.view) - - self.containerButton.addTarget(self, action: #selector(self.pressed), for: .touchUpInside) - self.containerButton.highligthedChanged = { [weak self] highlighted in - if let self, self.bounds.width > 0.0 { - let topScale: CGFloat = (self.bounds.width - 1.0) / self.bounds.width - let maxScale: CGFloat = (self.bounds.width + 1.0) / self.bounds.width - - if highlighted { - self.layer.removeAnimation(forKey: "opacity") - self.layer.removeAnimation(forKey: "sublayerTransform") - let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) - transition.updateTransformScale(layer: self.layer, scale: topScale) - } else { - let transition: ContainedViewLayoutTransition = .immediate - transition.updateTransformScale(layer: self.layer, scale: 1.0) - - self.layer.animateScale(from: topScale, to: maxScale, duration: 0.13, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in - guard let self else { - return - } - - self.layer.animateScale(from: maxScale, to: 1.0, duration: 0.1, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue) - }) - } - } - } - - self.containerNode.isGestureEnabled = false - } - - required init?(coder: NSCoder) { - preconditionFailure() - } - - @objc private func pressed() { - self.action() - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - var mappedPoint = point - if self.bounds.insetBy(dx: -8.0, dy: -4.0).contains(point) { - mappedPoint = self.bounds.center - } - return super.hitTest(mappedPoint, with: event) - } - - func update(context: AccountContext, item: Item, isSelected: Bool, theme: PresentationTheme, height: CGFloat, transition: ComponentTransition) -> CGSize { - let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.25) - - let spacing: CGFloat = 3.0 - let badgeSpacing: CGFloat = 4.0 - - let iconSize = CGSize(width: 18.0, height: 18.0) - - var avatarIconContent: EmojiStatusComponent.Content? - if case let .forum(topicId) = item.item.id { - if topicId != 1, let threadData = item.item.threadData { - if let fileId = threadData.info.icon, fileId != 0 { - avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: iconSize, placeholderColor: theme.list.mediaPlaceholderColor, themeColor: theme.list.itemAccentColor, loopMode: .count(0)) - } else { - avatarIconContent = .topic(title: String(threadData.info.title.prefix(1)), color: threadData.info.iconColor, size: iconSize) - } - } else { - avatarIconContent = .image(image: PresentationResourcesChatList.generalTopicIcon(theme), tintColor: theme.rootController.navigationBar.secondaryTextColor) - } - } - - if let avatarIconContent { - let avatarIconComponent = EmojiStatusComponent( - context: context, - animationCache: context.animationCache, - animationRenderer: context.animationRenderer, - content: avatarIconContent, - isVisibleForAnimations: false, - action: nil - ) - let icon: ComponentView - if let current = self.icon { - icon = current - } else { - icon = ComponentView() - self.icon = icon - } - let _ = icon.update( - transition: .immediate, - component: AnyComponent(avatarIconComponent), - environment: {}, - containerSize: CGSize(width: 18.0, height: 18.0) - ) - } else if let icon = self.icon { - self.icon = nil - icon.view?.removeFromSuperview() - } - - let titleText: String - if case let .forum(topicId) = item.item.id { - let _ = topicId - if let threadData = item.item.threadData { - titleText = threadData.info.title - } else { - //TODO:localize - titleText = "General" - } - } else { - titleText = item.item.renderedPeer.chatMainPeer?.compactDisplayTitle ?? " " - } - let titleSize = self.title.update( - transition: .immediate, - component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: titleText, font: Font.medium(14.0), textColor: isSelected ? theme.rootController.navigationBar.accentTextColor : theme.rootController.navigationBar.secondaryTextColor)) - )), - environment: {}, - containerSize: CGSize(width: 100.0, height: 100.0) - ) - - var badgeSize: CGSize? - if let readCounters = item.item.readCounters, readCounters.count > 0 { - let badge: ComponentView - var badgeTransition = transition - if let current = self.badge { - badge = current - } else { - badgeTransition = .immediate - badge = ComponentView() - self.badge = badge - } - - badgeSize = badge.update( - transition: badgeTransition, - component: AnyComponent(TextBadgeComponent( - text: countString(Int64(readCounters.count)), - font: Font.regular(12.0), - background: item.item.isMuted ? theme.chatList.unreadBadgeInactiveBackgroundColor : theme.chatList.unreadBadgeActiveBackgroundColor, - foreground: item.item.isMuted ? theme.chatList.unreadBadgeInactiveTextColor : theme.chatList.unreadBadgeActiveTextColor, - insets: UIEdgeInsets(top: 1.0, left: 5.0, bottom: 2.0, right: 5.0) - )), - environment: {}, - containerSize: CGSize(width: 100.0, height: 100.0) - ) - } - - var contentSize: CGFloat = iconSize.width + spacing + titleSize.width - if let badgeSize { - contentSize += badgeSpacing + badgeSize.width - } - - let size = CGSize(width: contentSize, height: height) - - let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: 5.0 + floor((size.height - iconSize.height) * 0.5)), size: iconSize) - let titleFrame = CGRect(origin: CGPoint(x: iconFrame.maxX + spacing, y: 5.0 + floor((size.height - titleSize.height) * 0.5)), size: titleSize) - - if let icon = self.icon { - if let iconView = icon.view { - if iconView.superview == nil { - iconView.isUserInteractionEnabled = false - self.containerButton.addSubview(iconView) - } - iconView.frame = iconFrame - } - - if let avatarNode = self.avatarNode { - self.avatarNode = nil - avatarNode.view.removeFromSuperview() - } - } else { - let avatarNode: AvatarNode - if let current = self.avatarNode { - avatarNode = current - } else { - avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 7.0)) - self.avatarNode = avatarNode - self.containerButton.addSubview(avatarNode.view) - } - avatarNode.frame = iconFrame - avatarNode.updateSize(size: iconFrame.size) - - if let peer = item.item.renderedPeer.chatMainPeer { - if peer.smallProfileImage != nil { - avatarNode.setPeerV2(context: context, theme: theme, peer: peer, overrideImage: nil, emptyColor: .gray, clipStyle: .round, synchronousLoad: false, displayDimensions: iconFrame.size) - } else { - avatarNode.setPeer(context: context, theme: theme, peer: peer, overrideImage: nil, emptyColor: .gray, clipStyle: .round, synchronousLoad: false, displayDimensions: iconFrame.size) - } - } - } - - if let titleView = self.title.view { - if titleView.superview == nil { - titleView.isUserInteractionEnabled = false - self.containerButton.addSubview(titleView) - } - titleView.frame = titleFrame - } - - if let badgeSize, let badge = self.badge { - let badgeFrame = CGRect(origin: CGPoint(x: titleFrame.maxX + badgeSpacing, y: titleFrame.minY + floorToScreenPixels((titleFrame.height - badgeSize.height) * 0.5)), size: badgeSize) - - if let badgeView = badge.view { - if badgeView.superview == nil { - badgeView.isUserInteractionEnabled = false - self.containerButton.addSubview(badgeView) - badgeView.frame = badgeFrame - badgeView.alpha = 0.0 - } - transition.setPosition(view: badgeView, position: badgeFrame.center) - transition.setBounds(view: badgeView, bounds: CGRect(origin: CGPoint(), size: badgeFrame.size)) - transition.setScale(view: badgeView, scale: 1.0) - alphaTransition.setAlpha(view: badgeView, alpha: 1.0) - } - } else if let badge = self.badge { - self.badge = nil - if let badgeView = badge.view { - let badgeFrame = CGRect(origin: CGPoint(x: titleFrame.maxX + badgeSpacing, y: titleFrame.minX + floorToScreenPixels((titleFrame.height - badgeView.bounds.height) * 0.5)), size: badgeView.bounds.size) - transition.setPosition(view: badgeView, position: badgeFrame.center) - transition.setScale(view: badgeView, scale: 0.001) - alphaTransition.setAlpha(view: badgeView, alpha: 0.0, completion: { [weak badgeView] _ in - badgeView?.removeFromSuperview() - }) - } - } - - transition.setFrame(view: self.containerButton, frame: CGRect(origin: CGPoint(), size: size)) - - self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)) - self.containerNode.frame = CGRect(origin: CGPoint(), size: size) - - return size - } - } - - private final class TabItemView: UIView { - private let context: AccountContext - private let action: () -> Void - - private let extractedContainerNode: ContextExtractedContentContainingNode - private let containerNode: ContextControllerSourceNode - - private let containerButton: HighlightTrackingButton - - private let icon = ComponentView() - - init(context: AccountContext, action: @escaping (() -> Void)) { - self.context = context - self.action = action - - self.extractedContainerNode = ContextExtractedContentContainingNode() - self.containerNode = ContextControllerSourceNode() - - self.containerButton = HighlightTrackingButton() - - super.init(frame: CGRect()) - - self.extractedContainerNode.contentNode.view.addSubview(self.containerButton) - - self.containerNode.addSubnode(self.extractedContainerNode) - self.containerNode.targetNodeForActivationProgress = self.extractedContainerNode.contentNode - self.addSubview(self.containerNode.view) - - self.containerButton.addTarget(self, action: #selector(self.pressed), for: .touchUpInside) - self.containerButton.highligthedChanged = { [weak self] highlighted in - if let self, self.bounds.width > 0.0 { - let topScale: CGFloat = (self.bounds.width - 1.0) / self.bounds.width - let maxScale: CGFloat = (self.bounds.width + 1.0) / self.bounds.width - - if highlighted { - self.layer.removeAnimation(forKey: "opacity") - self.layer.removeAnimation(forKey: "sublayerTransform") - let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) - transition.updateTransformScale(layer: self.layer, scale: topScale) - } else { - let transition: ContainedViewLayoutTransition = .immediate - transition.updateTransformScale(layer: self.layer, scale: 1.0) - - self.layer.animateScale(from: topScale, to: maxScale, duration: 0.13, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in - guard let self else { - return - } - - self.layer.animateScale(from: maxScale, to: 1.0, duration: 0.1, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue) - }) - } - } - } - - self.containerNode.isGestureEnabled = false - } - - required init?(coder: NSCoder) { - preconditionFailure() - } - - @objc private func pressed() { - self.action() - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - var mappedPoint = point - if self.bounds.insetBy(dx: -8.0, dy: -4.0).contains(point) { - mappedPoint = self.bounds.center - } - return super.hitTest(mappedPoint, with: event) - } - - func update(context: AccountContext, theme: PresentationTheme, height: CGFloat, transition: ComponentTransition) -> CGSize { - let iconSize = self.icon.update( - transition: .immediate, - component: AnyComponent(BundleIconComponent( - name: "Chat/Title Panels/SidebarIcon", - tintColor: theme.rootController.navigationBar.secondaryTextColor, - maxSize: nil, - scaleFactor: 1.0 - )), - environment: {}, - containerSize: CGSize(width: 100.0, height: 100.0) - ) - - let contentSize: CGFloat = iconSize.width - let size = CGSize(width: contentSize, height: height) - - let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: 5.0 + floor((size.height - iconSize.height) * 0.5)), size: iconSize) - - if let iconView = self.icon.view { - if iconView.superview == nil { - iconView.isUserInteractionEnabled = false - self.containerButton.addSubview(iconView) - } - iconView.frame = iconFrame - } - - transition.setFrame(view: self.containerButton, frame: CGRect(origin: CGPoint(), size: size)) - - self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)) - self.containerNode.frame = CGRect(origin: CGPoint(), size: size) - - return size - } - } - - private final class AllItemView: UIView { - private let context: AccountContext - private let action: () -> Void - - private let extractedContainerNode: ContextExtractedContentContainingNode - private let containerNode: ContextControllerSourceNode - - private let containerButton: HighlightTrackingButton - - private let title = ComponentView() - - init(context: AccountContext, action: @escaping (() -> Void)) { - self.context = context - self.action = action - - self.extractedContainerNode = ContextExtractedContentContainingNode() - self.containerNode = ContextControllerSourceNode() - - self.containerButton = HighlightTrackingButton() - - super.init(frame: CGRect()) - - self.extractedContainerNode.contentNode.view.addSubview(self.containerButton) - - self.containerNode.addSubnode(self.extractedContainerNode) - self.containerNode.targetNodeForActivationProgress = self.extractedContainerNode.contentNode - self.addSubview(self.containerNode.view) - - self.containerButton.addTarget(self, action: #selector(self.pressed), for: .touchUpInside) - self.containerButton.highligthedChanged = { [weak self] highlighted in - if let self, self.bounds.width > 0.0 { - let topScale: CGFloat = (self.bounds.width - 1.0) / self.bounds.width - let maxScale: CGFloat = (self.bounds.width + 1.0) / self.bounds.width - - if highlighted { - self.layer.removeAnimation(forKey: "opacity") - self.layer.removeAnimation(forKey: "sublayerTransform") - let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) - transition.updateTransformScale(layer: self.layer, scale: topScale) - } else { - let transition: ContainedViewLayoutTransition = .immediate - transition.updateTransformScale(layer: self.layer, scale: 1.0) - - self.layer.animateScale(from: topScale, to: maxScale, duration: 0.13, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in - guard let self else { - return - } - - self.layer.animateScale(from: maxScale, to: 1.0, duration: 0.1, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue) - }) - } - } - } - - self.containerNode.isGestureEnabled = false - } - - required init?(coder: NSCoder) { - preconditionFailure() - } - - @objc private func pressed() { - self.action() - } - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - var mappedPoint = point - if self.bounds.insetBy(dx: -8.0, dy: -4.0).contains(point) { - mappedPoint = self.bounds.center - } - return super.hitTest(mappedPoint, with: event) - } - - func update(context: AccountContext, isSelected: Bool, theme: PresentationTheme, height: CGFloat, transition: ComponentTransition) -> CGSize { - //TODO:localize - let titleText: String = "All" - let titleSize = self.title.update( - transition: .immediate, - component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: titleText, font: Font.medium(14.0), textColor: isSelected ? theme.rootController.navigationBar.accentTextColor : theme.rootController.navigationBar.secondaryTextColor)) - )), - environment: {}, - containerSize: CGSize(width: 100.0, height: 100.0) - ) - - let contentSize: CGFloat = titleSize.width - let size = CGSize(width: contentSize, height: height) - - let titleFrame = CGRect(origin: CGPoint(x: 0.0, y: 5.0 + floor((size.height - titleSize.height) * 0.5)), size: titleSize) - - if let titleView = self.title.view { - if titleView.superview == nil { - titleView.isUserInteractionEnabled = false - self.containerButton.addSubview(titleView) - } - titleView.frame = titleFrame - } - - transition.setFrame(view: self.containerButton, frame: CGRect(origin: CGPoint(), size: size)) - - self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentNode.frame = CGRect(origin: CGPoint(), size: size) - self.extractedContainerNode.contentRect = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)) - self.containerNode.frame = CGRect(origin: CGPoint(), size: size) - - return size - } - }*/ - private var params: Params? private let context: AccountContext @@ -618,234 +138,11 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C } transition.updateFrame(view: panelView, frame: panelFrame) } - - /* - - let containerInsets = UIEdgeInsets(top: 0.0, left: params.leftInset + 16.0, bottom: 0.0, right: params.rightInset + 16.0) - let itemSpacing: CGFloat = 24.0 - - var leftContentInset: CGFloat = containerInsets.left + 8.0 - - do { - var itemTransition = transition - var animateIn = false - let itemView: TabItemView - if let current = self.tabItemView { - itemView = current - } else { - itemTransition = .immediate - animateIn = true - itemView = TabItemView(context: self.context, action: { [weak self] in - guard let self else { - return - } - self.interfaceInteraction?.toggleChatSidebarMode() - }) - self.tabItemView = itemView - self.view.addSubview(itemView) - } - - let itemSize = itemView.update(context: self.context, theme: params.interfaceState.theme, height: panelHeight, transition: .immediate) - let itemFrame = CGRect(origin: CGPoint(x: leftContentInset, y: -5.0), size: itemSize) - - itemTransition.updatePosition(layer: itemView.layer, position: itemFrame.center) - itemTransition.updateBounds(layer: itemView.layer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) - - if animateIn && transition.isAnimated { - itemView.layer.animateAlpha(from: 0.0, to: itemView.alpha, duration: 0.15) - transition.animateTransformScale(view: itemView, from: 0.001) - } - - leftContentInset += itemSize.width + 8.0 - } - - var contentSize = CGSize(width: itemSpacing - 8.0, height: panelHeight) - - var validIds: [Item.Id] = [] - var isFirst = true - var selectedItemFrame: CGRect? - - do { - if isFirst { - isFirst = false - } else { - contentSize.width += itemSpacing - } - - var itemTransition = transition - var animateIn = false - let itemView: AllItemView - if let current = self.allItemView { - itemView = current - } else { - itemTransition = .immediate - animateIn = true - itemView = AllItemView(context: self.context, action: { [weak self] in - guard let self else { - return - } - self.interfaceInteraction?.updateChatLocationThread(nil, .left) - }) - self.allItemView = itemView - self.scrollView.addSubview(itemView) - } - - var isSelected = false - if params.interfaceState.chatLocation.threadId == nil { - isSelected = true - } - let itemSize = itemView.update(context: self.context, isSelected: isSelected, theme: params.interfaceState.theme, height: panelHeight, transition: .immediate) - let itemFrame = CGRect(origin: CGPoint(x: contentSize.width, y: -5.0), size: itemSize) - - if isSelected { - selectedItemFrame = itemFrame - } - - itemTransition.updatePosition(layer: itemView.layer, position: itemFrame.center) - itemTransition.updateBounds(layer: itemView.layer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) - - if animateIn && transition.isAnimated { - itemView.layer.animateAlpha(from: 0.0, to: itemView.alpha, duration: 0.15) - transition.animateTransformScale(view: itemView, from: 0.001) - } - - contentSize.width += itemSize.width - } - - for item in self.items { - if isFirst { - isFirst = false - } else { - contentSize.width += itemSpacing - } - let itemId = item.id - validIds.append(itemId) - - var itemTransition = transition - var animateIn = false - let itemView: ItemView - if let current = self.itemViews[itemId] { - itemView = current - } else { - itemTransition = .immediate - animateIn = true - let chatListItem = item.item - itemView = ItemView(context: self.context, action: { [weak self] in - guard let self else { - return - } - - let topicId: Int64 - if case let .forum(topicIdValue) = chatListItem.id { - topicId = topicIdValue - } else { - topicId = chatListItem.renderedPeer.peerId.toInt64() - } - - var direction = true - if let params = self.params, let lhsIndex = self.topicIndex(threadId: params.interfaceState.chatLocation.threadId), let rhsIndex = self.topicIndex(threadId: topicId) { - direction = lhsIndex < rhsIndex - } - - self.interfaceInteraction?.updateChatLocationThread(topicId, direction ? .right : .left) - }, contextGesture: { gesture, sourceNode in - }) - self.itemViews[itemId] = itemView - self.scrollView.addSubview(itemView) - } - - var isSelected = false - if case let .forum(topicId) = item.item.id { - isSelected = params.interfaceState.chatLocation.threadId == topicId - } else { - isSelected = params.interfaceState.chatLocation.threadId == item.item.renderedPeer.peerId.toInt64() - } - let itemSize = itemView.update(context: self.context, item: item, isSelected: isSelected, theme: params.interfaceState.theme, height: panelHeight, transition: .immediate) - let itemFrame = CGRect(origin: CGPoint(x: contentSize.width, y: -5.0), size: itemSize) - - if isSelected { - selectedItemFrame = itemFrame - } - - itemTransition.updatePosition(layer: itemView.layer, position: itemFrame.center) - itemTransition.updateBounds(layer: itemView.layer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) - - if animateIn && transition.isAnimated { - itemView.layer.animateAlpha(from: 0.0, to: itemView.alpha, duration: 0.15) - transition.animateTransformScale(view: itemView, from: 0.001) - } - - contentSize.width += itemSize.width - } - var removedIds: [Item.Id] = [] - for (id, itemView) in self.itemViews { - if !validIds.contains(id) { - removedIds.append(id) - - if transition.isAnimated { - itemView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak itemView] _ in - itemView?.removeFromSuperview() - }) - transition.updateTransformScale(layer: itemView.layer, scale: 0.001) - } else { - itemView.removeFromSuperview() - } - } - } - for id in removedIds { - self.itemViews.removeValue(forKey: id) - } - - if let selectedItemFrame { - let lineFrame = CGRect(origin: CGPoint(x: selectedItemFrame.minX, y: panelHeight - 4.0), size: CGSize(width: selectedItemFrame.width + 4.0, height: 4.0)) - if self.selectedLineView.isHidden { - self.selectedLineView.isHidden = false - self.selectedLineView.frame = lineFrame - } else { - transition.updateFrame(view: self.selectedLineView, frame: lineFrame) - } - } else { - self.selectedLineView.isHidden = true - } - - contentSize.width += containerInsets.right - - let scrollSize = CGSize(width: params.width - leftContentInset, height: contentSize.height) - self.scrollViewContainer.frame = CGRect(origin: CGPoint(x: leftContentInset, y: 0.0), size: scrollSize) - self.scrollViewMask.frame = CGRect(origin: CGPoint(), size: scrollSize) - - if self.scrollView.bounds.size != scrollSize { - self.scrollView.frame = CGRect(origin: CGPoint(), size: scrollSize) - } - if self.scrollView.contentSize != contentSize { - self.scrollView.contentSize = contentSize - } - - let scrollToId: ScrollId - if let threadId = params.interfaceState.chatLocation.threadId { - scrollToId = .topic(threadId) - } else { - scrollToId = .all - } - if self.appliedScrollToId != scrollToId { - if case let .topic(threadId) = scrollToId { - if let itemView = self.itemViews[.forum(threadId)] { - self.appliedScrollToId = scrollToId - self.scrollView.scrollRectToVisible(itemView.frame.insetBy(dx: -46.0, dy: 0.0), animated: hadItemViews) - } - } else if case .all = scrollToId { - self.appliedScrollToId = scrollToId - self.scrollView.scrollRectToVisible(CGRect(origin: CGPoint(), size: CGSize(width: 1.0, height: 1.0)), animated: hadItemViews) - } else { - self.appliedScrollToId = scrollToId - } - }*/ } public func updateGlobalOffset(globalOffset: CGFloat, transition: ComponentTransition) { if let panelView = self.panel.view as? ChatSideTopicsPanel.View { panelView.updateGlobalOffset(globalOffset: globalOffset, transition: transition) - //transition.setTransform(view: tabItemView, transform: CATransform3DMakeTranslation(0.0, -globalOffset, 0.0)) } } @@ -855,23 +152,5 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C } else { return nil } - - /*if let threadId { - if let value = self.items.firstIndex(where: { item in - if item.id == .chatList(PeerId(threadId)) { - return true - } else if item.id == .forum(threadId) { - return true - } else { - return false - } - }) { - return value + 1 - } else { - return nil - } - } else { - return 0 - }*/ } }