mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Added recent stickers clearing Added sending logs via email Added forward recipient change on forward acccessory panel tap Tweaked undo panel design Various UI fixes
269 lines
14 KiB
Swift
269 lines
14 KiB
Swift
import Foundation
|
|
import Postbox
|
|
import TelegramCore
|
|
|
|
enum ChatListNodeEntryId: Hashable {
|
|
case Hole(Int64)
|
|
case PeerId(Int64)
|
|
case GroupId(PeerGroupId)
|
|
|
|
var hashValue: Int {
|
|
switch self {
|
|
case let .Hole(peerId):
|
|
return peerId.hashValue
|
|
case let .PeerId(peerId):
|
|
return peerId.hashValue
|
|
case let .GroupId(groupId):
|
|
return groupId.hashValue
|
|
}
|
|
}
|
|
|
|
static func ==(lhs: ChatListNodeEntryId, rhs: ChatListNodeEntryId) -> Bool {
|
|
switch lhs {
|
|
case let .Hole(id):
|
|
if case .Hole(id) = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .PeerId(id):
|
|
if case .PeerId(id) = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .GroupId(groupId):
|
|
if case .GroupId(groupId) = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
enum ChatListNodeEntry: Comparable, Identifiable {
|
|
case PeerEntry(index: ChatListIndex, presentationData: ChatListPresentationData, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, peer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool)
|
|
case HoleEntry(ChatListHole, theme: PresentationTheme)
|
|
//case GroupReferenceEntry(index: ChatListIndex, presentationData: ChatListPresentationData, groupId: PeerGroupId, message: Message?, topPeers: [Peer], counters: GroupReferenceUnreadCounters, editing: Bool)
|
|
|
|
var index: ChatListIndex {
|
|
switch self {
|
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
|
return index
|
|
case let .HoleEntry(hole, _):
|
|
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
|
/*case let .GroupReferenceEntry(index, _, _, _, _, _, _):
|
|
return index*/
|
|
}
|
|
}
|
|
|
|
var stableId: ChatListNodeEntryId {
|
|
switch self {
|
|
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
|
return .PeerId(index.messageIndex.id.peerId.toInt64())
|
|
case let .HoleEntry(hole, _):
|
|
return .Hole(Int64(hole.index.id.id))
|
|
/*case let .GroupReferenceEntry(_, _, groupId, _, _, _, _):
|
|
return .GroupId(groupId)*/
|
|
}
|
|
}
|
|
|
|
static func <(lhs: ChatListNodeEntry, rhs: ChatListNodeEntry) -> Bool {
|
|
return lhs.index < rhs.index
|
|
}
|
|
|
|
static func ==(lhs: ChatListNodeEntry, rhs: ChatListNodeEntry) -> Bool {
|
|
switch lhs {
|
|
case let .PeerEntry(lhsIndex, lhsPresentationData, lhsMessage, lhsUnreadCount, lhsNotificationSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsSummaryInfo, lhsEditing, lhsHasRevealControls, lhsSelected, lhsInputActivities, lhsAd):
|
|
switch rhs {
|
|
case let .PeerEntry(rhsIndex, rhsPresentationData, rhsMessage, rhsUnreadCount, rhsNotificationSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsSummaryInfo, rhsEditing, rhsHasRevealControls, rhsSelected, rhsInputActivities, rhsAd):
|
|
if lhsIndex != rhsIndex {
|
|
return false
|
|
}
|
|
if lhsPresentationData !== rhsPresentationData {
|
|
return false
|
|
}
|
|
if lhsMessage?.stableVersion != rhsMessage?.stableVersion {
|
|
return false
|
|
}
|
|
if lhsMessage?.id != rhsMessage?.id || lhsMessage?.flags != rhsMessage?.flags || lhsUnreadCount != rhsUnreadCount {
|
|
return false
|
|
}
|
|
if let lhsNotificationSettings = lhsNotificationSettings, let rhsNotificationSettings = rhsNotificationSettings {
|
|
if !lhsNotificationSettings.isEqual(to: rhsNotificationSettings) {
|
|
return false
|
|
}
|
|
} else if (lhsNotificationSettings != nil) != (rhsNotificationSettings != nil) {
|
|
return false
|
|
}
|
|
if let lhsPeerPresence = lhsPresence, let rhsPeerPresence = rhsPresence {
|
|
if !lhsPeerPresence.isEqual(to: rhsPeerPresence) {
|
|
return false
|
|
}
|
|
} else if (lhsPresence != nil) != (rhsPresence != nil) {
|
|
return false
|
|
}
|
|
if let lhsEmbeddedState = lhsEmbeddedState, let rhsEmbeddedState = rhsEmbeddedState {
|
|
if !lhsEmbeddedState.isEqual(to: rhsEmbeddedState) {
|
|
return false
|
|
}
|
|
} else if (lhsEmbeddedState != nil) != (rhsEmbeddedState != nil) {
|
|
return false
|
|
}
|
|
if lhsEditing != rhsEditing {
|
|
return false
|
|
}
|
|
if lhsHasRevealControls != rhsHasRevealControls {
|
|
return false
|
|
}
|
|
if lhsSelected != rhsSelected {
|
|
return false
|
|
}
|
|
if lhsPeer != rhsPeer {
|
|
return false
|
|
}
|
|
if lhsSummaryInfo != rhsSummaryInfo {
|
|
return false
|
|
}
|
|
if let lhsInputActivities = lhsInputActivities, let rhsInputActivities = rhsInputActivities {
|
|
if lhsInputActivities.count != rhsInputActivities.count {
|
|
return false
|
|
}
|
|
for i in 0 ..< lhsInputActivities.count {
|
|
if !arePeersEqual(lhsInputActivities[i].0, rhsInputActivities[i].0) {
|
|
return false
|
|
}
|
|
if lhsInputActivities[i].1 != rhsInputActivities[i].1 {
|
|
return false
|
|
}
|
|
}
|
|
} else if (lhsInputActivities != nil) != (rhsInputActivities != nil) {
|
|
return false
|
|
}
|
|
if lhsAd != rhsAd {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case let .HoleEntry(lhsHole, lhsTheme):
|
|
switch rhs {
|
|
case let .HoleEntry(rhsHole, rhsTheme):
|
|
return lhsHole == rhsHole && lhsTheme === rhsTheme
|
|
default:
|
|
return false
|
|
}
|
|
/*case let .GroupReferenceEntry(lhsIndex, lhsPresentationData, lhsGroupId, lhsMessage, lhsTopPeers, lhsCounters, lhsEditing):
|
|
if case let .GroupReferenceEntry(rhsIndex, rhsPresentationData, rhsGroupId, rhsMessage, rhsTopPeers, rhsCounters, rhsEditing) = rhs {
|
|
if lhsIndex != rhsIndex {
|
|
return false
|
|
}
|
|
if lhsPresentationData !== rhsPresentationData {
|
|
return false
|
|
}
|
|
if lhsGroupId != rhsGroupId {
|
|
return false
|
|
}
|
|
if lhsMessage?.stableVersion != rhsMessage?.stableVersion {
|
|
return false
|
|
}
|
|
if lhsMessage?.id != rhsMessage?.id || lhsMessage?.flags != rhsMessage?.flags {
|
|
return false
|
|
}
|
|
if lhsTopPeers.count != rhsTopPeers.count {
|
|
return false
|
|
} else {
|
|
for i in 0 ..< lhsTopPeers.count {
|
|
if !arePeersEqual(lhsTopPeers[i], rhsTopPeers[i]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
if lhsCounters != rhsCounters {
|
|
return false
|
|
}
|
|
if lhsEditing != rhsEditing {
|
|
return false
|
|
}
|
|
return true
|
|
} else {
|
|
return false
|
|
}*/
|
|
}
|
|
}
|
|
}
|
|
|
|
private func offsetPinnedIndex(_ index: ChatListIndex, offset: UInt16) -> ChatListIndex {
|
|
if let pinningIndex = index.pinningIndex {
|
|
return ChatListIndex(pinningIndex: pinningIndex + offset, messageIndex: index.messageIndex)
|
|
} else {
|
|
return index
|
|
}
|
|
}
|
|
|
|
func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState, savedMessagesPeer: Peer?, mode: ChatListNodeMode) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
|
var result: [ChatListNodeEntry] = []
|
|
var pinnedIndexOffset: UInt16 = 0
|
|
if view.laterIndex == nil && savedMessagesPeer == nil {
|
|
pinnedIndexOffset = UInt16(view.additionalItemEntries.count)
|
|
}
|
|
|
|
loop: for entry in view.entries {
|
|
switch entry {
|
|
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
|
|
if let savedMessagesPeer = savedMessagesPeer, savedMessagesPeer.id == index.messageIndex.id.peerId {
|
|
continue loop
|
|
}
|
|
if state.pendingRemovalPeerIds.contains(index.messageIndex.id.peerId) {
|
|
continue loop
|
|
}
|
|
var updatedMessage = message
|
|
var updatedCombinedReadState = combinedReadState
|
|
if state.pendingClearHistoryPeerIds.contains(index.messageIndex.id.peerId) {
|
|
updatedMessage = nil
|
|
updatedCombinedReadState = nil
|
|
}
|
|
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false))
|
|
case let .HoleEntry(hole):
|
|
if hole.index.timestamp == Int32.max - 1 {
|
|
return ([], true)
|
|
}
|
|
result.append(.HoleEntry(hole, theme: state.presentationData.theme))
|
|
/*case let .GroupReferenceEntry(groupId, index, message, topPeers, counters):
|
|
if case .chatList = mode {
|
|
result.append(.GroupReferenceEntry(index: index, presentationData: state.presentationData, groupId: groupId, message: message, topPeers: topPeers, counters: counters, editing: state.editing))
|
|
}*/
|
|
}
|
|
}
|
|
if view.laterIndex == nil {
|
|
if let savedMessagesPeer = savedMessagesPeer {
|
|
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, message: nil, readState: nil, notificationSettings: nil, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, isAd: false))
|
|
} else {
|
|
if !view.additionalItemEntries.isEmpty {
|
|
var pinningIndex: UInt16 = UInt16(view.additionalItemEntries.count - 1)
|
|
for entry in view.additionalItemEntries.reversed() {
|
|
switch entry {
|
|
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
|
|
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex), presentationData: state.presentationData, message: message, readState: combinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: true))
|
|
if pinningIndex != 0 {
|
|
pinningIndex -= 1
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if result.count >= 1, case .HoleEntry = result[result.count - 1] {
|
|
return ([], true)
|
|
} else if result.count == 1, case .HoleEntry = result[0] {
|
|
return ([], true)
|
|
}
|
|
return (result, false)
|
|
}
|