diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index deffdc64bd..90d84f161d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -14410,3 +14410,5 @@ Sorry for the inconvenience."; "Stars.SendMessage.AdjustmentSectionFooterValue" = "You will receive **%@ Stars**."; "Stars.SendMessage.AdjustmentSectionFooterEmpty" = "You will receive **80%**."; "Stars.SendMessage.AdjustmentAction" = "OK"; + +"Stars.SendMessage.PriceFree" = "Free"; diff --git a/submodules/Postbox/Sources/MessageHistoryView.swift b/submodules/Postbox/Sources/MessageHistoryView.swift index 94b0a438a5..b35d8366c3 100644 --- a/submodules/Postbox/Sources/MessageHistoryView.swift +++ b/submodules/Postbox/Sources/MessageHistoryView.swift @@ -313,6 +313,7 @@ final class MutableMessageHistoryView: MutablePostboxView { private let clipHoles: Bool private let trackHoles: Bool private let anchor: HistoryViewInputAnchor + fileprivate var mapReadStatesFromThreads: Bool = false fileprivate var combinedReadStates: MessageHistoryViewReadState? fileprivate var transientReadStates: MessageHistoryViewReadState? @@ -322,6 +323,7 @@ final class MutableMessageHistoryView: MutablePostboxView { fileprivate var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] fileprivate var additionalDatas: [AdditionalMessageHistoryViewDataEntry] + fileprivate var threadMaxOutgoingReadId: [Int64: Int32] = [:] fileprivate(set) var sampledState: HistoryViewSample @@ -373,8 +375,14 @@ final class MutableMessageHistoryView: MutablePostboxView { switch peerIds { case let .associated(peerId, _): self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: peerId) != nil - case let .single(peerId, _): + case let .single(peerId, threadId): self.isAddedToChatList = postbox.chatListTable.getPeerChatListIndex(peerId: peerId) != nil + if threadId == nil, let peer = postbox.peerTable.get(peerId) { + let value = postbox.seedConfiguration.peerSummaryIsThreadBased(peer, peer.associatedPeerId.flatMap(postbox.peerTable.get)) + if value.value && value.threadsArePeers { + self.mapReadStatesFromThreads = true + } + } case let .external(input): switch input.content { case let .thread(peerId, _, _): @@ -401,6 +409,8 @@ final class MutableMessageHistoryView: MutablePostboxView { self.render(postbox: postbox) let _ = self.updateStoryStats(postbox: postbox) + + let _ = self.updateThreadInfos(postbox: postbox, updatedIds: nil) } private func reset(postbox: PostboxImpl) { @@ -1023,9 +1033,81 @@ final class MutableMessageHistoryView: MutablePostboxView { } } + if !transaction.updatedPeerThreadInfos.isEmpty { + if self.updateThreadInfos(postbox: postbox, updatedIds: transaction.updatedPeerThreadInfos) { + hasChanges = true + } + } + return hasChanges } + private func updateThreadInfos(postbox: PostboxImpl, updatedIds: Set?) -> Bool { + if self.mapReadStatesFromThreads, case let .single(peerId, peerThreadId) = self.peerIds, peerThreadId == nil { + switch self.sampledState { + case .loading: + if !self.threadMaxOutgoingReadId.isEmpty { + self.threadMaxOutgoingReadId.removeAll() + return true + } else { + return false + } + case let .loaded(loaded): + //TODO:release + let currentIds = Set(self.threadMaxOutgoingReadId.keys) + + var threadIds: Set = [] + for entry in loaded.entries { + if let threadId = entry.message.threadId { + threadIds.insert(threadId) + } + } + + var updated = false + if currentIds != threadIds { + updated = true + + for id in currentIds.subtracting(threadIds) { + self.threadMaxOutgoingReadId.removeValue(forKey: id) + } + } + + for threadId in threadIds { + var fetch = false + if let updatedIds { + if updatedIds.contains(MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadId)) { + fetch = true + } + } else { + fetch = self.threadMaxOutgoingReadId[threadId] == nil + } + + if fetch { + var maxOutgoingReadId: Int32? + if let threadData = postbox.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadId) { + maxOutgoingReadId = threadData.summary.maxOutgoingReadId + } + + let current = self.threadMaxOutgoingReadId[threadId] + if let maxOutgoingReadId { + if current != maxOutgoingReadId { + self.threadMaxOutgoingReadId[threadId] = maxOutgoingReadId + updated = true + } + } else if current != nil { + self.threadMaxOutgoingReadId.removeValue(forKey: threadId) + updated = true + } + } + } + + return updated + } + } else { + return false + } + } + private func render(postbox: PostboxImpl) { for namespace in self.topTaggedMessages.keys { if let entry = self.topTaggedMessages[namespace]!, case let .intermediate(message) = entry { @@ -1166,7 +1248,20 @@ public final class MessageHistoryView: PostboxView { } self.isLoadingEarlier = isLoadingEarlier entries = [] - if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates { + if mutableView.mapReadStatesFromThreads { + for entry in state.entries { + if mutableView.namespaces.contains(entry.message.id.namespace) { + var read = false + if let threadId = entry.message.threadId { + if let maxId = mutableView.threadMaxOutgoingReadId[threadId] { + read = entry.message.id.id <= maxId + } + } + + entries.append(MessageHistoryEntry(message: entry.message, isRead: read, location: entry.location, monthLocation: entry.monthLocation, attributes: entry.attributes)) + } + } + } else if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates { for entry in state.entries { if mutableView.namespaces.contains(entry.message.id.namespace) { let read: Bool diff --git a/submodules/Postbox/Sources/MessageHistoryViewState.swift b/submodules/Postbox/Sources/MessageHistoryViewState.swift index 02a4cf1532..7b665d1152 100644 --- a/submodules/Postbox/Sources/MessageHistoryViewState.swift +++ b/submodules/Postbox/Sources/MessageHistoryViewState.swift @@ -1308,6 +1308,7 @@ final class HistoryViewLoadedState { let halfLimit: Int let seedConfiguration: SeedConfiguration var orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries] + var threadSummaries: [Int64: Int32] var holes: HistoryViewHoles var spacesWithRemovals = Set() @@ -1321,6 +1322,7 @@ final class HistoryViewLoadedState { self.halfLimit = halfLimit self.seedConfiguration = postbox.seedConfiguration self.orderedEntriesBySpace = [:] + self.threadSummaries = [:] self.holes = holes var peerIds: [PeerId] = [] @@ -1854,6 +1856,7 @@ final class HistoryViewLoadedState { var holesToLower = false var holesToHigher = false var result: [MessageHistoryMessageEntry] = [] + if combinedSpacesAndIndicesByDirection.lowerOrAtAnchor.isEmpty && combinedSpacesAndIndicesByDirection.higherThanAnchor.isEmpty { if !clipRanges.isEmpty { holesToLower = true diff --git a/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift b/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift index d907298c7e..a51864febf 100644 --- a/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/MessagePriceItem/Sources/MessagePriceItem.swift @@ -368,8 +368,7 @@ private class MessagePriceItemNode: ListViewItemNode { strongSelf.leftTextNode.attributedText = NSAttributedString(string: "\(item.minValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor) strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor) - //TODO:localize - let centralLeftText = item.value == 0 ? "Free" : item.strings.Privacy_Messages_Stars(Int32(item.value)) + let centralLeftText = item.value == 0 ? item.strings.Stars_SendMessage_PriceFree : item.strings.Privacy_Messages_Stars(Int32(item.value)) strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor) strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor)