mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-27 13:40:41 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
b0c6afdcee
@ -1515,11 +1515,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
switch item.index {
|
switch item.index {
|
||||||
case .chatList:
|
case .chatList:
|
||||||
if case let .channel(channel) = peer.peer, channel.isForumOrMonoForum {
|
if case let .channel(channel) = peer.peer, (channel.isForum || (channel.isMonoForum && threadId != nil)) {
|
||||||
if let threadId = threadId {
|
if let threadId = threadId {
|
||||||
let source: ContextContentSource
|
let source: ContextContentSource
|
||||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, isMonoforumPost: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: !channel.isMonoForum, isMonoforumPost: channel.isMonoForum, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||||
)), subject: nil, botStart: nil, mode: .standard(.previewing), params: nil)
|
)), subject: nil, botStart: nil, mode: .standard(.previewing), params: nil)
|
||||||
chatController.canReadHistory.set(false)
|
chatController.canReadHistory.set(false)
|
||||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||||
|
@ -1195,7 +1195,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
requiresPremiumForMessaging: requiresPremiumForMessaging,
|
requiresPremiumForMessaging: requiresPremiumForMessaging,
|
||||||
displayAsTopicList: false,
|
displayAsTopicList: false,
|
||||||
tags: []
|
tags: []
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enabledContextActions: nil, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
case let .messagePlaceholder(_, presentationData, searchScope):
|
case let .messagePlaceholder(_, presentationData, searchScope):
|
||||||
var actionTitle: String?
|
var actionTitle: String?
|
||||||
@ -1215,7 +1215,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
let header = ChatListSearchItemHeader(type: .messages(location: nil), theme: presentationData.theme, strings: presentationData.strings, actionTitle: actionTitle, action: { sourceNode in
|
let header = ChatListSearchItemHeader(type: .messages(location: nil), theme: presentationData.theme, strings: presentationData.strings, actionTitle: actionTitle, action: { sourceNode in
|
||||||
openMessagesFilter(sourceNode)
|
openMessagesFilter(sourceNode)
|
||||||
})
|
})
|
||||||
return ChatListItem(presentationData: presentationData, context: context, chatListLocation: location, filterData: nil, index: EngineChatList.Item.Index.chatList(ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Cloud, id: 0), timestamp: 0))), content: .loading, editing: false, hasActiveRevealControls: false, selected: false, header: header, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
return ChatListItem(presentationData: presentationData, context: context, chatListLocation: location, filterData: nil, index: EngineChatList.Item.Index.chatList(ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Cloud, id: 0), timestamp: 0))), content: .loading, editing: false, hasActiveRevealControls: false, selected: false, header: header, enabledContextActions: nil, hiddenOffset: false, interaction: interaction)
|
||||||
case let .emptyMessagesFooter(presentationData, searchScope, searchQuery):
|
case let .emptyMessagesFooter(presentationData, searchScope, searchQuery):
|
||||||
var actionTitle: String?
|
var actionTitle: String?
|
||||||
let filterTitle: String
|
let filterTitle: String
|
||||||
@ -5426,7 +5426,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
requiresPremiumForMessaging: false,
|
requiresPremiumForMessaging: false,
|
||||||
displayAsTopicList: false,
|
displayAsTopicList: false,
|
||||||
tags: []
|
tags: []
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enabledContextActions: nil, hiddenOffset: false, interaction: interaction)
|
||||||
case .media:
|
case .media:
|
||||||
return nil
|
return nil
|
||||||
case .links:
|
case .links:
|
||||||
|
@ -219,7 +219,7 @@ public final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
requiresPremiumForMessaging: false,
|
requiresPremiumForMessaging: false,
|
||||||
displayAsTopicList: false,
|
displayAsTopicList: false,
|
||||||
tags: []
|
tags: []
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enabledContextActions: nil, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemNodes: [ChatListItemNode] = []
|
var itemNodes: [ChatListItemNode] = []
|
||||||
|
@ -453,6 +453,22 @@ private final class ChatListItemTagListComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
||||||
|
public enum EnabledContextActions {
|
||||||
|
public struct Actions: OptionSet {
|
||||||
|
public var rawValue: Int32
|
||||||
|
|
||||||
|
public init(rawValue: Int32) {
|
||||||
|
self.rawValue = rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static let toggleUnread = Actions(rawValue: 1 << 0)
|
||||||
|
public static let delete = Actions(rawValue: 1 << 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
case custom(Actions)
|
||||||
|
case auto
|
||||||
|
}
|
||||||
|
|
||||||
let presentationData: ChatListPresentationData
|
let presentationData: ChatListPresentationData
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let chatListLocation: ChatListControllerLocation
|
let chatListLocation: ChatListControllerLocation
|
||||||
@ -462,7 +478,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
|||||||
let editing: Bool
|
let editing: Bool
|
||||||
let hasActiveRevealControls: Bool
|
let hasActiveRevealControls: Bool
|
||||||
let selected: Bool
|
let selected: Bool
|
||||||
let enableContextActions: Bool
|
let enabledContextActions: EnabledContextActions?
|
||||||
let hiddenOffset: Bool
|
let hiddenOffset: Bool
|
||||||
let interaction: ChatListNodeInteraction
|
let interaction: ChatListNodeInteraction
|
||||||
|
|
||||||
@ -487,7 +503,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(presentationData: ChatListPresentationData, context: AccountContext, chatListLocation: ChatListControllerLocation, filterData: ChatListItemFilterData?, index: EngineChatList.Item.Index, content: ChatListItemContent, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, header: ListViewItemHeader?, enableContextActions: Bool, hiddenOffset: Bool, interaction: ChatListNodeInteraction) {
|
public init(presentationData: ChatListPresentationData, context: AccountContext, chatListLocation: ChatListControllerLocation, filterData: ChatListItemFilterData?, index: EngineChatList.Item.Index, content: ChatListItemContent, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, header: ListViewItemHeader?, enabledContextActions: EnabledContextActions?, hiddenOffset: Bool, interaction: ChatListNodeInteraction) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.chatListLocation = chatListLocation
|
self.chatListLocation = chatListLocation
|
||||||
self.filterData = filterData
|
self.filterData = filterData
|
||||||
@ -498,7 +514,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
|||||||
self.hasActiveRevealControls = hasActiveRevealControls
|
self.hasActiveRevealControls = hasActiveRevealControls
|
||||||
self.selected = selected
|
self.selected = selected
|
||||||
self.header = header
|
self.header = header
|
||||||
self.enableContextActions = enableContextActions
|
self.enabledContextActions = enabledContextActions
|
||||||
self.hiddenOffset = hiddenOffset
|
self.hiddenOffset = hiddenOffset
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
}
|
}
|
||||||
@ -3493,7 +3509,9 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if item.enableContextActions {
|
if let enabledContextActions = item.enabledContextActions {
|
||||||
|
switch enabledContextActions {
|
||||||
|
case .auto:
|
||||||
if case .forum = item.chatListLocation {
|
if case .forum = item.chatListLocation {
|
||||||
if case let .chat(itemPeer) = contentPeer, case let .channel(channel) = itemPeer.peer {
|
if case let .chat(itemPeer) = contentPeer, case let .channel(channel) = itemPeer.peer {
|
||||||
var canOpenClose = false
|
var canOpenClose = false
|
||||||
@ -3545,6 +3563,21 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
peerRevealOptions = []
|
peerRevealOptions = []
|
||||||
peerLeftRevealOptions = []
|
peerLeftRevealOptions = []
|
||||||
}
|
}
|
||||||
|
case let .custom(actions):
|
||||||
|
peerRevealOptions = []
|
||||||
|
peerLeftRevealOptions = []
|
||||||
|
|
||||||
|
if actions.contains(.toggleUnread) {
|
||||||
|
if unreadCount.unread {
|
||||||
|
peerLeftRevealOptions.append(ItemListRevealOption(key: RevealOptionKey.toggleMarkedUnread.rawValue, title: item.presentationData.strings.DialogList_Read, icon: readIcon, color: item.presentationData.theme.list.itemDisclosureActions.inactive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral1.foregroundColor))
|
||||||
|
} else {
|
||||||
|
peerLeftRevealOptions.append(ItemListRevealOption(key: RevealOptionKey.toggleMarkedUnread.rawValue, title: item.presentationData.strings.DialogList_Unread, icon: unreadIcon, color: item.presentationData.theme.list.itemDisclosureActions.accent.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.accent.foregroundColor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actions.contains(.delete) {
|
||||||
|
peerRevealOptions.append(ItemListRevealOption(key: RevealOptionKey.delete.rawValue, title: item.presentationData.strings.Common_Delete, icon: deleteIcon, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
peerRevealOptions = []
|
peerRevealOptions = []
|
||||||
peerLeftRevealOptions = []
|
peerLeftRevealOptions = []
|
||||||
|
@ -463,7 +463,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
selected: selected,
|
selected: selected,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: true,
|
enabledContextActions: .auto,
|
||||||
hiddenOffset: threadInfo?.isHidden == true && !revealed,
|
hiddenOffset: threadInfo?.isHidden == true && !revealed,
|
||||||
interaction: nodeInteraction
|
interaction: nodeInteraction
|
||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
@ -709,7 +709,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: true,
|
enabledContextActions: .auto,
|
||||||
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
||||||
interaction: nodeInteraction
|
interaction: nodeInteraction
|
||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
@ -862,7 +862,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
selected: selected,
|
selected: selected,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: true,
|
enabledContextActions: .auto,
|
||||||
hiddenOffset: threadInfo?.isHidden == true && !revealed,
|
hiddenOffset: threadInfo?.isHidden == true && !revealed,
|
||||||
interaction: nodeInteraction
|
interaction: nodeInteraction
|
||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
@ -1059,7 +1059,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: true,
|
enabledContextActions: .auto,
|
||||||
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
||||||
interaction: nodeInteraction
|
interaction: nodeInteraction
|
||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
|
@ -362,13 +362,24 @@ public func chatListViewForLocation(chatListLocation: ChatListControllerLocation
|
|||||||
|
|
||||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: item.index.id.namespace, id: item.index.id.id), timestamp: item.index.timestamp)
|
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: item.index.id.namespace, id: item.index.id.id), timestamp: item.index.timestamp)
|
||||||
|
|
||||||
|
let readCounters = EnginePeerReadCounters(state: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: Int32(item.unreadCount), markedUnread: item.markedUnread))]), isMuted: false)
|
||||||
|
|
||||||
|
var itemDraft: EngineChatList.Draft?
|
||||||
|
if let embeddedState = item.embeddedInterfaceState, let _ = embeddedState.overrideChatTimestamp {
|
||||||
|
if let opaqueState = _internal_decodeStoredChatInterfaceState(state: embeddedState) {
|
||||||
|
if let text = opaqueState.synchronizeableInputState?.text {
|
||||||
|
itemDraft = EngineChatList.Draft(text: text, entities: opaqueState.synchronizeableInputState?.entities ?? [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
items.append(EngineChatList.Item(
|
items.append(EngineChatList.Item(
|
||||||
id: .chatList(sourceId),
|
id: .chatList(sourceId),
|
||||||
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
||||||
messages: messages,
|
messages: messages,
|
||||||
readCounters: nil,
|
readCounters: readCounters,
|
||||||
isMuted: false,
|
isMuted: false,
|
||||||
draft: sourceId == accountPeerId ? draft : nil,
|
draft: sourceId == accountPeerId ? draft : itemDraft,
|
||||||
threadData: nil,
|
threadData: nil,
|
||||||
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
||||||
presence: nil,
|
presence: nil,
|
||||||
|
@ -8,6 +8,8 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
let index: MessageIndex
|
let index: MessageIndex
|
||||||
let topMessage: Message?
|
let topMessage: Message?
|
||||||
let unreadCount: Int
|
let unreadCount: Int
|
||||||
|
let markedUnread: Bool
|
||||||
|
let embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
id: Int64,
|
id: Int64,
|
||||||
@ -15,7 +17,9 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
pinnedIndex: Int?,
|
pinnedIndex: Int?,
|
||||||
index: MessageIndex,
|
index: MessageIndex,
|
||||||
topMessage: Message?,
|
topMessage: Message?,
|
||||||
unreadCount: Int
|
unreadCount: Int,
|
||||||
|
markedUnread: Bool,
|
||||||
|
embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
@ -23,6 +27,8 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
self.index = index
|
self.index = index
|
||||||
self.topMessage = topMessage
|
self.topMessage = topMessage
|
||||||
self.unreadCount = unreadCount
|
self.unreadCount = unreadCount
|
||||||
|
self.markedUnread = markedUnread
|
||||||
|
self.embeddedInterfaceState = embeddedInterfaceState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,13 +71,17 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
pinnedIndex = index
|
pinnedIndex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let embeddedInterfaceState = postbox.peerChatThreadInterfaceStateTable.get(PeerChatThreadId(peerId: self.peerId, threadId: item.threadId))
|
||||||
|
|
||||||
self.items.append(Item(
|
self.items.append(Item(
|
||||||
id: item.threadId,
|
id: item.threadId,
|
||||||
peer: postbox.peerTable.get(PeerId(item.threadId)),
|
peer: postbox.peerTable.get(PeerId(item.threadId)),
|
||||||
pinnedIndex: pinnedIndex,
|
pinnedIndex: pinnedIndex,
|
||||||
index: item.index,
|
index: item.index,
|
||||||
topMessage: postbox.getMessage(item.index.id),
|
topMessage: postbox.getMessage(item.index.id),
|
||||||
unreadCount: Int(item.info.summary.totalUnreadCount)
|
unreadCount: Int(item.info.summary.totalUnreadCount),
|
||||||
|
markedUnread: item.info.summary.isMarkedUnread,
|
||||||
|
embeddedInterfaceState: embeddedInterfaceState
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +135,8 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
public let index: MessageIndex
|
public let index: MessageIndex
|
||||||
public let topMessage: Message?
|
public let topMessage: Message?
|
||||||
public let unreadCount: Int
|
public let unreadCount: Int
|
||||||
|
public let markedUnread: Bool
|
||||||
|
public let embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
id: Int64,
|
id: Int64,
|
||||||
@ -132,7 +144,9 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
pinnedIndex: Int?,
|
pinnedIndex: Int?,
|
||||||
index: MessageIndex,
|
index: MessageIndex,
|
||||||
topMessage: Message?,
|
topMessage: Message?,
|
||||||
unreadCount: Int
|
unreadCount: Int,
|
||||||
|
markedUnread: Bool,
|
||||||
|
embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
@ -140,6 +154,8 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
self.index = index
|
self.index = index
|
||||||
self.topMessage = topMessage
|
self.topMessage = topMessage
|
||||||
self.unreadCount = unreadCount
|
self.unreadCount = unreadCount
|
||||||
|
self.markedUnread = markedUnread
|
||||||
|
self.embeddedInterfaceState = embeddedInterfaceState
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
@ -168,6 +184,12 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
if lhs.unreadCount != rhs.unreadCount {
|
if lhs.unreadCount != rhs.unreadCount {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.markedUnread != rhs.markedUnread {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.embeddedInterfaceState != rhs.embeddedInterfaceState {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -190,7 +212,9 @@ public final class MessageHistorySavedMessagesIndexView: PostboxView {
|
|||||||
pinnedIndex: item.pinnedIndex,
|
pinnedIndex: item.pinnedIndex,
|
||||||
index: item.index,
|
index: item.index,
|
||||||
topMessage: item.topMessage,
|
topMessage: item.topMessage,
|
||||||
unreadCount: item.unreadCount
|
unreadCount: item.unreadCount,
|
||||||
|
markedUnread: item.markedUnread,
|
||||||
|
embeddedInterfaceState: item.embeddedInterfaceState
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
self.items = items
|
self.items = items
|
||||||
|
@ -3,20 +3,24 @@ import Foundation
|
|||||||
public struct StoredMessageHistoryThreadInfo: Equatable, PostboxCoding {
|
public struct StoredMessageHistoryThreadInfo: Equatable, PostboxCoding {
|
||||||
public struct Summary: Equatable, PostboxCoding {
|
public struct Summary: Equatable, PostboxCoding {
|
||||||
public var totalUnreadCount: Int32
|
public var totalUnreadCount: Int32
|
||||||
|
public var isMarkedUnread: Bool
|
||||||
public var mutedUntil: Int32?
|
public var mutedUntil: Int32?
|
||||||
|
|
||||||
public init(totalUnreadCount: Int32, mutedUntil: Int32?) {
|
public init(totalUnreadCount: Int32, isMarkedUnread: Bool, mutedUntil: Int32?) {
|
||||||
self.totalUnreadCount = totalUnreadCount
|
self.totalUnreadCount = totalUnreadCount
|
||||||
|
self.isMarkedUnread = isMarkedUnread
|
||||||
self.mutedUntil = mutedUntil
|
self.mutedUntil = mutedUntil
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
self.totalUnreadCount = decoder.decodeInt32ForKey("u", orElse: 0)
|
self.totalUnreadCount = decoder.decodeInt32ForKey("u", orElse: 0)
|
||||||
self.mutedUntil = decoder.decodeOptionalInt32ForKey("m")
|
self.mutedUntil = decoder.decodeOptionalInt32ForKey("m")
|
||||||
|
self.isMarkedUnread = decoder.decodeBoolForKey("mu", orElse: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
encoder.encodeInt32(self.totalUnreadCount, forKey: "u")
|
encoder.encodeInt32(self.totalUnreadCount, forKey: "u")
|
||||||
|
encoder.encodeBool(self.isMarkedUnread, forKey: "mu")
|
||||||
if let mutedUntil = self.mutedUntil {
|
if let mutedUntil = self.mutedUntil {
|
||||||
encoder.encodeInt32(mutedUntil, forKey: "m")
|
encoder.encodeInt32(mutedUntil, forKey: "m")
|
||||||
} else {
|
} else {
|
||||||
|
@ -312,7 +312,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: interaction
|
interaction: interaction
|
||||||
)
|
)
|
||||||
|
@ -459,7 +459,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: interaction
|
interaction: interaction
|
||||||
)
|
)
|
||||||
|
@ -5364,15 +5364,16 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func deleteSavedHistory(flags: Int32, peer: Api.InputPeer, maxId: Int32, minDate: Int32?, maxDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.AffectedHistory>) {
|
static func deleteSavedHistory(flags: Int32, parentPeer: Api.InputPeer?, peer: Api.InputPeer, maxId: Int32, minDate: Int32?, maxDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.AffectedHistory>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1855459371)
|
buffer.appendInt32(1304758367)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
if Int(flags) & Int(1 << 0) != 0 {parentPeer!.serialize(buffer, true)}
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
serializeInt32(maxId, buffer: buffer, boxed: false)
|
serializeInt32(maxId, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(minDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(minDate!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(maxDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(maxDate!, buffer: buffer, boxed: false)}
|
||||||
return (FunctionDescription(name: "messages.deleteSavedHistory", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in
|
return (FunctionDescription(name: "messages.deleteSavedHistory", parameters: [("flags", String(describing: flags)), ("parentPeer", String(describing: parentPeer)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.messages.AffectedHistory?
|
var result: Api.messages.AffectedHistory?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -73,7 +73,7 @@ enum AccountStateMutationOperation {
|
|||||||
case ReadOutbox(MessageId, Int32?)
|
case ReadOutbox(MessageId, Int32?)
|
||||||
case ResetReadState(peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, maxOutgoingReadId: MessageId.Id, maxKnownId: MessageId.Id, count: Int32, markedUnread: Bool?)
|
case ResetReadState(peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, maxOutgoingReadId: MessageId.Id, maxKnownId: MessageId.Id, count: Int32, markedUnread: Bool?)
|
||||||
case ResetIncomingReadState(groupId: PeerGroupId, peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, count: Int32, pts: Int32)
|
case ResetIncomingReadState(groupId: PeerGroupId, peerId: PeerId, namespace: MessageId.Namespace, maxIncomingReadId: MessageId.Id, count: Int32, pts: Int32)
|
||||||
case UpdatePeerChatUnreadMark(PeerId, MessageId.Namespace, Bool)
|
case UpdatePeerChatUnreadMark(PeerId, Int64?, MessageId.Namespace, Bool)
|
||||||
case ResetMessageTagSummary(PeerId, MessageTags, MessageId.Namespace, Int32, MessageHistoryTagNamespaceCountValidityRange)
|
case ResetMessageTagSummary(PeerId, MessageTags, MessageId.Namespace, Int32, MessageHistoryTagNamespaceCountValidityRange)
|
||||||
case ReadGroupFeedInbox(PeerGroupId, MessageIndex)
|
case ReadGroupFeedInbox(PeerGroupId, MessageIndex)
|
||||||
case UpdateState(AuthorizedAccountState.State)
|
case UpdateState(AuthorizedAccountState.State)
|
||||||
@ -424,8 +424,8 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.ResetIncomingReadState(groupId: groupId, peerId: peerId, namespace: namespace, maxIncomingReadId: maxIncomingReadId, count: count, pts: pts))
|
self.addOperation(.ResetIncomingReadState(groupId: groupId, peerId: peerId, namespace: namespace, maxIncomingReadId: maxIncomingReadId, count: count, pts: pts))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func updatePeerChatUnreadMark(_ peerId: PeerId, namespace: MessageId.Namespace, value: Bool) {
|
mutating func updatePeerChatUnreadMark(_ peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, value: Bool) {
|
||||||
self.addOperation(.UpdatePeerChatUnreadMark(peerId, namespace, value))
|
self.addOperation(.UpdatePeerChatUnreadMark(peerId, threadId, namespace, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func resetMessageTagSummary(_ peerId: PeerId, tag: MessageTags, namespace: MessageId.Namespace, count: Int32, range: MessageHistoryTagNamespaceCountValidityRange) {
|
mutating func resetMessageTagSummary(_ peerId: PeerId, tag: MessageTags, namespace: MessageId.Namespace, count: Int32, range: MessageHistoryTagNamespaceCountValidityRange) {
|
||||||
|
@ -67,6 +67,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
case isClosed
|
case isClosed
|
||||||
case isHidden
|
case isHidden
|
||||||
case notificationSettings
|
case notificationSettings
|
||||||
|
case isMarkedUnread
|
||||||
}
|
}
|
||||||
|
|
||||||
public var creationDate: Int32
|
public var creationDate: Int32
|
||||||
@ -74,6 +75,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
public var author: PeerId
|
public var author: PeerId
|
||||||
public var info: EngineMessageHistoryThread.Info
|
public var info: EngineMessageHistoryThread.Info
|
||||||
public var incomingUnreadCount: Int32
|
public var incomingUnreadCount: Int32
|
||||||
|
public var isMarkedUnread: Bool
|
||||||
public var maxIncomingReadId: Int32
|
public var maxIncomingReadId: Int32
|
||||||
public var maxKnownMessageId: Int32
|
public var maxKnownMessageId: Int32
|
||||||
public var maxOutgoingReadId: Int32
|
public var maxOutgoingReadId: Int32
|
||||||
@ -87,6 +89,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
author: PeerId,
|
author: PeerId,
|
||||||
info: EngineMessageHistoryThread.Info,
|
info: EngineMessageHistoryThread.Info,
|
||||||
incomingUnreadCount: Int32,
|
incomingUnreadCount: Int32,
|
||||||
|
isMarkedUnread: Bool,
|
||||||
maxIncomingReadId: Int32,
|
maxIncomingReadId: Int32,
|
||||||
maxKnownMessageId: Int32,
|
maxKnownMessageId: Int32,
|
||||||
maxOutgoingReadId: Int32,
|
maxOutgoingReadId: Int32,
|
||||||
@ -99,6 +102,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
self.author = author
|
self.author = author
|
||||||
self.info = info
|
self.info = info
|
||||||
self.incomingUnreadCount = incomingUnreadCount
|
self.incomingUnreadCount = incomingUnreadCount
|
||||||
|
self.isMarkedUnread = isMarkedUnread
|
||||||
self.maxIncomingReadId = maxIncomingReadId
|
self.maxIncomingReadId = maxIncomingReadId
|
||||||
self.maxKnownMessageId = maxKnownMessageId
|
self.maxKnownMessageId = maxKnownMessageId
|
||||||
self.maxOutgoingReadId = maxOutgoingReadId
|
self.maxOutgoingReadId = maxOutgoingReadId
|
||||||
@ -115,6 +119,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
self.author = try container.decode(PeerId.self, forKey: .author)
|
self.author = try container.decode(PeerId.self, forKey: .author)
|
||||||
self.info = try container.decode(EngineMessageHistoryThread.Info.self, forKey: .info)
|
self.info = try container.decode(EngineMessageHistoryThread.Info.self, forKey: .info)
|
||||||
self.incomingUnreadCount = try container.decode(Int32.self, forKey: .incomingUnreadCount)
|
self.incomingUnreadCount = try container.decode(Int32.self, forKey: .incomingUnreadCount)
|
||||||
|
self.isMarkedUnread = try container.decodeIfPresent(Bool.self, forKey: .isMarkedUnread) ?? false
|
||||||
self.maxIncomingReadId = try container.decode(Int32.self, forKey: .maxIncomingReadId)
|
self.maxIncomingReadId = try container.decode(Int32.self, forKey: .maxIncomingReadId)
|
||||||
self.maxKnownMessageId = try container.decode(Int32.self, forKey: .maxKnownMessageId)
|
self.maxKnownMessageId = try container.decode(Int32.self, forKey: .maxKnownMessageId)
|
||||||
self.maxOutgoingReadId = try container.decode(Int32.self, forKey: .maxOutgoingReadId)
|
self.maxOutgoingReadId = try container.decode(Int32.self, forKey: .maxOutgoingReadId)
|
||||||
@ -131,6 +136,7 @@ public struct MessageHistoryThreadData: Codable, Equatable {
|
|||||||
try container.encode(self.author, forKey: .author)
|
try container.encode(self.author, forKey: .author)
|
||||||
try container.encode(self.info, forKey: .info)
|
try container.encode(self.info, forKey: .info)
|
||||||
try container.encode(self.incomingUnreadCount, forKey: .incomingUnreadCount)
|
try container.encode(self.incomingUnreadCount, forKey: .incomingUnreadCount)
|
||||||
|
try container.encode(self.isMarkedUnread, forKey: .isMarkedUnread)
|
||||||
try container.encode(self.maxIncomingReadId, forKey: .maxIncomingReadId)
|
try container.encode(self.maxIncomingReadId, forKey: .maxIncomingReadId)
|
||||||
try container.encode(self.maxKnownMessageId, forKey: .maxKnownMessageId)
|
try container.encode(self.maxKnownMessageId, forKey: .maxKnownMessageId)
|
||||||
try container.encode(self.maxOutgoingReadId, forKey: .maxOutgoingReadId)
|
try container.encode(self.maxOutgoingReadId, forKey: .maxOutgoingReadId)
|
||||||
@ -154,6 +160,7 @@ extension StoredMessageHistoryThreadInfo {
|
|||||||
}
|
}
|
||||||
self.init(data: entry, summary: Summary(
|
self.init(data: entry, summary: Summary(
|
||||||
totalUnreadCount: data.incomingUnreadCount,
|
totalUnreadCount: data.incomingUnreadCount,
|
||||||
|
isMarkedUnread: data.isMarkedUnread,
|
||||||
mutedUntil: mutedUntil
|
mutedUntil: mutedUntil
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -654,6 +661,7 @@ public func _internal_fillSavedMessageHistory(accountPeerId: PeerId, postbox: Po
|
|||||||
author: accountPeerId,
|
author: accountPeerId,
|
||||||
info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0),
|
info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0),
|
||||||
incomingUnreadCount: 0,
|
incomingUnreadCount: 0,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: 0,
|
maxIncomingReadId: 0,
|
||||||
maxKnownMessageId: 0,
|
maxKnownMessageId: 0,
|
||||||
maxOutgoingReadId: 0,
|
maxOutgoingReadId: 0,
|
||||||
@ -771,6 +779,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||||||
iconColor: 0
|
iconColor: 0
|
||||||
),
|
),
|
||||||
incomingUnreadCount: 0,
|
incomingUnreadCount: 0,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: 0,
|
maxIncomingReadId: 0,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: 0,
|
maxOutgoingReadId: 0,
|
||||||
@ -812,7 +821,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||||||
index: topicIndex,
|
index: topicIndex,
|
||||||
threadPeer: threadPeer
|
threadPeer: threadPeer
|
||||||
))
|
))
|
||||||
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
case let .monoForumDialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
let isMarkedUnread = (flags & (1 << 3)) != 0
|
||||||
let data = MessageHistoryThreadData(
|
let data = MessageHistoryThreadData(
|
||||||
creationDate: 0,
|
creationDate: 0,
|
||||||
isOwnedByMe: true,
|
isOwnedByMe: true,
|
||||||
@ -823,6 +833,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||||||
iconColor: 0
|
iconColor: 0
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: isMarkedUnread,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -971,6 +982,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||||||
iconColor: iconColor
|
iconColor: iconColor
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
@ -1224,11 +1224,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
switch peer {
|
switch peer {
|
||||||
case let .dialogPeer(peer):
|
case let .dialogPeer(peer):
|
||||||
let peerId = peer.peerId
|
let peerId = peer.peerId
|
||||||
//TODO:release
|
|
||||||
if let savedPeerId {
|
if let savedPeerId {
|
||||||
|
updatedState.updatePeerChatUnreadMark(peerId, threadId: savedPeerId.peerId.toInt64(), namespace: Namespaces.Message.Cloud, value: (flags & (1 << 0)) != 0)
|
||||||
let _ = savedPeerId
|
let _ = savedPeerId
|
||||||
} else {
|
} else {
|
||||||
updatedState.updatePeerChatUnreadMark(peerId, namespace: Namespaces.Message.Cloud, value: (flags & (1 << 0)) != 0)
|
updatedState.updatePeerChatUnreadMark(peerId, threadId: nil, namespace: Namespaces.Message.Cloud, value: (flags & (1 << 0)) != 0)
|
||||||
}
|
}
|
||||||
case .dialogPeerFolder:
|
case .dialogPeerFolder:
|
||||||
break
|
break
|
||||||
@ -2080,6 +2080,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: iconColor
|
iconColor: iconColor
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -2098,7 +2099,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
}
|
}
|
||||||
case let .savedDialog(savedDialog):
|
case let .savedDialog(savedDialog):
|
||||||
switch savedDialog {
|
switch savedDialog {
|
||||||
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
case let .monoForumDialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
|
||||||
state.operations.append(.ResetForumTopic(
|
state.operations.append(.ResetForumTopic(
|
||||||
topicId: PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64()),
|
topicId: PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64()),
|
||||||
@ -2113,6 +2114,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: 0
|
iconColor: 0
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: (flags & (1 << 3)) != 0,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -2229,6 +2231,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: iconColor
|
iconColor: iconColor
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -2247,7 +2250,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
}
|
}
|
||||||
case let .savedDialog(savedDialog):
|
case let .savedDialog(savedDialog):
|
||||||
switch savedDialog {
|
switch savedDialog {
|
||||||
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
case let .monoForumDialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
let data = MessageHistoryThreadData(
|
let data = MessageHistoryThreadData(
|
||||||
creationDate: 0,
|
creationDate: 0,
|
||||||
isOwnedByMe: true,
|
isOwnedByMe: true,
|
||||||
@ -2258,6 +2261,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: 0
|
iconColor: 0
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: (flags & (1 << 3)) != 0,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -2381,6 +2385,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: iconColor
|
iconColor: iconColor
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: false,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -2397,7 +2402,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
}
|
}
|
||||||
case let .savedDialog(savedDialog):
|
case let .savedDialog(savedDialog):
|
||||||
switch savedDialog {
|
switch savedDialog {
|
||||||
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
case let .monoForumDialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
|
||||||
fetchedChatList.threadInfos[PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64())] = StoreMessageHistoryThreadData(
|
fetchedChatList.threadInfos[PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64())] = StoreMessageHistoryThreadData(
|
||||||
data: MessageHistoryThreadData(
|
data: MessageHistoryThreadData(
|
||||||
@ -2410,6 +2415,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM
|
|||||||
iconColor: 0
|
iconColor: 0
|
||||||
),
|
),
|
||||||
incomingUnreadCount: unreadCount,
|
incomingUnreadCount: unreadCount,
|
||||||
|
isMarkedUnread: (flags & (1 << 3)) != 0,
|
||||||
maxIncomingReadId: readInboxMaxId,
|
maxIncomingReadId: readInboxMaxId,
|
||||||
maxKnownMessageId: topMessage,
|
maxKnownMessageId: topMessage,
|
||||||
maxOutgoingReadId: readOutboxMaxId,
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
@ -4360,8 +4366,17 @@ func replayFinalState(
|
|||||||
transaction.setNeedsIncomingReadStateSynchronization(peerId)
|
transaction.setNeedsIncomingReadStateSynchronization(peerId)
|
||||||
invalidateGroupStats.insert(groupId)
|
invalidateGroupStats.insert(groupId)
|
||||||
}
|
}
|
||||||
case let .UpdatePeerChatUnreadMark(peerId, namespace, value):
|
case let .UpdatePeerChatUnreadMark(peerId, threadId, namespace, value):
|
||||||
|
if let threadId {
|
||||||
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
|
data.isMarkedUnread = value
|
||||||
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
transaction.applyMarkUnread(peerId: peerId, namespace: namespace, value: value, interactive: false)
|
transaction.applyMarkUnread(peerId: peerId, namespace: namespace, value: value, interactive: false)
|
||||||
|
}
|
||||||
case let .ResetMessageTagSummary(peerId, tag, namespace, count, range):
|
case let .ResetMessageTagSummary(peerId, tag, namespace, count, range):
|
||||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: tag, namespace: namespace, customTag: nil, count: count, maxId: range.maxId)
|
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: tag, namespace: namespace, customTag: nil, count: count, maxId: range.maxId)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
|
@ -453,7 +453,7 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|
|||||||
flags |= 1 << 3
|
flags |= 1 << 3
|
||||||
updatedMaxId = 0
|
updatedMaxId = 0
|
||||||
}
|
}
|
||||||
let signal = network.request(Api.functions.messages.deleteSavedHistory(flags: flags, peer: inputSubPeer, maxId: updatedMaxId, minDate: operation.minTimestamp, maxDate: operation.maxTimestamp))
|
let signal = network.request(Api.functions.messages.deleteSavedHistory(flags: flags, parentPeer: nil, peer: inputSubPeer, maxId: updatedMaxId, minDate: operation.minTimestamp, maxDate: operation.maxTimestamp))
|
||||||
|> map { result -> Api.messages.AffectedHistory? in
|
|> map { result -> Api.messages.AffectedHistory? in
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -490,6 +490,52 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|
|||||||
return .complete()
|
return .complete()
|
||||||
} else {
|
} else {
|
||||||
if let threadId = operation.threadId {
|
if let threadId = operation.threadId {
|
||||||
|
if peer.isMonoForum {
|
||||||
|
guard let inputPeer = apiInputPeer(peer) else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
guard let inputSubPeer = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer) else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags: Int32 = 0
|
||||||
|
var updatedMaxId = operation.topMessageId.id
|
||||||
|
if operation.minTimestamp != nil {
|
||||||
|
flags |= 1 << 2
|
||||||
|
updatedMaxId = 0
|
||||||
|
}
|
||||||
|
if operation.maxTimestamp != nil {
|
||||||
|
flags |= 1 << 3
|
||||||
|
updatedMaxId = 0
|
||||||
|
}
|
||||||
|
flags |= 1 << 0
|
||||||
|
let signal = network.request(Api.functions.messages.deleteSavedHistory(flags: flags, parentPeer: inputPeer, peer: inputSubPeer, maxId: updatedMaxId, minDate: operation.minTimestamp, maxDate: operation.maxTimestamp))
|
||||||
|
|> map { result -> Api.messages.AffectedHistory? in
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<Api.messages.AffectedHistory?, Bool> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<Void, Bool> in
|
||||||
|
if let result = result {
|
||||||
|
switch result {
|
||||||
|
case let .affectedHistory(pts, ptsCount, offset):
|
||||||
|
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
|
||||||
|
if offset == 0 {
|
||||||
|
return .fail(true)
|
||||||
|
} else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .fail(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (signal |> restart)
|
||||||
|
|> `catch` { _ -> Signal<Void, NoError> in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return network.request(Api.functions.channels.deleteTopicHistory(channel: inputChannel, topMsgId: Int32(clamping: threadId)))
|
return network.request(Api.functions.channels.deleteTopicHistory(channel: inputChannel, topMsgId: Int32(clamping: threadId)))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.messages.AffectedHistory?, NoError> in
|
|> `catch` { _ -> Signal<Api.messages.AffectedHistory?, NoError> in
|
||||||
@ -500,6 +546,7 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|
|||||||
}
|
}
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
if operation.type == .forEveryone {
|
if operation.type == .forEveryone {
|
||||||
|
@ -190,7 +190,7 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
|||||||
},
|
},
|
||||||
automaticThreadIndexInfo: { peerId, _ in
|
automaticThreadIndexInfo: { peerId, _ in
|
||||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||||
return StoredMessageHistoryThreadInfo(data: CodableEntry(data: Data()), summary: StoredMessageHistoryThreadInfo.Summary(totalUnreadCount: 0, mutedUntil: nil))
|
return StoredMessageHistoryThreadInfo(data: CodableEntry(data: Data()), summary: StoredMessageHistoryThreadInfo.Summary(totalUnreadCount: 0, isMarkedUnread: false, mutedUntil: nil))
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,58 @@ func _internal_togglePeerUnreadMarkInteractively(postbox: Postbox, network: Netw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_toggleForumThreadUnreadMarkInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, peerId: PeerId, threadId: Int64, setToValue: Bool?) {
|
||||||
|
guard let peer = transaction.getPeer(peerId) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let channel = peer as? TelegramChannel, channel.isForumOrMonoForum else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let messageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: peerId, threadId: threadId, namespaces: Set([Namespaces.Message.Cloud])) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let setToValue = setToValue ?? !(data.incomingUnreadCount != 0 || data.isMarkedUnread)
|
||||||
|
|
||||||
|
if setToValue {
|
||||||
|
data.isMarkedUnread = true
|
||||||
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel.flags.contains(.isForum) {
|
||||||
|
} else if channel.flags.contains(.isMonoforum) {
|
||||||
|
if let inputPeer = apiInputPeer(channel), let subPeer = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer) {
|
||||||
|
let _ = network.request(Api.functions.messages.markDialogUnread(flags: 1 << 0, parentPeer: inputPeer, peer: .inputDialogPeer(peer: subPeer))).start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if data.incomingUnreadCount != 0 || data.isMarkedUnread {
|
||||||
|
data.incomingUnreadCount = 0
|
||||||
|
data.isMarkedUnread = false
|
||||||
|
data.maxIncomingReadId = max(messageIndex.id.id, data.maxIncomingReadId)
|
||||||
|
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
||||||
|
|
||||||
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
if channel.flags.contains(.isForum) {
|
||||||
|
if let inputPeer = apiInputPeer(channel) {
|
||||||
|
let _ = network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: threadId), readMaxId: messageIndex.id.id)).start()
|
||||||
|
}
|
||||||
|
} else if channel.flags.contains(.isMonoforum) {
|
||||||
|
if let inputPeer = apiInputPeer(channel), let subPeer = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer) {
|
||||||
|
let _ = network.request(Api.functions.messages.readSavedHistory(parentPeer: inputPeer, peer: subPeer, maxId: messageIndex.id.id)).start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func _internal_markForumThreadAsReadInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, peerId: PeerId, threadId: Int64) {
|
func _internal_markForumThreadAsReadInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, peerId: PeerId, threadId: Int64) {
|
||||||
guard let peer = transaction.getPeer(peerId) else {
|
guard let peer = transaction.getPeer(peerId) else {
|
||||||
return
|
return
|
||||||
@ -130,6 +182,7 @@ func _internal_markForumThreadAsReadInteractively(transaction: Transaction, netw
|
|||||||
}
|
}
|
||||||
if data.incomingUnreadCount != 0 {
|
if data.incomingUnreadCount != 0 {
|
||||||
data.incomingUnreadCount = 0
|
data.incomingUnreadCount = 0
|
||||||
|
data.isMarkedUnread = false
|
||||||
data.maxIncomingReadId = max(messageIndex.id.id, data.maxIncomingReadId)
|
data.maxIncomingReadId = max(messageIndex.id.id, data.maxIncomingReadId)
|
||||||
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
||||||
|
|
||||||
@ -169,6 +222,7 @@ func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, netwo
|
|||||||
}
|
}
|
||||||
if data.incomingUnreadCount != 0 {
|
if data.incomingUnreadCount != 0 {
|
||||||
data.incomingUnreadCount = 0
|
data.incomingUnreadCount = 0
|
||||||
|
data.isMarkedUnread = false
|
||||||
data.maxIncomingReadId = max(messageIndex.id.id, data.maxIncomingReadId)
|
data.maxIncomingReadId = max(messageIndex.id.id, data.maxIncomingReadId)
|
||||||
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
||||||
|
|
||||||
|
@ -740,6 +740,13 @@ public extension TelegramEngine {
|
|||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func togglePeerUnreadMarkInteractively(peerId: EnginePeer.Id, threadId: Int64, setToValue: Bool?) -> Signal<Never, NoError> {
|
||||||
|
return self.account.postbox.transaction { transaction -> Void in
|
||||||
|
_internal_toggleForumThreadUnreadMarkInteractively(transaction: transaction, network: self.account.network, viewTracker: self.account.viewTracker, peerId: peerId, threadId: threadId, setToValue: setToValue)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
|
||||||
public func markForumThreadAsRead(peerId: EnginePeer.Id, threadId: Int64) -> Signal<Never, NoError> {
|
public func markForumThreadAsRead(peerId: EnginePeer.Id, threadId: Int64) -> Signal<Never, NoError> {
|
||||||
return self.account.postbox.transaction { transaction -> Void in
|
return self.account.postbox.transaction { transaction -> Void in
|
||||||
_internal_markForumThreadAsReadInteractively(transaction: transaction, network: self.account.network, viewTracker: self.account.viewTracker, peerId: peerId, threadId: threadId)
|
_internal_markForumThreadAsReadInteractively(transaction: transaction, network: self.account.network, viewTracker: self.account.viewTracker, peerId: peerId, threadId: threadId)
|
||||||
|
@ -277,6 +277,9 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
return self.isReadyPromise.get()
|
return self.isReadyPromise.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var hintDeletedChats = Set<EnginePeer.Id>()
|
||||||
|
private var hintAnimateListTransition: Bool = false
|
||||||
|
|
||||||
override public init(frame: CGRect) {
|
override public init(frame: CGRect) {
|
||||||
self.listNode = ListView()
|
self.listNode = ListView()
|
||||||
|
|
||||||
@ -330,6 +333,34 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func performDeleteAction(peerId: EnginePeer.Id, threadId: Int64?) {
|
||||||
|
guard let component = self.component else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let mainPeerId = component.peerId else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if case .monoforumChats = component.contents {
|
||||||
|
let threadId = threadId ?? peerId.toInt64()
|
||||||
|
|
||||||
|
self.hintDeletedChats.insert(peerId)
|
||||||
|
let _ = component.context.engine.peers.removeForumChannelThread(id: mainPeerId, threadId: threadId).startStandalone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func performToggleUnreadAction(peerId: EnginePeer.Id, threadId: Int64?) {
|
||||||
|
guard let component = self.component else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let mainPeerId = component.peerId, case .monoforumChats = component.contents else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let threadId = threadId ?? peerId.toInt64()
|
||||||
|
|
||||||
|
let _ = component.context.engine.messages.togglePeerUnreadMarkInteractively(peerId: mainPeerId, threadId: threadId, setToValue: nil).startStandalone()
|
||||||
|
}
|
||||||
|
|
||||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
guard let result = super.hitTest(point, with: event) else {
|
guard let result = super.hitTest(point, with: event) else {
|
||||||
return nil
|
return nil
|
||||||
@ -655,9 +686,33 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
|
|
||||||
let contentsId = self.nextContentsId
|
let contentsId = self.nextContentsId
|
||||||
self.nextContentsId += 1
|
self.nextContentsId += 1
|
||||||
|
|
||||||
|
let contentId: ContentsState.ContentId = .search(query)
|
||||||
|
|
||||||
|
if let previousContentsState = self.contentsState, previousContentsState.contentId == contentId {
|
||||||
|
for deletedPeerId in self.hintDeletedChats {
|
||||||
|
if previousContentsState.entries.contains(where: { entry in
|
||||||
|
if case let .chat(id) = entry.id, case .chatList(deletedPeerId) = id {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) && !entries.contains(where: { entry in
|
||||||
|
if case let .chat(id) = entry.id, case .chatList(deletedPeerId) = id {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) {
|
||||||
|
self.hintAnimateListTransition = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.hintDeletedChats.removeAll()
|
||||||
|
|
||||||
self.contentsState = ContentsState(
|
self.contentsState = ContentsState(
|
||||||
id: contentsId,
|
id: contentsId,
|
||||||
contentId: .search(query),
|
contentId: contentId,
|
||||||
entries: entries,
|
entries: entries,
|
||||||
messages: messages,
|
messages: messages,
|
||||||
hasEarlier: false, //!(result?.completed ?? true),
|
hasEarlier: false, //!(result?.completed ?? true),
|
||||||
@ -783,9 +838,17 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
},
|
},
|
||||||
setPeerThreadMuted: { _, _, _ in
|
setPeerThreadMuted: { _, _, _ in
|
||||||
},
|
},
|
||||||
deletePeer: { _, _ in
|
deletePeer: { [weak self] peerId, _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.performDeleteAction(peerId: peerId, threadId: nil)
|
||||||
},
|
},
|
||||||
deletePeerThread: { _, _ in
|
deletePeerThread: { [weak self] peerId, threadId in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.performDeleteAction(peerId: peerId, threadId: nil)
|
||||||
},
|
},
|
||||||
setPeerThreadStopped: { _, _, _ in
|
setPeerThreadStopped: { _, _, _ in
|
||||||
},
|
},
|
||||||
@ -795,7 +858,11 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
},
|
},
|
||||||
updatePeerGrouping: { _, _ in
|
updatePeerGrouping: { _, _ in
|
||||||
},
|
},
|
||||||
togglePeerMarkedUnread: { _, _ in
|
togglePeerMarkedUnread: { [weak self] peerId, _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.performToggleUnreadAction(peerId: peerId, threadId: nil)
|
||||||
},
|
},
|
||||||
toggleArchivedFolderHiddenByDefault: {
|
toggleArchivedFolderHiddenByDefault: {
|
||||||
},
|
},
|
||||||
@ -960,7 +1027,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
return ChatListItem(
|
return ChatListItem(
|
||||||
presentationData: chatListPresentationData,
|
presentationData: chatListPresentationData,
|
||||||
context: component.context,
|
context: component.context,
|
||||||
chatListLocation: component.peerId == component.context.account.peerId ? .savedMessagesChats(peerId: component.context.account.peerId) : .chatList(groupId: .root),
|
chatListLocation: .savedMessagesChats(peerId: component.peerId ?? component.context.account.peerId),
|
||||||
filterData: nil,
|
filterData: nil,
|
||||||
index: .forum(
|
index: .forum(
|
||||||
pinnedIndex: .none,
|
pinnedIndex: .none,
|
||||||
@ -997,7 +1064,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: displayMessagesHeader ? ChatListSearchItemHeader(type: .messages(location: nil), theme: listPresentationData.theme, strings: listPresentationData.strings) : nil,
|
header: displayMessagesHeader ? ChatListSearchItemHeader(type: .messages(location: nil), theme: listPresentationData.theme, strings: listPresentationData.strings) : nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
@ -1012,12 +1079,12 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
messages: item.messages,
|
messages: item.messages,
|
||||||
peer: item.renderedPeer,
|
peer: item.renderedPeer,
|
||||||
threadInfo: nil,
|
threadInfo: nil,
|
||||||
combinedReadState: nil,
|
combinedReadState: item.readCounters,
|
||||||
isRemovedFromTotalUnreadCount: false,
|
isRemovedFromTotalUnreadCount: false,
|
||||||
presence: nil,
|
presence: nil,
|
||||||
hasUnseenMentions: false,
|
hasUnseenMentions: false,
|
||||||
hasUnseenReactions: false,
|
hasUnseenReactions: false,
|
||||||
draftState: nil,
|
draftState: item.draft.flatMap(ChatListItemContent.DraftState.init(draft:)),
|
||||||
mediaDraftContentType: nil,
|
mediaDraftContentType: nil,
|
||||||
inputActivities: nil,
|
inputActivities: nil,
|
||||||
promoInfo: nil,
|
promoInfo: nil,
|
||||||
@ -1036,7 +1103,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: .custom([.toggleUnread, .delete]),
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
@ -1044,6 +1111,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var scrollToItem: ListViewScrollToItem?
|
var scrollToItem: ListViewScrollToItem?
|
||||||
|
var listTransactionOptions: ListViewDeleteAndInsertOptions = [.Synchronous, .LowLatency, .PreferSynchronousDrawing, .PreferSynchronousResourceLoading]
|
||||||
if previousContentsState?.contentId != contentsState.contentId && !contentsState.entries.isEmpty {
|
if previousContentsState?.contentId != contentsState.contentId && !contentsState.entries.isEmpty {
|
||||||
scrollToItem = ListViewScrollToItem(
|
scrollToItem = ListViewScrollToItem(
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -1054,6 +1122,11 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if previousContentsState?.contentId == contentsState.contentId && self.hintAnimateListTransition {
|
||||||
|
listTransactionOptions.insert(.AnimateInsertion)
|
||||||
|
}
|
||||||
|
self.hintAnimateListTransition = false
|
||||||
|
|
||||||
self.listNode.transaction(
|
self.listNode.transaction(
|
||||||
deleteIndices: deleteIndices.map { index in
|
deleteIndices: deleteIndices.map { index in
|
||||||
return ListViewDeleteItem(index: index, directionHint: nil)
|
return ListViewDeleteItem(index: index, directionHint: nil)
|
||||||
@ -1075,7 +1148,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
directionHint: nil
|
directionHint: nil
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
options: [.Synchronous, .LowLatency, .PreferSynchronousDrawing, .PreferSynchronousResourceLoading],
|
options: listTransactionOptions,
|
||||||
scrollToItem: scrollToItem,
|
scrollToItem: scrollToItem,
|
||||||
updateSizeAndInsets: nil,
|
updateSizeAndInsets: nil,
|
||||||
updateOpaqueState: contentsState.id
|
updateOpaqueState: contentsState.id
|
||||||
|
@ -1713,7 +1713,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
}
|
}
|
||||||
} else if item.message.id.peerId.isRepliesOrVerificationCodes {
|
} else if item.message.id.peerId.isRepliesOrVerificationCodes {
|
||||||
needsShareButton = false
|
needsShareButton = false
|
||||||
} else if let channel = item.content.firstMessage.peers[item.content.firstMessage.id.peerId] as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = item.content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, case .peer = item.chatLocation {
|
} else if let channel = item.content.firstMessage.peers[item.content.firstMessage.id.peerId] as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = item.content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething), case .peer = item.chatLocation {
|
||||||
if incoming {
|
if incoming {
|
||||||
needsShareButton = true
|
needsShareButton = true
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if channel.isMonoForum {
|
if channel.isMonoForum {
|
||||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
headerSeparableThreadId = content.firstMessage.threadId
|
headerSeparableThreadId = content.firstMessage.threadId
|
||||||
|
|
||||||
if let threadId = content.firstMessage.threadId, let peer = content.firstMessage.peers[EnginePeer.Id(threadId)] {
|
if let threadId = content.firstMessage.threadId, let peer = content.firstMessage.peers[EnginePeer.Id(threadId)] {
|
||||||
|
@ -138,11 +138,16 @@ final class ChatMessageNotificationItemNode: NotificationItemNode {
|
|||||||
authorString = EnginePeer(author).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
authorString = EnginePeer(author).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
} else {
|
||||||
if let threadData = item.threadData {
|
if let threadData = item.threadData {
|
||||||
title = "\(authorString) → \(threadData.info.title)"
|
title = "\(authorString) → \(threadData.info.title)"
|
||||||
} else {
|
} else {
|
||||||
title = authorString + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
title = authorString + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
title = peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
title = peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder)
|
||||||
for attribute in firstMessage.attributes {
|
for attribute in firstMessage.attributes {
|
||||||
|
@ -244,7 +244,7 @@ public final class LoadingOverlayNode: ASDisplayNode {
|
|||||||
requiresPremiumForMessaging: false,
|
requiresPremiumForMessaging: false,
|
||||||
displayAsTopicList: false,
|
displayAsTopicList: false,
|
||||||
tags: []
|
tags: []
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enabledContextActions: nil, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemNodes: [ChatListItemNode] = []
|
var itemNodes: [ChatListItemNode] = []
|
||||||
@ -616,7 +616,7 @@ private final class PeerInfoScreenPersonalChannelItemNode: PeerInfoScreenItemNod
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
|
@ -264,7 +264,7 @@ final class GreetingMessageListItemComponent: Component {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
|
@ -294,7 +294,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: isSelected,
|
selected: isSelected,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: true,
|
enabledContextActions: .auto,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
|
@ -954,7 +954,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: interaction
|
interaction: interaction
|
||||||
)
|
)
|
||||||
|
@ -4761,7 +4761,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let defaultDirection: ChatControllerAnimateInnerChatSwitchDirection? = self.chatDisplayNode.chatLocationTabSwitchDirection(from: self.chatLocation.threadId, to: self.presentationInterfaceState.chatLocation.threadId).flatMap { direction -> ChatControllerAnimateInnerChatSwitchDirection in
|
let defaultDirection: ChatControllerAnimateInnerChatSwitchDirection? = self.chatDisplayNode.chatLocationTabSwitchDirection(from: self.chatLocation.threadId, to: threadId).flatMap { direction -> ChatControllerAnimateInnerChatSwitchDirection in
|
||||||
return direction ? .right : .left
|
return direction ? .right : .left
|
||||||
}
|
}
|
||||||
self.updateChatLocationThread(threadId: threadId, animationDirection: animationDirection ?? defaultDirection)
|
self.updateChatLocationThread(threadId: threadId, animationDirection: animationDirection ?? defaultDirection)
|
||||||
@ -7835,7 +7835,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum {
|
if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum {
|
||||||
attributes.removeAll(where: { $0 is SendAsMessageAttribute })
|
attributes.removeAll(where: { $0 is SendAsMessageAttribute })
|
||||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.presentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, let sendAsPeerId = self.presentationInterfaceState.currentSendAsPeerId {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.presentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething), let sendAsPeerId = self.presentationInterfaceState.currentSendAsPeerId {
|
||||||
attributes.append(SendAsMessageAttribute(peerId: sendAsPeerId))
|
attributes.append(SendAsMessageAttribute(peerId: sendAsPeerId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -866,7 +866,7 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
} else if let cachedChannelData = peerView.cachedData as? CachedChannelData {
|
} else if let cachedChannelData = peerView.cachedData as? CachedChannelData {
|
||||||
if let channel = peer as? TelegramChannel, channel.isMonoForum {
|
if let channel = peer as? TelegramChannel, channel.isMonoForum {
|
||||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = peerView.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = peerView.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
currentSendAsPeerId = channel.linkedMonoforumId
|
currentSendAsPeerId = channel.linkedMonoforumId
|
||||||
} else {
|
} else {
|
||||||
currentSendAsPeerId = nil
|
currentSendAsPeerId = nil
|
||||||
@ -1365,12 +1365,19 @@ extension ChatControllerImpl {
|
|||||||
contactStatus = ChatContactStatus(canAddContact: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy, managingBot: managingBot)
|
contactStatus = ChatContactStatus(canAddContact: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: invitedBy, managingBot: managingBot)
|
||||||
|
|
||||||
if let channel = peerView.peers[peerView.peerId] as? TelegramChannel {
|
if let channel = peerView.peers[peerView.peerId] as? TelegramChannel {
|
||||||
|
if channel.isMonoForum {
|
||||||
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = peerView.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
|
} else {
|
||||||
|
sendPaidMessageStars = channel.sendPaidMessageStars
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
|
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
|
||||||
} else {
|
} else {
|
||||||
sendPaidMessageStars = channel.sendPaidMessageStars
|
sendPaidMessageStars = channel.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var peers = SimpleDictionary<PeerId, Peer>()
|
var peers = SimpleDictionary<PeerId, Peer>()
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
@ -1524,7 +1531,7 @@ extension ChatControllerImpl {
|
|||||||
var currentSendAsPeerId: PeerId?
|
var currentSendAsPeerId: PeerId?
|
||||||
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
if let peer = peerView.peers[peerView.peerId] as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData {
|
||||||
if peer.isMonoForum {
|
if peer.isMonoForum {
|
||||||
if let linkedMonoforumId = peer.linkedMonoforumId, let mainChannel = peerView.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
if let linkedMonoforumId = peer.linkedMonoforumId, let mainChannel = peerView.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
currentSendAsPeerId = peer.linkedMonoforumId
|
currentSendAsPeerId = peer.linkedMonoforumId
|
||||||
} else {
|
} else {
|
||||||
currentSendAsPeerId = nil
|
currentSendAsPeerId = nil
|
||||||
|
@ -2999,12 +2999,20 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
displayInlineSearch = true
|
displayInlineSearch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.chatLocation.threadId == nil, let channel = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
if self.chatLocation.threadId == nil, let channel = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
if self.chatPresentationInterfaceState.search != nil {
|
if self.chatPresentationInterfaceState.search != nil {
|
||||||
displayInlineSearch = true
|
displayInlineSearch = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var showNavigateButtons = true
|
||||||
|
if let _ = chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState {
|
||||||
|
showNavigateButtons = false
|
||||||
|
}
|
||||||
|
if chatPresentationInterfaceState.displayHistoryFilterAsList {
|
||||||
|
showNavigateButtons = false
|
||||||
|
}
|
||||||
|
|
||||||
if displayInlineSearch {
|
if displayInlineSearch {
|
||||||
let peerId = self.chatPresentationInterfaceState.chatLocation.peerId
|
let peerId = self.chatPresentationInterfaceState.chatLocation.peerId
|
||||||
|
|
||||||
@ -3029,7 +3037,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
} else {
|
} else {
|
||||||
mappedContents = .empty
|
mappedContents = .empty
|
||||||
}
|
}
|
||||||
} else if self.chatLocation.threadId == nil, let channel = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
} else if self.chatLocation.threadId == nil, let channel = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
mappedContents = .monoforumChats(query: self.chatPresentationInterfaceState.search?.query ?? "")
|
mappedContents = .monoforumChats(query: self.chatPresentationInterfaceState.search?.query ?? "")
|
||||||
} else if case .peer(self.context.account.peerId) = self.chatPresentationInterfaceState.chatLocation {
|
} else if case .peer(self.context.account.peerId) = self.chatPresentationInterfaceState.chatLocation {
|
||||||
mappedContents = .tag(MemoryBuffer())
|
mappedContents = .tag(MemoryBuffer())
|
||||||
@ -3037,6 +3045,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
mappedContents = .empty
|
mappedContents = .empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if case .empty = mappedContents {
|
||||||
|
} else {
|
||||||
|
showNavigateButtons = false
|
||||||
|
}
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let chatLocation = self.chatLocation
|
let chatLocation = self.chatLocation
|
||||||
|
|
||||||
@ -3148,7 +3161,12 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
self.controller?.alwaysShowSearchResultsAsList = false
|
self.controller?.alwaysShowSearchResultsAsList = false
|
||||||
self.alwaysShowSearchResultsAsList = false
|
self.alwaysShowSearchResultsAsList = false
|
||||||
self.controller?.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
|
self.controller?.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
|
||||||
return state.updatedDisplayHistoryFilterAsList(false)
|
var state = state
|
||||||
|
state = state.updatedDisplayHistoryFilterAsList(false)
|
||||||
|
if let channel = state.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
|
state = state.updatedSearch(nil)
|
||||||
|
}
|
||||||
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3270,26 +3288,13 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: peerId)
|
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: peerId)
|
||||||
let interfaceStateKey: PostboxViewKey = .chatInterfaceState(peerId: peerId)
|
|
||||||
|
|
||||||
let accountPeerId = self.context.account.peerId
|
let threadListSignal: Signal<EngineChatList?, NoError> = self.context.account.postbox.combinedView(keys: [viewKey])
|
||||||
let threadListSignal: Signal<EngineChatList?, NoError> = self.context.account.postbox.combinedView(keys: [viewKey, interfaceStateKey])
|
|
||||||
|> map { views -> EngineChatList? in
|
|> map { views -> EngineChatList? in
|
||||||
guard let view = views.views[viewKey] as? MessageHistorySavedMessagesIndexView else {
|
guard let view = views.views[viewKey] as? MessageHistorySavedMessagesIndexView else {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
var draft: EngineChatList.Draft?
|
|
||||||
if let interfaceStateView = views.views[interfaceStateKey] as? ChatInterfaceStateView {
|
|
||||||
if let embeddedState = interfaceStateView.value, let _ = embeddedState.overrideChatTimestamp {
|
|
||||||
if let opaqueState = _internal_decodeStoredChatInterfaceState(state: embeddedState) {
|
|
||||||
if let text = opaqueState.synchronizeableInputState?.text {
|
|
||||||
draft = EngineChatList.Draft(text: text, entities: opaqueState.synchronizeableInputState?.entities ?? [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var items: [EngineChatList.Item] = []
|
var items: [EngineChatList.Item] = []
|
||||||
for item in view.items {
|
for item in view.items {
|
||||||
guard let sourcePeer = item.peer else {
|
guard let sourcePeer = item.peer else {
|
||||||
@ -3310,9 +3315,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
||||||
messages: messages,
|
messages: messages,
|
||||||
readCounters: EnginePeerReadCounters(
|
readCounters: EnginePeerReadCounters(
|
||||||
incomingReadId: 0, outgoingReadId: 0, count: Int32(item.unreadCount), markedUnread: false),
|
incomingReadId: 0, outgoingReadId: 0, count: Int32(item.unreadCount), markedUnread: item.markedUnread),
|
||||||
isMuted: false,
|
isMuted: false,
|
||||||
draft: sourceId == accountPeerId ? draft : nil,
|
draft: nil,
|
||||||
threadData: nil,
|
threadData: nil,
|
||||||
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
||||||
presence: nil,
|
presence: nil,
|
||||||
@ -3466,6 +3471,8 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
transition.updateAlpha(node: self.backgroundNode, alpha: 1.0)
|
transition.updateAlpha(node: self.backgroundNode, alpha: 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transition.updateAlpha(node: self.navigateButtons, alpha: showNavigateButtons ? 1.0 : 0.0)
|
||||||
|
|
||||||
let listBottomInset = self.historyNode.insets.top
|
let listBottomInset = self.historyNode.insets.top
|
||||||
if let previousListBottomInset = previousListBottomInset, listBottomInset != previousListBottomInset {
|
if let previousListBottomInset = previousListBottomInset, listBottomInset != previousListBottomInset {
|
||||||
if abs(listBottomInset - previousListBottomInset) > 80.0 {
|
if abs(listBottomInset - previousListBottomInset) > 80.0 {
|
||||||
@ -3694,15 +3701,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
self.emptyNode?.isHidden = false
|
self.emptyNode?.isHidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var showNavigateButtons = true
|
|
||||||
if let _ = chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState {
|
|
||||||
showNavigateButtons = false
|
|
||||||
}
|
|
||||||
if chatPresentationInterfaceState.displayHistoryFilterAsList {
|
|
||||||
showNavigateButtons = false
|
|
||||||
}
|
|
||||||
transition.updateAlpha(node: self.navigateButtons, alpha: showNavigateButtons ? 1.0 : 0.0)
|
|
||||||
|
|
||||||
if let openStickersDisposable = self.openStickersDisposable {
|
if let openStickersDisposable = self.openStickersDisposable {
|
||||||
if case .media = chatPresentationInterfaceState.inputMode {
|
if case .media = chatPresentationInterfaceState.inputMode {
|
||||||
} else {
|
} else {
|
||||||
|
@ -230,7 +230,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
|
|
||||||
if channel.flags.contains(.isMonoforum) {
|
if channel.flags.contains(.isMonoforum) {
|
||||||
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, case .peer = chatPresentationInterfaceState.chatLocation {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething), case .peer = chatPresentationInterfaceState.chatLocation {
|
||||||
if chatPresentationInterfaceState.interfaceState.replyMessageSubject == nil {
|
if chatPresentationInterfaceState.interfaceState.replyMessageSubject == nil {
|
||||||
displayInputTextPanel = false
|
displayInputTextPanel = false
|
||||||
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
||||||
|
@ -230,7 +230,7 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
func titleTopicsPanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, force: Bool) -> ChatTopicListTitleAccessoryPanelNode? {
|
func titleTopicsPanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, force: Bool) -> ChatTopicListTitleAccessoryPanelNode? {
|
||||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, chatPresentationInterfaceState.search == nil {
|
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething), chatPresentationInterfaceState.search == nil {
|
||||||
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
||||||
if case .top = topicListDisplayMode, let peerId = chatPresentationInterfaceState.chatLocation.peerId {
|
if case .top = topicListDisplayMode, let peerId = chatPresentationInterfaceState.chatLocation.peerId {
|
||||||
if let currentPanel = currentPanel as? ChatTopicListTitleAccessoryPanelNode {
|
if let currentPanel = currentPanel as? ChatTopicListTitleAccessoryPanelNode {
|
||||||
@ -262,7 +262,7 @@ func sidePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, chatPresentationInterfaceState.search == nil {
|
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething), chatPresentationInterfaceState.search == nil {
|
||||||
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
||||||
if case .side = topicListDisplayMode {
|
if case .side = topicListDisplayMode {
|
||||||
return AnyComponentWithIdentity(
|
return AnyComponentWithIdentity(
|
||||||
|
@ -118,7 +118,7 @@ private enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: interaction
|
interaction: interaction
|
||||||
)
|
)
|
||||||
|
@ -262,6 +262,10 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode {
|
|||||||
canChangeListMode = true
|
canChangeListMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let channel = params.interfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, params.interfaceState.chatLocation.threadId == nil, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = params.interfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.hasPermission(.sendSomething) {
|
||||||
|
canChangeListMode = false
|
||||||
|
}
|
||||||
|
|
||||||
let height: CGFloat
|
let height: CGFloat
|
||||||
if case .regular = params.metrics.widthClass {
|
if case .regular = params.metrics.widthClass {
|
||||||
height = 49.0
|
height = 49.0
|
||||||
|
@ -249,7 +249,7 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
|||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
header: nil,
|
header: nil,
|
||||||
enableContextActions: false,
|
enabledContextActions: nil,
|
||||||
hiddenOffset: false,
|
hiddenOffset: false,
|
||||||
interaction: chatListNodeInteraction
|
interaction: chatListNodeInteraction
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user