mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-27 13:40:41 +00:00
[WIP] Monoforums
This commit is contained in:
parent
245ad761be
commit
09c49d47d9
@ -1297,7 +1297,15 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
if let data = view.cachedData as? CachedUserData {
|
if let data = view.cachedData as? CachedUserData {
|
||||||
return data.sendPaidMessageStars
|
return data.sendPaidMessageStars
|
||||||
} else if let channel = peerViewMainPeer(view) as? TelegramChannel {
|
} else if let channel = peerViewMainPeer(view) as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId {
|
||||||
|
if let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
return mainChannel.sendPaidMessageStars
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return channel.sendPaidMessageStars
|
return channel.sendPaidMessageStars
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4023,7 +4023,7 @@ open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDel
|
|||||||
}
|
}
|
||||||
headerNode.updateFlashingOnScrolling(flashing, animated: false)
|
headerNode.updateFlashingOnScrolling(flashing, animated: false)
|
||||||
headerNode.frame = headerFrame
|
headerNode.frame = headerFrame
|
||||||
headerNode.updateLayoutInternal(size: headerFrame.size, leftInset: leftInset, rightInset: rightInset, transition: animateInsertion ? .immediate : transition.0)
|
headerNode.updateLayoutInternal(size: headerFrame.size, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
|
||||||
headerNode.updateInternalStickLocationDistanceFactor(stickLocationDistanceFactor, animated: false)
|
headerNode.updateInternalStickLocationDistanceFactor(stickLocationDistanceFactor, animated: false)
|
||||||
self.itemHeaderNodes[id] = headerNode
|
self.itemHeaderNodes[id] = headerNode
|
||||||
if insertItemBelowOtherHeaders {
|
if insertItemBelowOtherHeaders {
|
||||||
|
@ -1070,6 +1070,16 @@ public struct PeerAndThreadId: Hashable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct PeerAndBoundThreadId: Hashable {
|
||||||
|
public var peerId: PeerId
|
||||||
|
public var threadId: Int64
|
||||||
|
|
||||||
|
public init(peerId: PeerId, threadId: Int64) {
|
||||||
|
self.peerId = peerId
|
||||||
|
self.threadId = threadId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct MessageAndThreadId: Hashable {
|
public struct MessageAndThreadId: Hashable {
|
||||||
public var messageId: MessageId
|
public var messageId: MessageId
|
||||||
public var threadId: Int64?
|
public var threadId: Int64?
|
||||||
|
@ -7,19 +7,22 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
let pinnedIndex: Int?
|
let pinnedIndex: Int?
|
||||||
let index: MessageIndex
|
let index: MessageIndex
|
||||||
let topMessage: Message?
|
let topMessage: Message?
|
||||||
|
let unreadCount: Int
|
||||||
|
|
||||||
init(
|
init(
|
||||||
id: Int64,
|
id: Int64,
|
||||||
peer: Peer?,
|
peer: Peer?,
|
||||||
pinnedIndex: Int?,
|
pinnedIndex: Int?,
|
||||||
index: MessageIndex,
|
index: MessageIndex,
|
||||||
topMessage: Message?
|
topMessage: Message?,
|
||||||
|
unreadCount: Int
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.pinnedIndex = pinnedIndex
|
self.pinnedIndex = pinnedIndex
|
||||||
self.index = index
|
self.index = index
|
||||||
self.topMessage = topMessage
|
self.topMessage = topMessage
|
||||||
|
self.unreadCount = unreadCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +70,8 @@ final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
|||||||
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)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,19 +124,22 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
public let pinnedIndex: Int?
|
public let pinnedIndex: Int?
|
||||||
public let index: MessageIndex
|
public let index: MessageIndex
|
||||||
public let topMessage: Message?
|
public let topMessage: Message?
|
||||||
|
public let unreadCount: Int
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
id: Int64,
|
id: Int64,
|
||||||
peer: Peer?,
|
peer: Peer?,
|
||||||
pinnedIndex: Int?,
|
pinnedIndex: Int?,
|
||||||
index: MessageIndex,
|
index: MessageIndex,
|
||||||
topMessage: Message?
|
topMessage: Message?,
|
||||||
|
unreadCount: Int
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.pinnedIndex = pinnedIndex
|
self.pinnedIndex = pinnedIndex
|
||||||
self.index = index
|
self.index = index
|
||||||
self.topMessage = topMessage
|
self.topMessage = topMessage
|
||||||
|
self.unreadCount = unreadCount
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
@ -158,6 +165,9 @@ public final class EngineMessageHistorySavedMessagesThread {
|
|||||||
} else if (lhs.topMessage == nil) != (rhs.topMessage == nil) {
|
} else if (lhs.topMessage == nil) != (rhs.topMessage == nil) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.unreadCount != rhs.unreadCount {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -179,7 +189,8 @@ public final class MessageHistorySavedMessagesIndexView: PostboxView {
|
|||||||
peer: item.peer,
|
peer: item.peer,
|
||||||
pinnedIndex: item.pinnedIndex,
|
pinnedIndex: item.pinnedIndex,
|
||||||
index: item.index,
|
index: item.index,
|
||||||
topMessage: item.topMessage
|
topMessage: item.topMessage,
|
||||||
|
unreadCount: item.unreadCount
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
self.items = items
|
self.items = items
|
||||||
|
@ -48,13 +48,18 @@ final class MutablePeerView: MutablePostboxView {
|
|||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
peerIds.insert(peerId)
|
peerIds.insert(peerId)
|
||||||
|
|
||||||
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId {
|
||||||
peerIds.insert(associatedPeerId)
|
peerIds.insert(associatedPeerId)
|
||||||
|
|
||||||
|
if peer.associatedPeerOverridesIdentity {
|
||||||
self.contactPeerId = associatedPeerId
|
self.contactPeerId = associatedPeerId
|
||||||
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
|
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
|
||||||
} else {
|
} else {
|
||||||
self.contactPeerId = peerId
|
self.contactPeerId = peerId
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.contactPeerId = peerId
|
||||||
|
}
|
||||||
self.cachedData = postbox.cachedPeerDataTable.get(contactPeerId)
|
self.cachedData = postbox.cachedPeerDataTable.get(contactPeerId)
|
||||||
self.peerIsContact = postbox.contactsTable.isContact(peerId: self.contactPeerId)
|
self.peerIsContact = postbox.contactsTable.isContact(peerId: self.contactPeerId)
|
||||||
var cachedDataPeerIds = Set<PeerId>()
|
var cachedDataPeerIds = Set<PeerId>()
|
||||||
@ -76,17 +81,21 @@ final class MutablePeerView: MutablePostboxView {
|
|||||||
self.memberStoryStats[id] = value
|
self.memberStoryStats[id] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId, peer.associatedPeerOverridesIdentity {
|
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId {
|
||||||
if let peer = getPeer(associatedPeerId) {
|
if let peer = getPeer(associatedPeerId) {
|
||||||
self.peers[associatedPeerId] = peer
|
self.peers[associatedPeerId] = peer
|
||||||
}
|
}
|
||||||
if let presence = getPeerPresence(associatedPeerId) {
|
if let presence = getPeerPresence(associatedPeerId) {
|
||||||
self.peerPresences[associatedPeerId] = presence
|
self.peerPresences[associatedPeerId] = presence
|
||||||
}
|
}
|
||||||
|
if peer.associatedPeerOverridesIdentity {
|
||||||
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(associatedPeerId)
|
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(associatedPeerId)
|
||||||
} else {
|
} else {
|
||||||
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
|
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
|
||||||
|
}
|
||||||
for id in messageIds {
|
for id in messageIds {
|
||||||
if let message = postbox.getMessage(id) {
|
if let message = postbox.getMessage(id) {
|
||||||
self.messages[id] = message
|
self.messages[id] = message
|
||||||
|
@ -1249,7 +1249,7 @@ public final class ShareController: ViewController {
|
|||||||
private func shareModern(text: String, peerIds: [EnginePeer.Id], topicIds: [EnginePeer.Id: Int64], showNames: Bool, silently: Bool) -> Signal<ShareState, ShareControllerError> {
|
private func shareModern(text: String, peerIds: [EnginePeer.Id], topicIds: [EnginePeer.Id: Int64], showNames: Bool, silently: Bool) -> Signal<ShareState, ShareControllerError> {
|
||||||
return self.currentContext.stateManager.postbox.combinedView(
|
return self.currentContext.stateManager.postbox.combinedView(
|
||||||
keys: peerIds.map { peerId in
|
keys: peerIds.map { peerId in
|
||||||
return PostboxViewKey.basicPeer(peerId)
|
return PostboxViewKey.peer(peerId: peerId, components: [])
|
||||||
} + peerIds.map { peerId in
|
} + peerIds.map { peerId in
|
||||||
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
||||||
}
|
}
|
||||||
@ -1259,17 +1259,23 @@ public final class ShareController: ViewController {
|
|||||||
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
||||||
var requiresStars: [EnginePeer.Id: StarsAmount] = [:]
|
var requiresStars: [EnginePeer.Id: StarsAmount] = [:]
|
||||||
for peerId in peerIds {
|
for peerId in peerIds {
|
||||||
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? BasicPeerView, let peer = view.peer {
|
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? PeerView, let peer = peerViewMainPeer(view) {
|
||||||
result[peerId] = EnginePeer(peer)
|
result[peerId] = EnginePeer(peer)
|
||||||
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
||||||
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
||||||
requiresStars[peerId] = cachedData.sendPaidMessageStars
|
requiresStars[peerId] = cachedData.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId {
|
||||||
|
if let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
requiresStars[peerId] = mainChannel.sendPaidMessageStars
|
||||||
|
}
|
||||||
|
} else {
|
||||||
requiresStars[peerId] = channel.sendPaidMessageStars
|
requiresStars[peerId] = channel.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (result, requiresStars)
|
return (result, requiresStars)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
@ -1903,7 +1909,7 @@ public final class ShareController: ViewController {
|
|||||||
}
|
}
|
||||||
return currentContext.stateManager.postbox.combinedView(
|
return currentContext.stateManager.postbox.combinedView(
|
||||||
keys: peerIds.map { peerId in
|
keys: peerIds.map { peerId in
|
||||||
return PostboxViewKey.basicPeer(peerId)
|
return PostboxViewKey.peer(peerId: peerId, components: [])
|
||||||
} + peerIds.map { peerId in
|
} + peerIds.map { peerId in
|
||||||
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
||||||
}
|
}
|
||||||
@ -1913,17 +1919,23 @@ public final class ShareController: ViewController {
|
|||||||
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
||||||
var requiresStars: [EnginePeer.Id: StarsAmount] = [:]
|
var requiresStars: [EnginePeer.Id: StarsAmount] = [:]
|
||||||
for peerId in peerIds {
|
for peerId in peerIds {
|
||||||
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? BasicPeerView, let peer = view.peer {
|
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? PeerView, let peer = peerViewMainPeer(view) {
|
||||||
result[peerId] = EnginePeer(peer)
|
result[peerId] = EnginePeer(peer)
|
||||||
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
||||||
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
||||||
requiresStars[peerId] = cachedData.sendPaidMessageStars
|
requiresStars[peerId] = cachedData.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId {
|
||||||
|
if let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
requiresStars[peerId] = mainChannel.sendPaidMessageStars
|
||||||
|
}
|
||||||
|
} else {
|
||||||
requiresStars[peerId] = channel.sendPaidMessageStars
|
requiresStars[peerId] = channel.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (result, requiresStars)
|
return (result, requiresStars)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
@ -2518,6 +2530,9 @@ public final class ShareController: ViewController {
|
|||||||
possiblePremiumRequiredPeers.insert(user.id)
|
possiblePremiumRequiredPeers.insert(user.id)
|
||||||
} else if let channel = peer as? TelegramChannel, let _ = channel.sendPaidMessageStars {
|
} else if let channel = peer as? TelegramChannel, let _ = channel.sendPaidMessageStars {
|
||||||
possiblePremiumRequiredPeers.insert(channel.id)
|
possiblePremiumRequiredPeers.insert(channel.id)
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = entryData.renderedPeer.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.sendPaidMessageStars != nil {
|
||||||
|
possiblePremiumRequiredPeers.insert(channel.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -2531,7 +2546,7 @@ public final class ShareController: ViewController {
|
|||||||
keys.append(peerPresencesKey)
|
keys.append(peerPresencesKey)
|
||||||
|
|
||||||
for id in possiblePremiumRequiredPeers {
|
for id in possiblePremiumRequiredPeers {
|
||||||
keys.append(.basicPeer(id))
|
keys.append(.peer(peerId: id, components: []))
|
||||||
keys.append(.cachedPeerData(peerId: id))
|
keys.append(.cachedPeerData(peerId: id))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2549,8 +2564,12 @@ public final class ShareController: ViewController {
|
|||||||
if let view = views.views[.cachedPeerData(peerId: id)] as? CachedPeerDataView, let data = view.cachedPeerData as? CachedUserData {
|
if let view = views.views[.cachedPeerData(peerId: id)] as? CachedPeerDataView, let data = view.cachedPeerData as? CachedUserData {
|
||||||
requiresPremiumForMessaging[id] = data.flags.contains(.premiumRequired)
|
requiresPremiumForMessaging[id] = data.flags.contains(.premiumRequired)
|
||||||
requiresStars[id] = data.sendPaidMessageStars?.value
|
requiresStars[id] = data.sendPaidMessageStars?.value
|
||||||
} else if let view = views.views[.basicPeer(id)] as? BasicPeerView, let channel = view.peer as? TelegramChannel {
|
} else if let view = views.views[.basicPeer(id)] as? PeerView, let channel = peerViewMainPeer(view) as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
requiresStars[id] = mainChannel.sendPaidMessageStars?.value
|
||||||
|
} else {
|
||||||
requiresStars[id] = channel.sendPaidMessageStars?.value
|
requiresStars[id] = channel.sendPaidMessageStars?.value
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
requiresPremiumForMessaging[id] = false
|
requiresPremiumForMessaging[id] = false
|
||||||
}
|
}
|
||||||
|
@ -1274,7 +1274,7 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
|
|||||||
if let context = self.context, let tryShare = self.tryShare {
|
if let context = self.context, let tryShare = self.tryShare {
|
||||||
let _ = (context.stateManager.postbox.combinedView(
|
let _ = (context.stateManager.postbox.combinedView(
|
||||||
keys: peerIds.map { peerId in
|
keys: peerIds.map { peerId in
|
||||||
return PostboxViewKey.basicPeer(peerId)
|
return PostboxViewKey.peer(peerId: peerId, components: [])
|
||||||
} + peerIds.map { peerId in
|
} + peerIds.map { peerId in
|
||||||
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
return PostboxViewKey.cachedPeerData(peerId: peerId)
|
||||||
}
|
}
|
||||||
@ -1284,17 +1284,21 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
|
|||||||
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
var result: [EnginePeer.Id: EnginePeer?] = [:]
|
||||||
var requiresStars: [EnginePeer.Id: Int64] = [:]
|
var requiresStars: [EnginePeer.Id: Int64] = [:]
|
||||||
for peerId in peerIds {
|
for peerId in peerIds {
|
||||||
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? BasicPeerView, let peer = view.peer {
|
if let view = views.views[PostboxViewKey.basicPeer(peerId)] as? PeerView, let peer = peerViewMainPeer(view) {
|
||||||
result[peerId] = EnginePeer(peer)
|
result[peerId] = EnginePeer(peer)
|
||||||
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
if peer is TelegramUser, let cachedPeerDataView = views.views[PostboxViewKey.cachedPeerData(peerId: peerId)] as? CachedPeerDataView {
|
||||||
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
if let cachedData = cachedPeerDataView.cachedPeerData as? CachedUserData {
|
||||||
requiresStars[peerId] = cachedData.sendPaidMessageStars?.value
|
requiresStars[peerId] = cachedData.sendPaidMessageStars?.value
|
||||||
}
|
}
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
requiresStars[peerId] = mainChannel.sendPaidMessageStars?.value
|
||||||
|
} else {
|
||||||
requiresStars[peerId] = channel.sendPaidMessageStars?.value
|
requiresStars[peerId] = channel.sendPaidMessageStars?.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (result, requiresStars)
|
return (result, requiresStars)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peers, requiresStars in
|
|> deliverOnMainQueue).start(next: { [weak self] peers, requiresStars in
|
||||||
|
@ -872,6 +872,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1054465340] = { return Api.RichText.parse_textUnderline($0) }
|
dict[-1054465340] = { return Api.RichText.parse_textUnderline($0) }
|
||||||
dict[1009288385] = { return Api.RichText.parse_textUrl($0) }
|
dict[1009288385] = { return Api.RichText.parse_textUrl($0) }
|
||||||
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
|
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
|
||||||
|
dict[2099641667] = { return Api.SavedDialog.parse_monoForumDialog($0) }
|
||||||
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
|
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
|
||||||
dict[-881854424] = { return Api.SavedReactionTag.parse_savedReactionTag($0) }
|
dict[-881854424] = { return Api.SavedReactionTag.parse_savedReactionTag($0) }
|
||||||
dict[-539360103] = { return Api.SavedStarGift.parse_savedStarGift($0) }
|
dict[-539360103] = { return Api.SavedStarGift.parse_savedStarGift($0) }
|
||||||
@ -1064,8 +1065,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) }
|
dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) }
|
||||||
dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) }
|
dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) }
|
||||||
dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) }
|
dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) }
|
||||||
dict[-513517117] = { return Api.Update.parse_updateDialogUnreadMark($0) }
|
dict[-1235684802] = { return Api.Update.parse_updateDialogUnreadMark($0) }
|
||||||
dict[457829485] = { return Api.Update.parse_updateDraftMessage($0) }
|
dict[-302247650] = { return Api.Update.parse_updateDraftMessage($0) }
|
||||||
dict[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) }
|
dict[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) }
|
||||||
dict[-469536605] = { return Api.Update.parse_updateEditMessage($0) }
|
dict[-469536605] = { return Api.Update.parse_updateEditMessage($0) }
|
||||||
dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($0) }
|
dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($0) }
|
||||||
@ -1123,6 +1124,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) }
|
dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) }
|
||||||
dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) }
|
dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) }
|
||||||
dict[-131960447] = { return Api.Update.parse_updateReadMessagesContents($0) }
|
dict[-131960447] = { return Api.Update.parse_updateReadMessagesContents($0) }
|
||||||
|
dict[-1124907246] = { return Api.Update.parse_updateReadMonoForumInbox($0) }
|
||||||
|
dict[-1532521610] = { return Api.Update.parse_updateReadMonoForumOutbox($0) }
|
||||||
dict[-145845461] = { return Api.Update.parse_updateReadStories($0) }
|
dict[-145845461] = { return Api.Update.parse_updateReadStories($0) }
|
||||||
dict[821314523] = { return Api.Update.parse_updateRecentEmojiStatuses($0) }
|
dict[821314523] = { return Api.Update.parse_updateRecentEmojiStatuses($0) }
|
||||||
dict[1870160884] = { return Api.Update.parse_updateRecentReactions($0) }
|
dict[1870160884] = { return Api.Update.parse_updateRecentReactions($0) }
|
||||||
|
@ -47,11 +47,24 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum SavedDialog: TypeConstructorDescription {
|
indirect enum SavedDialog: TypeConstructorDescription {
|
||||||
|
case monoForumDialog(flags: Int32, peer: Api.Peer, topMessage: Int32, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, draft: Api.DraftMessage?)
|
||||||
case savedDialog(flags: Int32, peer: Api.Peer, topMessage: Int32)
|
case savedDialog(flags: Int32, peer: Api.Peer, topMessage: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .monoForumDialog(let flags, let peer, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let draft):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(2099641667)
|
||||||
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(topMessage, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(readInboxMaxId, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(readOutboxMaxId, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(unreadCount, buffer: buffer, boxed: false)
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {draft!.serialize(buffer, true)}
|
||||||
|
break
|
||||||
case .savedDialog(let flags, let peer, let topMessage):
|
case .savedDialog(let flags, let peer, let topMessage):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-1115174036)
|
buffer.appendInt32(-1115174036)
|
||||||
@ -65,11 +78,46 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .monoForumDialog(let flags, let peer, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let draft):
|
||||||
|
return ("monoForumDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any), ("readInboxMaxId", readInboxMaxId as Any), ("readOutboxMaxId", readOutboxMaxId as Any), ("unreadCount", unreadCount as Any), ("draft", draft as Any)])
|
||||||
case .savedDialog(let flags, let peer, let topMessage):
|
case .savedDialog(let flags, let peer, let topMessage):
|
||||||
return ("savedDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any)])
|
return ("savedDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func parse_monoForumDialog(_ reader: BufferReader) -> SavedDialog? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
var _2: Api.Peer?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
}
|
||||||
|
var _3: Int32?
|
||||||
|
_3 = reader.readInt32()
|
||||||
|
var _4: Int32?
|
||||||
|
_4 = reader.readInt32()
|
||||||
|
var _5: Int32?
|
||||||
|
_5 = reader.readInt32()
|
||||||
|
var _6: Int32?
|
||||||
|
_6 = reader.readInt32()
|
||||||
|
var _7: Api.DraftMessage?
|
||||||
|
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_7 = Api.parse(reader, signature: signature) as? Api.DraftMessage
|
||||||
|
} }
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
let _c3 = _3 != nil
|
||||||
|
let _c4 = _4 != nil
|
||||||
|
let _c5 = _5 != nil
|
||||||
|
let _c6 = _6 != nil
|
||||||
|
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||||
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||||
|
return Api.SavedDialog.monoForumDialog(flags: _1!, peer: _2!, topMessage: _3!, readInboxMaxId: _4!, readOutboxMaxId: _5!, unreadCount: _6!, draft: _7)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
public static func parse_savedDialog(_ reader: BufferReader) -> SavedDialog? {
|
public static func parse_savedDialog(_ reader: BufferReader) -> SavedDialog? {
|
||||||
var _1: Int32?
|
var _1: Int32?
|
||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
|
@ -1037,8 +1037,8 @@ public extension Api {
|
|||||||
case updateDialogFilterOrder(order: [Int32])
|
case updateDialogFilterOrder(order: [Int32])
|
||||||
case updateDialogFilters
|
case updateDialogFilters
|
||||||
case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer)
|
case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer)
|
||||||
case updateDialogUnreadMark(flags: Int32, peer: Api.DialogPeer)
|
case updateDialogUnreadMark(flags: Int32, peer: Api.DialogPeer, savedPeerId: Api.Peer?)
|
||||||
case updateDraftMessage(flags: Int32, peer: Api.Peer, topMsgId: Int32?, draft: Api.DraftMessage)
|
case updateDraftMessage(flags: Int32, peer: Api.Peer, topMsgId: Int32?, savedPeerId: Api.Peer?, draft: Api.DraftMessage)
|
||||||
case updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
|
case updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
|
||||||
case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
|
case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
|
||||||
case updateEncryptedChatTyping(chatId: Int32)
|
case updateEncryptedChatTyping(chatId: Int32)
|
||||||
@ -1096,6 +1096,8 @@ public extension Api {
|
|||||||
case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32)
|
case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32)
|
||||||
case updateReadHistoryOutbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32)
|
case updateReadHistoryOutbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32)
|
||||||
case updateReadMessagesContents(flags: Int32, messages: [Int32], pts: Int32, ptsCount: Int32, date: Int32?)
|
case updateReadMessagesContents(flags: Int32, messages: [Int32], pts: Int32, ptsCount: Int32, date: Int32?)
|
||||||
|
case updateReadMonoForumInbox(flags: Int32, channelId: Int64, savedPeerId: Api.Peer, readMaxId: Int32)
|
||||||
|
case updateReadMonoForumOutbox(channelId: Int64, savedPeerId: Api.Peer, readMaxId: Int32)
|
||||||
case updateReadStories(peer: Api.Peer, maxId: Int32)
|
case updateReadStories(peer: Api.Peer, maxId: Int32)
|
||||||
case updateRecentEmojiStatuses
|
case updateRecentEmojiStatuses
|
||||||
case updateRecentReactions
|
case updateRecentReactions
|
||||||
@ -1653,20 +1655,22 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)}
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
case .updateDialogUnreadMark(let flags, let peer):
|
case .updateDialogUnreadMark(let flags, let peer, let savedPeerId):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-513517117)
|
buffer.appendInt32(-1235684802)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
case .updateDraftMessage(let flags, let peer, let topMsgId, let draft):
|
case .updateDraftMessage(let flags, let peer, let topMsgId, let savedPeerId, let draft):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(457829485)
|
buffer.appendInt32(-302247650)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||||
draft.serialize(buffer, true)
|
draft.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
case .updateEditChannelMessage(let message, let pts, let ptsCount):
|
case .updateEditChannelMessage(let message, let pts, let ptsCount):
|
||||||
@ -2164,6 +2168,23 @@ public extension Api {
|
|||||||
serializeInt32(ptsCount, buffer: buffer, boxed: false)
|
serializeInt32(ptsCount, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(date!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(date!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
|
case .updateReadMonoForumInbox(let flags, let channelId, let savedPeerId, let readMaxId):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1124907246)
|
||||||
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
serializeInt64(channelId, buffer: buffer, boxed: false)
|
||||||
|
savedPeerId.serialize(buffer, true)
|
||||||
|
serializeInt32(readMaxId, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
|
case .updateReadMonoForumOutbox(let channelId, let savedPeerId, let readMaxId):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1532521610)
|
||||||
|
}
|
||||||
|
serializeInt64(channelId, buffer: buffer, boxed: false)
|
||||||
|
savedPeerId.serialize(buffer, true)
|
||||||
|
serializeInt32(readMaxId, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
case .updateReadStories(let peer, let maxId):
|
case .updateReadStories(let peer, let maxId):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-145845461)
|
buffer.appendInt32(-145845461)
|
||||||
@ -2491,10 +2512,10 @@ public extension Api {
|
|||||||
return ("updateDialogFilters", [])
|
return ("updateDialogFilters", [])
|
||||||
case .updateDialogPinned(let flags, let folderId, let peer):
|
case .updateDialogPinned(let flags, let folderId, let peer):
|
||||||
return ("updateDialogPinned", [("flags", flags as Any), ("folderId", folderId as Any), ("peer", peer as Any)])
|
return ("updateDialogPinned", [("flags", flags as Any), ("folderId", folderId as Any), ("peer", peer as Any)])
|
||||||
case .updateDialogUnreadMark(let flags, let peer):
|
case .updateDialogUnreadMark(let flags, let peer, let savedPeerId):
|
||||||
return ("updateDialogUnreadMark", [("flags", flags as Any), ("peer", peer as Any)])
|
return ("updateDialogUnreadMark", [("flags", flags as Any), ("peer", peer as Any), ("savedPeerId", savedPeerId as Any)])
|
||||||
case .updateDraftMessage(let flags, let peer, let topMsgId, let draft):
|
case .updateDraftMessage(let flags, let peer, let topMsgId, let savedPeerId, let draft):
|
||||||
return ("updateDraftMessage", [("flags", flags as Any), ("peer", peer as Any), ("topMsgId", topMsgId as Any), ("draft", draft as Any)])
|
return ("updateDraftMessage", [("flags", flags as Any), ("peer", peer as Any), ("topMsgId", topMsgId as Any), ("savedPeerId", savedPeerId as Any), ("draft", draft as Any)])
|
||||||
case .updateEditChannelMessage(let message, let pts, let ptsCount):
|
case .updateEditChannelMessage(let message, let pts, let ptsCount):
|
||||||
return ("updateEditChannelMessage", [("message", message as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any)])
|
return ("updateEditChannelMessage", [("message", message as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any)])
|
||||||
case .updateEditMessage(let message, let pts, let ptsCount):
|
case .updateEditMessage(let message, let pts, let ptsCount):
|
||||||
@ -2609,6 +2630,10 @@ public extension Api {
|
|||||||
return ("updateReadHistoryOutbox", [("peer", peer as Any), ("maxId", maxId as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any)])
|
return ("updateReadHistoryOutbox", [("peer", peer as Any), ("maxId", maxId as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any)])
|
||||||
case .updateReadMessagesContents(let flags, let messages, let pts, let ptsCount, let date):
|
case .updateReadMessagesContents(let flags, let messages, let pts, let ptsCount, let date):
|
||||||
return ("updateReadMessagesContents", [("flags", flags as Any), ("messages", messages as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any), ("date", date as Any)])
|
return ("updateReadMessagesContents", [("flags", flags as Any), ("messages", messages as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any), ("date", date as Any)])
|
||||||
|
case .updateReadMonoForumInbox(let flags, let channelId, let savedPeerId, let readMaxId):
|
||||||
|
return ("updateReadMonoForumInbox", [("flags", flags as Any), ("channelId", channelId as Any), ("savedPeerId", savedPeerId as Any), ("readMaxId", readMaxId as Any)])
|
||||||
|
case .updateReadMonoForumOutbox(let channelId, let savedPeerId, let readMaxId):
|
||||||
|
return ("updateReadMonoForumOutbox", [("channelId", channelId as Any), ("savedPeerId", savedPeerId as Any), ("readMaxId", readMaxId as Any)])
|
||||||
case .updateReadStories(let peer, let maxId):
|
case .updateReadStories(let peer, let maxId):
|
||||||
return ("updateReadStories", [("peer", peer as Any), ("maxId", maxId as Any)])
|
return ("updateReadStories", [("peer", peer as Any), ("maxId", maxId as Any)])
|
||||||
case .updateRecentEmojiStatuses:
|
case .updateRecentEmojiStatuses:
|
||||||
@ -3783,10 +3808,15 @@ public extension Api {
|
|||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_2 = Api.parse(reader, signature: signature) as? Api.DialogPeer
|
_2 = Api.parse(reader, signature: signature) as? Api.DialogPeer
|
||||||
}
|
}
|
||||||
|
var _3: Api.Peer?
|
||||||
|
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_3 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
if _c1 && _c2 {
|
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||||
return Api.Update.updateDialogUnreadMark(flags: _1!, peer: _2!)
|
if _c1 && _c2 && _c3 {
|
||||||
|
return Api.Update.updateDialogUnreadMark(flags: _1!, peer: _2!, savedPeerId: _3)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -3801,16 +3831,21 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
var _3: Int32?
|
var _3: Int32?
|
||||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||||
var _4: Api.DraftMessage?
|
var _4: Api.Peer?
|
||||||
|
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_4 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
} }
|
||||||
|
var _5: Api.DraftMessage?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_4 = Api.parse(reader, signature: signature) as? Api.DraftMessage
|
_5 = Api.parse(reader, signature: signature) as? Api.DraftMessage
|
||||||
}
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||||
let _c4 = _4 != nil
|
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 {
|
let _c5 = _5 != nil
|
||||||
return Api.Update.updateDraftMessage(flags: _1!, peer: _2!, topMsgId: _3, draft: _4!)
|
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||||
|
return Api.Update.updateDraftMessage(flags: _1!, peer: _2!, topMsgId: _3, savedPeerId: _4, draft: _5!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
@ -4802,6 +4837,47 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_updateReadMonoForumInbox(_ reader: BufferReader) -> Update? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
var _2: Int64?
|
||||||
|
_2 = reader.readInt64()
|
||||||
|
var _3: Api.Peer?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_3 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
}
|
||||||
|
var _4: Int32?
|
||||||
|
_4 = reader.readInt32()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
let _c3 = _3 != nil
|
||||||
|
let _c4 = _4 != nil
|
||||||
|
if _c1 && _c2 && _c3 && _c4 {
|
||||||
|
return Api.Update.updateReadMonoForumInbox(flags: _1!, channelId: _2!, savedPeerId: _3!, readMaxId: _4!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static func parse_updateReadMonoForumOutbox(_ reader: BufferReader) -> Update? {
|
||||||
|
var _1: Int64?
|
||||||
|
_1 = reader.readInt64()
|
||||||
|
var _2: Api.Peer?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
|
}
|
||||||
|
var _3: Int32?
|
||||||
|
_3 = reader.readInt32()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
let _c3 = _3 != nil
|
||||||
|
if _c1 && _c2 && _c3 {
|
||||||
|
return Api.Update.updateReadMonoForumOutbox(channelId: _1!, savedPeerId: _2!, readMaxId: _3!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
public static func parse_updateReadStories(_ reader: BufferReader) -> Update? {
|
public static func parse_updateReadStories(_ reader: BufferReader) -> Update? {
|
||||||
var _1: Api.Peer?
|
var _1: Api.Peer?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -5983,11 +5983,12 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func getDialogUnreadMarks() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogPeer]>) {
|
static func getDialogUnreadMarks(flags: Int32, parentPeer: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogPeer]>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(585256482)
|
buffer.appendInt32(555754018)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
return (FunctionDescription(name: "messages.getDialogUnreadMarks", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogPeer]? in
|
if Int(flags) & Int(1 << 0) != 0 {parentPeer!.serialize(buffer, true)}
|
||||||
|
return (FunctionDescription(name: "messages.getDialogUnreadMarks", parameters: [("flags", String(describing: flags)), ("parentPeer", String(describing: parentPeer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogPeer]? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: [Api.DialogPeer]?
|
var result: [Api.DialogPeer]?
|
||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
@ -7281,12 +7282,13 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func markDialogUnread(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
static func markDialogUnread(flags: Int32, parentPeer: Api.InputPeer?, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(-1031349873)
|
buffer.appendInt32(-1940912392)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {parentPeer!.serialize(buffer, true)}
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
return (FunctionDescription(name: "messages.markDialogUnread", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
return (FunctionDescription(name: "messages.markDialogUnread", parameters: [("flags", String(describing: flags)), ("parentPeer", String(describing: parentPeer)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Bool?
|
var result: Api.Bool?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -7470,6 +7472,23 @@ public extension Api.functions.messages {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.messages {
|
||||||
|
static func readSavedHistory(parentPeer: Api.InputPeer, peer: Api.InputPeer, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1169540261)
|
||||||
|
parentPeer.serialize(buffer, true)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(maxId, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "messages.readSavedHistory", parameters: [("parentPeer", String(describing: parentPeer)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.Bool?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func receivedMessages(maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ReceivedNotifyMessage]>) {
|
static func receivedMessages(maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ReceivedNotifyMessage]>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
@ -113,7 +113,7 @@ enum AccountStateMutationOperation {
|
|||||||
case SyncChatListFilters
|
case SyncChatListFilters
|
||||||
case UpdateChatListFilterOrder(order: [Int32])
|
case UpdateChatListFilterOrder(order: [Int32])
|
||||||
case UpdateChatListFilter(id: Int32, filter: Api.DialogFilter?)
|
case UpdateChatListFilter(id: Int32, filter: Api.DialogFilter?)
|
||||||
case UpdateReadThread(threadMessageId: MessageId, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?)
|
case UpdateReadThread(peerId: PeerId, threadId: Int64, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?)
|
||||||
case UpdateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32)
|
case UpdateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32)
|
||||||
case UpdateGroupCall(peerId: PeerId?, call: Api.GroupCall)
|
case UpdateGroupCall(peerId: PeerId?, call: Api.GroupCall)
|
||||||
case UpdateGroupCallChainBlocks(id: Int64, accessHash: Int64, subChainId: Int32, blocks: [Data], nextOffset: Int32)
|
case UpdateGroupCallChainBlocks(id: Int64, accessHash: Int64, subChainId: Int32, blocks: [Data], nextOffset: Int32)
|
||||||
@ -122,7 +122,7 @@ enum AccountStateMutationOperation {
|
|||||||
case UpdateAudioTranscription(messageId: MessageId, id: Int64, isPending: Bool, text: String)
|
case UpdateAudioTranscription(messageId: MessageId, id: Int64, isPending: Bool, text: String)
|
||||||
case UpdateConfig
|
case UpdateConfig
|
||||||
case UpdateExtendedMedia(MessageId, [Api.MessageExtendedMedia])
|
case UpdateExtendedMedia(MessageId, [Api.MessageExtendedMedia])
|
||||||
case ResetForumTopic(topicId: MessageId, data: StoreMessageHistoryThreadData, pts: Int32)
|
case ResetForumTopic(topicId: PeerAndBoundThreadId, data: StoreMessageHistoryThreadData, pts: Int32?)
|
||||||
case UpdateStory(peerId: PeerId, story: Api.StoryItem)
|
case UpdateStory(peerId: PeerId, story: Api.StoryItem)
|
||||||
case UpdateReadStories(peerId: PeerId, maxId: Int32)
|
case UpdateReadStories(peerId: PeerId, maxId: Int32)
|
||||||
case UpdateStoryStealthMode(data: Api.StoriesStealthMode)
|
case UpdateStoryStealthMode(data: Api.StoriesStealthMode)
|
||||||
@ -392,8 +392,8 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.ReadOutbox(messageId, timestamp))
|
self.addOperation(.ReadOutbox(messageId, timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func readThread(threadMessageId: MessageId, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?) {
|
mutating func readThread(peerId: PeerId, threadId: Int64, readMaxId: Int32, isIncoming: Bool, mainChannelMessage: MessageId?) {
|
||||||
self.addOperation(.UpdateReadThread(threadMessageId: threadMessageId, readMaxId: readMaxId, isIncoming: isIncoming, mainChannelMessage: mainChannelMessage))
|
self.addOperation(.UpdateReadThread(peerId: peerId, threadId: threadId, readMaxId: readMaxId, isIncoming: isIncoming, mainChannelMessage: mainChannelMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func updateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32) {
|
mutating func updateGroupCallParticipants(id: Int64, accessHash: Int64, participants: [Api.GroupCallParticipant], version: Int32) {
|
||||||
@ -854,8 +854,8 @@ struct AccountReplayedFinalState {
|
|||||||
let updatedPeersNearby: [PeerNearby]?
|
let updatedPeersNearby: [PeerNearby]?
|
||||||
let isContactUpdates: [(PeerId, Bool)]
|
let isContactUpdates: [(PeerId, Bool)]
|
||||||
let delayNotificatonsUntil: Int32?
|
let delayNotificatonsUntil: Int32?
|
||||||
let updatedIncomingThreadReadStates: [MessageId: MessageId.Id]
|
let updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
|
||||||
let updatedOutgoingThreadReadStates: [MessageId: MessageId.Id]
|
let updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
|
||||||
let updateConfig: Bool
|
let updateConfig: Bool
|
||||||
let isPremiumUpdated: Bool
|
let isPremiumUpdated: Bool
|
||||||
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
||||||
@ -887,8 +887,8 @@ struct AccountFinalStateEvents {
|
|||||||
let updatedQts: Int32?
|
let updatedQts: Int32?
|
||||||
let externallyUpdatedPeerId: Set<PeerId>
|
let externallyUpdatedPeerId: Set<PeerId>
|
||||||
let authorizationListUpdated: Bool
|
let authorizationListUpdated: Bool
|
||||||
let updatedIncomingThreadReadStates: [MessageId: MessageId.Id]
|
let updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
|
||||||
let updatedOutgoingThreadReadStates: [MessageId: MessageId.Id]
|
let updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
|
||||||
let updateConfig: Bool
|
let updateConfig: Bool
|
||||||
let isPremiumUpdated: Bool
|
let isPremiumUpdated: Bool
|
||||||
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
||||||
@ -901,7 +901,7 @@ struct AccountFinalStateEvents {
|
|||||||
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty && self.updatedStarsBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty && self.reportMessageDelivery.isEmpty && self.addedConferenceInvitationMessagesIds.isEmpty
|
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty && self.updatedStarsBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty && self.reportMessageDelivery.isEmpty && self.addedConferenceInvitationMessagesIds.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set(), reportMessageDelivery: Set<MessageId> = Set(), addedConferenceInvitationMessagesIds: [MessageId] = []) {
|
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set(), reportMessageDelivery: Set<MessageId> = Set(), addedConferenceInvitationMessagesIds: [MessageId] = []) {
|
||||||
self.addedIncomingMessageIds = addedIncomingMessageIds
|
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
self.addedReactionEvents = addedReactionEvents
|
self.addedReactionEvents = addedReactionEvents
|
||||||
self.wasScheduledMessageIds = wasScheduledMessageIds
|
self.wasScheduledMessageIds = wasScheduledMessageIds
|
||||||
|
@ -234,13 +234,13 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let topicId = topicId {
|
if let topicId {
|
||||||
return account.postbox.transaction { transaction -> Void in
|
return account.postbox.transaction { transaction -> Void in
|
||||||
transaction.removeHole(peerId: peerId, threadId: topicId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1))
|
transaction.removeHole(peerId: peerId, threadId: topicId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1))
|
||||||
}
|
}
|
||||||
|> castError(CreateForumChannelTopicError.self)
|
|> castError(CreateForumChannelTopicError.self)
|
||||||
|> mapToSignal { _ -> Signal<Int64, CreateForumChannelTopicError> in
|
|> mapToSignal { _ -> Signal<Int64, CreateForumChannelTopicError> in
|
||||||
return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, ids: [MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))])
|
return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: topicId)])
|
||||||
|> castError(CreateForumChannelTopicError.self)
|
|> castError(CreateForumChannelTopicError.self)
|
||||||
|> map { _ -> Int64 in
|
|> map { _ -> Int64 in
|
||||||
return topicId
|
return topicId
|
||||||
@ -270,7 +270,7 @@ func _internal_fetchForumChannelTopic(account: Account, peerId: PeerId, threadId
|
|||||||
if let info = info {
|
if let info = info {
|
||||||
return .single(.result(info))
|
return .single(.result(info))
|
||||||
} else {
|
} else {
|
||||||
return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, ids: [MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))])
|
return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: threadId)])
|
||||||
|> mapToSignal { _ -> Signal<FetchForumChannelTopicResult, NoError> in
|
|> mapToSignal { _ -> Signal<FetchForumChannelTopicResult, NoError> in
|
||||||
return account.postbox.transaction { transaction -> FetchForumChannelTopicResult in
|
return account.postbox.transaction { transaction -> FetchForumChannelTopicResult in
|
||||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
@ -803,6 +803,58 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||||
|
threadId: peer.peerId.toInt64(),
|
||||||
|
data: data,
|
||||||
|
topMessage: topMessage,
|
||||||
|
unreadMentionsCount: 0,
|
||||||
|
unreadReactionsCount: 0,
|
||||||
|
index: topicIndex,
|
||||||
|
threadPeer: threadPeer
|
||||||
|
))
|
||||||
|
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
let data = MessageHistoryThreadData(
|
||||||
|
creationDate: 0,
|
||||||
|
isOwnedByMe: true,
|
||||||
|
author: accountPeerId,
|
||||||
|
info: EngineMessageHistoryThread.Info(
|
||||||
|
title: "",
|
||||||
|
icon: nil,
|
||||||
|
iconColor: 0
|
||||||
|
),
|
||||||
|
incomingUnreadCount: unreadCount,
|
||||||
|
maxIncomingReadId: readInboxMaxId,
|
||||||
|
maxKnownMessageId: topMessage,
|
||||||
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: false,
|
||||||
|
isHidden: false,
|
||||||
|
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||||
|
)
|
||||||
|
|
||||||
|
var topTimestamp: Int32 = 1
|
||||||
|
for message in addedMessages {
|
||||||
|
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
|
||||||
|
topTimestamp = max(topTimestamp, message.timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
|
||||||
|
if let minIndexValue = minIndex {
|
||||||
|
if topicIndex < minIndexValue {
|
||||||
|
minIndex = topicIndex
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minIndex = topicIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
var threadPeer: Peer?
|
||||||
|
for user in users {
|
||||||
|
if user.peerId == peer.peerId {
|
||||||
|
threadPeer = TelegramUser(user: user)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||||
threadId: peer.peerId.toInt64(),
|
threadId: peer.peerId.toInt64(),
|
||||||
data: data,
|
data: data,
|
||||||
|
@ -412,10 +412,14 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<
|
|||||||
}
|
}
|
||||||
} else if let channel = peer as? TelegramChannel {
|
} else if let channel = peer as? TelegramChannel {
|
||||||
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
|
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
|
||||||
|
} else {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = transaction.getPeer(linkedMonoforumId) as? TelegramChannel {
|
||||||
|
sendPaidMessageStars = mainChannel.sendPaidMessageStars
|
||||||
} else {
|
} else {
|
||||||
sendPaidMessageStars = channel.sendPaidMessageStars
|
sendPaidMessageStars = channel.sendPaidMessageStars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var messages: [EnqueueMessage] = []
|
var messages: [EnqueueMessage] = []
|
||||||
for id in ids {
|
for id in ids {
|
||||||
|
@ -130,7 +130,7 @@ private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update])
|
|||||||
peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)))
|
peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)))
|
||||||
case let .updateReadHistoryInbox(_, _, peer, _, _, _, _):
|
case let .updateReadHistoryInbox(_, _, peer, _, _, _, _):
|
||||||
peerIds.insert(peer.peerId)
|
peerIds.insert(peer.peerId)
|
||||||
case let .updateDraftMessage(_, peer, _, draft):
|
case let .updateDraftMessage(_, peer, _, _, draft):
|
||||||
switch draft {
|
switch draft {
|
||||||
case .draftMessage:
|
case .draftMessage:
|
||||||
peerIds.insert(peer.peerId)
|
peerIds.insert(peer.peerId)
|
||||||
@ -1213,14 +1213,23 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
if let mainChannelId = mainChannelId, let mainChannelPost = mainChannelPost {
|
if let mainChannelId = mainChannelId, let mainChannelPost = mainChannelPost {
|
||||||
mainChannelMessage = MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(mainChannelId)), namespace: Namespaces.Message.Cloud, id: mainChannelPost)
|
mainChannelMessage = MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(mainChannelId)), namespace: Namespaces.Message.Cloud, id: mainChannelPost)
|
||||||
}
|
}
|
||||||
updatedState.readThread(threadMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: topMsgId), readMaxId: readMaxId, isIncoming: true, mainChannelMessage: mainChannelMessage)
|
updatedState.readThread(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadId: Int64(topMsgId), readMaxId: readMaxId, isIncoming: true, mainChannelMessage: mainChannelMessage)
|
||||||
case let .updateReadChannelDiscussionOutbox(channelId, topMsgId, readMaxId):
|
case let .updateReadChannelDiscussionOutbox(channelId, topMsgId, readMaxId):
|
||||||
updatedState.readThread(threadMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: topMsgId), readMaxId: readMaxId, isIncoming: false, mainChannelMessage: nil)
|
updatedState.readThread(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadId: Int64(topMsgId), readMaxId: readMaxId, isIncoming: false, mainChannelMessage: nil)
|
||||||
case let .updateDialogUnreadMark(flags, peer):
|
case let .updateReadMonoForumInbox(_, channelId, savedPeerId, readMaxId):
|
||||||
|
updatedState.readThread(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadId: savedPeerId.peerId.toInt64(), readMaxId: readMaxId, isIncoming: true, mainChannelMessage: nil)
|
||||||
|
case let .updateReadMonoForumOutbox(channelId, savedPeerId, readMaxId):
|
||||||
|
updatedState.readThread(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadId: savedPeerId.peerId.toInt64(), readMaxId: readMaxId, isIncoming: false, mainChannelMessage: nil)
|
||||||
|
case let .updateDialogUnreadMark(flags, peer, savedPeerId):
|
||||||
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 {
|
||||||
|
let _ = savedPeerId
|
||||||
|
} else {
|
||||||
updatedState.updatePeerChatUnreadMark(peerId, namespace: Namespaces.Message.Cloud, value: (flags & (1 << 0)) != 0)
|
updatedState.updatePeerChatUnreadMark(peerId, namespace: Namespaces.Message.Cloud, value: (flags & (1 << 0)) != 0)
|
||||||
|
}
|
||||||
case .dialogPeerFolder:
|
case .dialogPeerFolder:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1563,7 +1572,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
updatedState.addUpdateInstalledStickerPacks(.sync)
|
updatedState.addUpdateInstalledStickerPacks(.sync)
|
||||||
case .updateSavedGifs:
|
case .updateSavedGifs:
|
||||||
updatedState.addUpdateRecentGifs()
|
updatedState.addUpdateRecentGifs()
|
||||||
case let .updateDraftMessage(_, peer, topMsgId, draft):
|
case let .updateDraftMessage(_, peer, topMsgId, savedPeerId, draft):
|
||||||
let inputState: SynchronizeableChatInputState?
|
let inputState: SynchronizeableChatInputState?
|
||||||
switch draft {
|
switch draft {
|
||||||
case .draftMessageEmpty:
|
case .draftMessageEmpty:
|
||||||
@ -1620,7 +1629,9 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
inputState = SynchronizeableChatInputState(replySubject: replySubject, text: message, entities: messageTextEntitiesFromApiEntities(entities ?? []), timestamp: date, textSelection: nil, messageEffectId: messageEffectId)
|
inputState = SynchronizeableChatInputState(replySubject: replySubject, text: message, entities: messageTextEntitiesFromApiEntities(entities ?? []), timestamp: date, textSelection: nil, messageEffectId: messageEffectId)
|
||||||
}
|
}
|
||||||
var threadId: Int64?
|
var threadId: Int64?
|
||||||
if let topMsgId = topMsgId {
|
if let savedPeerId {
|
||||||
|
threadId = savedPeerId.peerId.toInt64()
|
||||||
|
} else if let topMsgId {
|
||||||
threadId = Int64(topMsgId)
|
threadId = Int64(topMsgId)
|
||||||
}
|
}
|
||||||
updatedState.addUpdateChatInputState(peerId: peer.peerId, threadId: threadId, state: inputState)
|
updatedState.addUpdateChatInputState(peerId: peer.peerId, threadId: threadId, state: inputState)
|
||||||
@ -1905,7 +1916,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, state: finalState)
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: .network(network), state: finalState)
|
||||||
|> mapToSignal { finalState in
|
|> mapToSignal { finalState in
|
||||||
return resolveAssociatedMessages(accountPeerId: accountPeerId, postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(accountPeerId: accountPeerId, postbox: postbox, network: network, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
@ -1921,8 +1932,52 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
final class FetchedForumThreads {
|
||||||
var forumThreadIds = Set<MessageId>()
|
enum Item {
|
||||||
|
case savedDialog(Api.SavedDialog)
|
||||||
|
case forum(Api.ForumTopic)
|
||||||
|
}
|
||||||
|
|
||||||
|
let items: [Item]
|
||||||
|
let totalCount: Int
|
||||||
|
let orderByDate: Bool
|
||||||
|
let pts: Int32?
|
||||||
|
let messages: [Api.Message]
|
||||||
|
let users: [Api.User]
|
||||||
|
let chats: [Api.Chat]
|
||||||
|
|
||||||
|
init(items: [Item], totalCount: Int, orderByDate: Bool, pts: Int32?, messages: [Api.Message], users: [Api.User], chats: [Api.Chat]) {
|
||||||
|
self.items = items
|
||||||
|
self.totalCount = totalCount
|
||||||
|
self.orderByDate = orderByDate
|
||||||
|
self.pts = pts
|
||||||
|
self.messages = messages
|
||||||
|
self.users = users
|
||||||
|
self.chats = chats
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(forumTopics: Api.messages.ForumTopics) {
|
||||||
|
switch forumTopics {
|
||||||
|
case let .forumTopics(flags, count, topics, messages, chats, users, pts):
|
||||||
|
let orderByDate = (flags & (1 << 0)) != 0
|
||||||
|
self.init(items: topics.map(Item.forum), totalCount: Int(count), orderByDate: orderByDate, pts: pts, messages: messages, users: users, chats: chats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init(savedDialogs: Api.messages.SavedDialogs) {
|
||||||
|
switch savedDialogs {
|
||||||
|
case let .savedDialogs(dialogs, messages, chats, users):
|
||||||
|
self.init(items: dialogs.map(Item.savedDialog), totalCount: Int(dialogs.count), orderByDate: false, pts: nil, messages: messages, users: users, chats: chats)
|
||||||
|
case let .savedDialogsSlice(count, dialogs, messages, chats, users):
|
||||||
|
self.init(items: dialogs.map(Item.savedDialog), totalCount: Int(count), orderByDate: false, pts: nil, messages: messages, users: users, chats: chats)
|
||||||
|
case .savedDialogsNotModified:
|
||||||
|
self.init(items: [], totalCount: 0, orderByDate: false, pts: 0, messages: [], users: [], chats: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
|
var forumThreadIds = Set<PeerAndBoundThreadId>()
|
||||||
|
|
||||||
for operation in state.operations {
|
for operation in state.operations {
|
||||||
switch operation {
|
switch operation {
|
||||||
@ -1930,8 +1985,8 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
for message in messages {
|
for message in messages {
|
||||||
if let threadId = message.threadId {
|
if let threadId = message.threadId {
|
||||||
if let channel = state.peers[message.id.peerId] as? TelegramChannel, case .group = channel.info {
|
if let channel = state.peers[message.id.peerId] as? TelegramChannel, case .group = channel.info {
|
||||||
if channel.flags.contains(.isForum) {
|
if channel.flags.contains(.isForum) || channel.flags.contains(.isMonoforum) {
|
||||||
forumThreadIds.insert(MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: Int32(clamping: threadId)))
|
forumThreadIds.insert(PeerAndBoundThreadId(peerId: message.id.peerId, threadId: threadId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1945,31 +2000,65 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
return .single(state)
|
return .single(state)
|
||||||
} else {
|
} else {
|
||||||
return postbox.transaction { transaction -> Signal<AccountMutableState, NoError> in
|
return postbox.transaction { transaction -> Signal<AccountMutableState, NoError> in
|
||||||
var missingForumThreadIds: [PeerId: [Int32]] = [:]
|
var missingForumThreadIds: [PeerId: [Int64]] = [:]
|
||||||
for threadId in forumThreadIds {
|
for threadId in forumThreadIds {
|
||||||
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: Int64(threadId.id)) {
|
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: threadId.threadId) {
|
||||||
} else {
|
} else {
|
||||||
missingForumThreadIds[threadId.peerId, default: []].append(threadId.id)
|
missingForumThreadIds[threadId.peerId, default: []].append(threadId.threadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if missingForumThreadIds.isEmpty {
|
if missingForumThreadIds.isEmpty {
|
||||||
return .single(state)
|
return .single(state)
|
||||||
} else {
|
} else {
|
||||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
var signals: [Signal<(Peer, FetchedForumThreads)?, NoError>] = []
|
||||||
for (peerId, threadIds) in missingForumThreadIds {
|
for (peerId, threadIds) in missingForumThreadIds {
|
||||||
guard let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) else {
|
guard let peer = transaction.getPeer(peerId) as? TelegramChannel, let inputPeer = apiInputPeer(peer), let inputChannel = apiInputChannel(peer) else {
|
||||||
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
|
||||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
if peer.flags.contains(.isMonoforum) {
|
||||||
return (peer, result)
|
//TODO:release
|
||||||
|
let signal = source.request(Api.functions.messages.getSavedDialogs(flags: 1 << 1, parentPeer: inputPeer, offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100, hash: 0))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
let result = FetchedForumThreads(savedDialogs: result)
|
||||||
|
return (peer, FetchedForumThreads(
|
||||||
|
items: result.items.filter({ item -> Bool in
|
||||||
|
switch item {
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, _, _, _, _, _):
|
||||||
|
return threadIds.contains(peer.peerId.toInt64())
|
||||||
|
case .savedDialog:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
case .forum:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
totalCount: result.totalCount,
|
||||||
|
orderByDate: result.orderByDate,
|
||||||
|
pts: result.pts,
|
||||||
|
messages: result.messages,
|
||||||
|
users: result.users,
|
||||||
|
chats: result.chats
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
signals.append(signal)
|
signals.append(signal)
|
||||||
|
} else {
|
||||||
|
let signal = source.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds.map { Int32(clamping: $0) }))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
return (peer, FetchedForumThreads(forumTopics: result))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
signals.append(signal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return combineLatest(signals)
|
return combineLatest(signals)
|
||||||
@ -1983,24 +2072,24 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
let peerIsForum = peer.isForum
|
let peerIsForum = peer.isForum
|
||||||
let peerId = peer.id
|
let peerId = peer.id
|
||||||
|
|
||||||
switch result {
|
state.mergeChats(result.chats)
|
||||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
state.mergeUsers(result.users)
|
||||||
state.mergeChats(chats)
|
|
||||||
state.mergeUsers(users)
|
|
||||||
|
|
||||||
for message in messages {
|
for message in result.messages {
|
||||||
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
||||||
storeMessages.append(message)
|
storeMessages.append(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for topic in topics {
|
for topic in result.items {
|
||||||
|
switch topic {
|
||||||
|
case let .forum(topic):
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||||
let _ = draft
|
let _ = draft
|
||||||
|
|
||||||
state.operations.append(.ResetForumTopic(
|
state.operations.append(.ResetForumTopic(
|
||||||
topicId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id),
|
topicId: PeerAndBoundThreadId(peerId: peerId, threadId: Int64(id)),
|
||||||
data: StoreMessageHistoryThreadData(
|
data: StoreMessageHistoryThreadData(
|
||||||
data: MessageHistoryThreadData(
|
data: MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
@ -2023,11 +2112,44 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
unreadMentionCount: unreadMentionsCount,
|
unreadMentionCount: unreadMentionsCount,
|
||||||
unreadReactionCount: unreadReactionsCount
|
unreadReactionCount: unreadReactionsCount
|
||||||
),
|
),
|
||||||
pts: pts
|
pts: result.pts
|
||||||
))
|
))
|
||||||
case .forumTopicDeleted:
|
case .forumTopicDeleted:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
|
||||||
|
state.operations.append(.ResetForumTopic(
|
||||||
|
topicId: PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64()),
|
||||||
|
data: StoreMessageHistoryThreadData(
|
||||||
|
data: MessageHistoryThreadData(
|
||||||
|
creationDate: 0,
|
||||||
|
isOwnedByMe: true,
|
||||||
|
author: accountPeerId,
|
||||||
|
info: EngineMessageHistoryThread.Info(
|
||||||
|
title: "",
|
||||||
|
icon: nil,
|
||||||
|
iconColor: 0
|
||||||
|
),
|
||||||
|
incomingUnreadCount: unreadCount,
|
||||||
|
maxIncomingReadId: readInboxMaxId,
|
||||||
|
maxKnownMessageId: topMessage,
|
||||||
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: false,
|
||||||
|
isHidden: false,
|
||||||
|
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||||
|
),
|
||||||
|
topMessageId: topMessage,
|
||||||
|
unreadMentionCount: 0,
|
||||||
|
unreadReactionCount: 0
|
||||||
|
),
|
||||||
|
pts: result.pts
|
||||||
|
))
|
||||||
|
case .savedDialog:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2043,38 +2165,71 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, ids: [MessageId]) -> Signal<Void, NoError> {
|
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, ids: [PeerAndBoundThreadId]) -> Signal<Void, NoError> {
|
||||||
let forumThreadIds = Set(ids)
|
let forumThreadIds = Set(ids)
|
||||||
|
|
||||||
if forumThreadIds.isEmpty {
|
if forumThreadIds.isEmpty {
|
||||||
return .single(Void())
|
return .single(Void())
|
||||||
} else {
|
} else {
|
||||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
var missingForumThreadIds: [PeerId: [Int32]] = [:]
|
var missingForumThreadIds: [PeerId: [Int64]] = [:]
|
||||||
for threadId in forumThreadIds {
|
for threadId in forumThreadIds {
|
||||||
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: Int64(threadId.id)) {
|
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: threadId.threadId) {
|
||||||
} else {
|
} else {
|
||||||
missingForumThreadIds[threadId.peerId, default: []].append(threadId.id)
|
missingForumThreadIds[threadId.peerId, default: []].append(threadId.threadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if missingForumThreadIds.isEmpty {
|
if missingForumThreadIds.isEmpty {
|
||||||
return .single(Void())
|
return .single(Void())
|
||||||
} else {
|
} else {
|
||||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
var signals: [Signal<(Peer, FetchedForumThreads)?, NoError>] = []
|
||||||
for (peerId, threadIds) in missingForumThreadIds {
|
for (peerId, threadIds) in missingForumThreadIds {
|
||||||
guard let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) else {
|
guard let peer = transaction.getPeer(peerId) as? TelegramChannel, let inputPeer = apiInputPeer(peer), let inputChannel = apiInputChannel(peer) else {
|
||||||
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
Logger.shared.log("State", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
|
||||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
if peer.flags.contains(.isMonoforum) {
|
||||||
return (peer, result)
|
let signal = source.request(Api.functions.messages.getSavedDialogs(flags: 1 << 1, parentPeer: inputPeer, offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100, hash: 0))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
let result = FetchedForumThreads(savedDialogs: result)
|
||||||
|
return (peer, FetchedForumThreads(
|
||||||
|
items: result.items.filter({ item -> Bool in
|
||||||
|
switch item {
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, _, _, _, _, _):
|
||||||
|
return threadIds.contains(peer.peerId.toInt64())
|
||||||
|
case .savedDialog:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
case .forum:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
totalCount: result.totalCount,
|
||||||
|
orderByDate: result.orderByDate,
|
||||||
|
pts: result.pts,
|
||||||
|
messages: result.messages,
|
||||||
|
users: result.users,
|
||||||
|
chats: result.chats
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
signals.append(signal)
|
signals.append(signal)
|
||||||
|
} else {
|
||||||
|
let signal = source.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds.map { Int32(clamping: $0) }))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
return (peer, FetchedForumThreads(forumTopics: result))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
signals.append(signal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return combineLatest(signals)
|
return combineLatest(signals)
|
||||||
@ -2089,18 +2244,18 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
let peerIsForum = peer.isForum
|
let peerIsForum = peer.isForum
|
||||||
let peerId = peer.id
|
let peerId = peer.id
|
||||||
|
|
||||||
switch result {
|
chats.append(contentsOf: result.chats)
|
||||||
case let .forumTopics(_, _, topics, messages, apiChats, apiUsers, _):
|
users.append(contentsOf: result.users)
|
||||||
chats.append(contentsOf: apiChats)
|
|
||||||
users.append(contentsOf: apiUsers)
|
|
||||||
|
|
||||||
for message in messages {
|
for message in result.messages {
|
||||||
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
||||||
storeMessages.append(message)
|
storeMessages.append(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for topic in topics {
|
for item in result.items {
|
||||||
|
switch item {
|
||||||
|
case let .forum(topic):
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||||
let _ = draft
|
let _ = draft
|
||||||
@ -2131,6 +2286,35 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
case .forumTopicDeleted:
|
case .forumTopicDeleted:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
let data = MessageHistoryThreadData(
|
||||||
|
creationDate: 0,
|
||||||
|
isOwnedByMe: true,
|
||||||
|
author: accountPeerId,
|
||||||
|
info: EngineMessageHistoryThread.Info(
|
||||||
|
title: "",
|
||||||
|
icon: nil,
|
||||||
|
iconColor: 0
|
||||||
|
),
|
||||||
|
incomingUnreadCount: unreadCount,
|
||||||
|
maxIncomingReadId: readInboxMaxId,
|
||||||
|
maxKnownMessageId: topMessage,
|
||||||
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: false,
|
||||||
|
isHidden: false,
|
||||||
|
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||||
|
)
|
||||||
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: peer.peerId.toInt64(), info: entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.replaceMessageTagSummary(peerId: peerId, threadId: peer.peerId.toInt64(), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topMessage)
|
||||||
|
transaction.replaceMessageTagSummary(peerId: peerId, threadId: peer.peerId.toInt64(), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: 0, maxId: topMessage)
|
||||||
|
case .savedDialog:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2148,13 +2332,13 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, fetchedChatList: FetchedChatList) -> Signal<FetchedChatList, NoError> {
|
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, fetchedChatList: FetchedChatList) -> Signal<FetchedChatList, NoError> {
|
||||||
var forumThreadIds = Set<MessageId>()
|
var forumThreadIds = Set<PeerAndBoundThreadId>()
|
||||||
|
|
||||||
for message in fetchedChatList.storeMessages {
|
for message in fetchedChatList.storeMessages {
|
||||||
if let threadId = message.threadId {
|
if let threadId = message.threadId {
|
||||||
if let channel = fetchedChatList.peers.peers.first(where: { $0.key == message.id.peerId })?.value as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
if let channel = fetchedChatList.peers.peers.first(where: { $0.key == message.id.peerId })?.value as? TelegramChannel, case .group = channel.info, (channel.flags.contains(.isForum) || channel.flags.contains(.isMonoforum)) {
|
||||||
forumThreadIds.insert(MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: Int32(clamping: threadId)))
|
forumThreadIds.insert(PeerAndBoundThreadId(peerId: message.id.peerId, threadId: threadId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2163,31 +2347,65 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
return .single(fetchedChatList)
|
return .single(fetchedChatList)
|
||||||
} else {
|
} else {
|
||||||
return postbox.transaction { transaction -> Signal<FetchedChatList, NoError> in
|
return postbox.transaction { transaction -> Signal<FetchedChatList, NoError> in
|
||||||
var missingForumThreadIds: [PeerId: [Int32]] = [:]
|
var missingForumThreadIds: [PeerId: [Int64]] = [:]
|
||||||
for threadId in forumThreadIds {
|
for threadId in forumThreadIds {
|
||||||
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: Int64(threadId.id)) {
|
if let _ = transaction.getMessageHistoryThreadInfo(peerId: threadId.peerId, threadId: threadId.threadId) {
|
||||||
} else {
|
} else {
|
||||||
missingForumThreadIds[threadId.peerId, default: []].append(threadId.id)
|
missingForumThreadIds[threadId.peerId, default: []].append(threadId.threadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if missingForumThreadIds.isEmpty {
|
if missingForumThreadIds.isEmpty {
|
||||||
return .single(fetchedChatList)
|
return .single(fetchedChatList)
|
||||||
} else {
|
} else {
|
||||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
var signals: [Signal<(Peer, FetchedForumThreads)?, NoError>] = []
|
||||||
for (peerId, threadIds) in missingForumThreadIds {
|
for (peerId, threadIds) in missingForumThreadIds {
|
||||||
guard let peer = fetchedChatList.peers.get(peerId), let inputChannel = apiInputChannel(peer) else {
|
guard let peer = fetchedChatList.peers.get(peerId) as? TelegramChannel, let inputPeer = apiInputPeer(peer), let inputChannel = apiInputChannel(peer) else {
|
||||||
Logger.shared.log("resolveForumThreads", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
Logger.shared.log("resolveForumThreads", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let signal = network.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds))
|
|
||||||
|> map { result -> (Peer, Api.messages.ForumTopics)? in
|
if peer.flags.contains(.isMonoforum) {
|
||||||
return (peer, result)
|
//TODO:release
|
||||||
|
let signal = source.request(Api.functions.messages.getSavedDialogs(flags: 1 << 1, parentPeer: inputPeer, offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100, hash: 0))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
let result = FetchedForumThreads(savedDialogs: result)
|
||||||
|
return (peer, FetchedForumThreads(
|
||||||
|
items: result.items.filter({ item -> Bool in
|
||||||
|
switch item {
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, _, _, _, _, _):
|
||||||
|
return threadIds.contains(peer.peerId.toInt64())
|
||||||
|
case .savedDialog:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<(Peer, Api.messages.ForumTopics)?, NoError> in
|
case .forum:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
totalCount: result.totalCount,
|
||||||
|
orderByDate: result.orderByDate,
|
||||||
|
pts: result.pts,
|
||||||
|
messages: result.messages,
|
||||||
|
users: result.users,
|
||||||
|
chats: result.chats
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
signals.append(signal)
|
signals.append(signal)
|
||||||
|
} else {
|
||||||
|
let signal = source.request(Api.functions.channels.getForumTopicsByID(channel: inputChannel, topics: threadIds.map { Int32(clamping: $0) }))
|
||||||
|
|> map { result -> (Peer, FetchedForumThreads)? in
|
||||||
|
return (peer, FetchedForumThreads(forumTopics: result))
|
||||||
|
}
|
||||||
|
|> `catch` { _ -> Signal<(Peer, FetchedForumThreads)?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
signals.append(signal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return combineLatest(signals)
|
return combineLatest(signals)
|
||||||
@ -2199,22 +2417,22 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
let peerIsForum = peer.isForum
|
let peerIsForum = peer.isForum
|
||||||
let peerId = peer.id
|
let peerId = peer.id
|
||||||
|
|
||||||
switch result {
|
fetchedChatList.peers = fetchedChatList.peers.union(with: AccumulatedPeers(chats: result.chats, users: result.users))
|
||||||
case let .forumTopics(_, _, topics, messages, chats, users, _):
|
|
||||||
fetchedChatList.peers = fetchedChatList.peers.union(with: AccumulatedPeers(chats: chats, users: users))
|
|
||||||
|
|
||||||
for message in messages {
|
for message in result.messages {
|
||||||
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
if let message = StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: peerIsForum) {
|
||||||
fetchedChatList.storeMessages.append(message)
|
fetchedChatList.storeMessages.append(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for topic in topics {
|
for item in result.items {
|
||||||
|
switch item {
|
||||||
|
case let .forum(topic):
|
||||||
switch topic {
|
switch topic {
|
||||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||||
let _ = draft
|
let _ = draft
|
||||||
|
|
||||||
fetchedChatList.threadInfos[MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)] = StoreMessageHistoryThreadData(
|
fetchedChatList.threadInfos[PeerAndBoundThreadId(peerId: peerId, threadId: Int64(id))] = StoreMessageHistoryThreadData(
|
||||||
data: MessageHistoryThreadData(
|
data: MessageHistoryThreadData(
|
||||||
creationDate: date,
|
creationDate: date,
|
||||||
isOwnedByMe: (flags & (1 << 1)) != 0,
|
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||||
@ -2239,6 +2457,35 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
case .forumTopicDeleted:
|
case .forumTopicDeleted:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case let .savedDialog(savedDialog):
|
||||||
|
switch savedDialog {
|
||||||
|
case let .monoForumDialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _):
|
||||||
|
|
||||||
|
fetchedChatList.threadInfos[PeerAndBoundThreadId(peerId: peerId, threadId: peer.peerId.toInt64())] = StoreMessageHistoryThreadData(
|
||||||
|
data: MessageHistoryThreadData(
|
||||||
|
creationDate: 0,
|
||||||
|
isOwnedByMe: true,
|
||||||
|
author: accountPeerId,
|
||||||
|
info: EngineMessageHistoryThread.Info(
|
||||||
|
title: "",
|
||||||
|
icon: nil,
|
||||||
|
iconColor: 0
|
||||||
|
),
|
||||||
|
incomingUnreadCount: unreadCount,
|
||||||
|
maxIncomingReadId: readInboxMaxId,
|
||||||
|
maxKnownMessageId: topMessage,
|
||||||
|
maxOutgoingReadId: readOutboxMaxId,
|
||||||
|
isClosed: false,
|
||||||
|
isHidden: false,
|
||||||
|
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||||
|
),
|
||||||
|
topMessageId: topMessage,
|
||||||
|
unreadMentionCount: 0,
|
||||||
|
unreadReactionCount: 0
|
||||||
|
)
|
||||||
|
case .savedDialog:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2416,7 +2663,7 @@ private func resolveAssociatedMessages(accountPeerId: PeerId, postbox: Postbox,
|
|||||||
if missingReplyMessageIds.isEmpty && missingGeneralMessageIds.isEmpty {
|
if missingReplyMessageIds.isEmpty && missingGeneralMessageIds.isEmpty {
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), reactions: reactionsFromState(state), result: state)
|
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), reactions: reactionsFromState(state), result: state)
|
||||||
|> mapToSignal { state in
|
|> mapToSignal { state in
|
||||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state)
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: .network(network), state: state)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var missingPeers = false
|
var missingPeers = false
|
||||||
@ -2518,7 +2765,7 @@ private func resolveAssociatedMessages(accountPeerId: PeerId, postbox: Postbox,
|
|||||||
|> mapToSignal { updatedState -> Signal<AccountMutableState, NoError> in
|
|> mapToSignal { updatedState -> Signal<AccountMutableState, NoError> in
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: updatedState), reactions: reactionsFromState(updatedState), result: updatedState)
|
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: updatedState), reactions: reactionsFromState(updatedState), result: updatedState)
|
||||||
|> mapToSignal { state in
|
|> mapToSignal { state in
|
||||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state)
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: .network(network), state: state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3118,7 +3365,7 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState)
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: .network(network), state: updatedState)
|
||||||
|> mapToSignal { updatedState in
|
|> mapToSignal { updatedState in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: updatedState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: updatedState)
|
||||||
|> map { updatedState -> (AccountMutableState, Bool, Int32?) in
|
|> map { updatedState -> (AccountMutableState, Bool, Int32?) in
|
||||||
@ -3443,8 +3690,8 @@ func replayFinalState(
|
|||||||
var peerIdsWithAddedSecretMessages = Set<PeerId>()
|
var peerIdsWithAddedSecretMessages = Set<PeerId>()
|
||||||
|
|
||||||
var updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:]
|
var updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:]
|
||||||
var updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:]
|
var updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:]
|
||||||
var updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]
|
var updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:]
|
||||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||||
var updatedCalls: [Api.PhoneCall] = []
|
var updatedCalls: [Api.PhoneCall] = []
|
||||||
@ -4018,28 +4265,29 @@ func replayFinalState(
|
|||||||
}
|
}
|
||||||
case .ReadGroupFeedInbox:
|
case .ReadGroupFeedInbox:
|
||||||
break
|
break
|
||||||
case let .UpdateReadThread(threadMessageId, readMaxId, isIncoming, mainChannelMessage):
|
case let .UpdateReadThread(peerId, threadId, readMaxId, isIncoming, mainChannelMessage):
|
||||||
|
let peerAndThreadId = PeerAndBoundThreadId(peerId: peerId, threadId: threadId)
|
||||||
if isIncoming {
|
if isIncoming {
|
||||||
if let currentId = updatedIncomingThreadReadStates[threadMessageId] {
|
if let currentId = updatedIncomingThreadReadStates[peerAndThreadId] {
|
||||||
if currentId < readMaxId {
|
if currentId < readMaxId {
|
||||||
updatedIncomingThreadReadStates[threadMessageId] = readMaxId
|
updatedIncomingThreadReadStates[peerAndThreadId] = readMaxId
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updatedIncomingThreadReadStates[threadMessageId] = readMaxId
|
updatedIncomingThreadReadStates[peerAndThreadId] = readMaxId
|
||||||
}
|
}
|
||||||
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
||||||
let threadId = Int64(threadMessageId.id)
|
let threadId = peerAndThreadId.threadId
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
if readMaxId > data.maxIncomingReadId {
|
if readMaxId > data.maxIncomingReadId {
|
||||||
if let toIndex = transaction.getMessage(MessageId(peerId: threadMessageId.peerId, namespace: threadMessageId.namespace, id: readMaxId))?.index {
|
if let toIndex = transaction.getMessage(MessageId(peerId: peerAndThreadId.peerId, namespace: Namespaces.Message.Cloud, id: readMaxId))?.index {
|
||||||
if let count = transaction.getThreadMessageCount(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), namespace: threadMessageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: toIndex) {
|
if let count = transaction.getThreadMessageCount(peerId: peerAndThreadId.peerId, threadId: peerAndThreadId.threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: data.maxIncomingReadId, toIndex: toIndex) {
|
||||||
data.incomingUnreadCount = max(0, data.incomingUnreadCount - Int32(count))
|
data.incomingUnreadCount = max(0, data.incomingUnreadCount - Int32(count))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let topMessageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: threadMessageId.peerId, threadId: threadId, namespaces: Set([Namespaces.Message.Cloud])) {
|
if let topMessageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: peerAndThreadId.peerId, threadId: threadId, namespaces: Set([Namespaces.Message.Cloud])) {
|
||||||
if readMaxId >= topMessageIndex.id.id {
|
if readMaxId >= topMessageIndex.id.id {
|
||||||
let containingHole = transaction.getThreadIndexHole(peerId: threadMessageId.peerId, threadId: threadId, namespace: topMessageIndex.id.namespace, containing: topMessageIndex.id.id)
|
let containingHole = transaction.getThreadIndexHole(peerId: peerAndThreadId.peerId, threadId: threadId, namespace: topMessageIndex.id.namespace, containing: topMessageIndex.id.id)
|
||||||
if let _ = containingHole[.everywhere] {
|
if let _ = containingHole[.everywhere] {
|
||||||
} else {
|
} else {
|
||||||
data.incomingUnreadCount = 0
|
data.incomingUnreadCount = 0
|
||||||
@ -4051,7 +4299,7 @@ func replayFinalState(
|
|||||||
data.maxIncomingReadId = max(data.maxIncomingReadId, readMaxId)
|
data.maxIncomingReadId = max(data.maxIncomingReadId, readMaxId)
|
||||||
|
|
||||||
if let entry = StoredMessageHistoryThreadInfo(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: peerAndThreadId.threadId, info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4073,20 +4321,20 @@ func replayFinalState(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let currentId = updatedOutgoingThreadReadStates[threadMessageId] {
|
if let currentId = updatedOutgoingThreadReadStates[peerAndThreadId] {
|
||||||
if currentId < readMaxId {
|
if currentId < readMaxId {
|
||||||
updatedOutgoingThreadReadStates[threadMessageId] = readMaxId
|
updatedOutgoingThreadReadStates[peerAndThreadId] = readMaxId
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updatedOutgoingThreadReadStates[threadMessageId] = readMaxId
|
updatedOutgoingThreadReadStates[peerAndThreadId] = readMaxId
|
||||||
}
|
}
|
||||||
if let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) {
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id))?.data.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: peerAndThreadId.threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
if readMaxId >= data.maxOutgoingReadId {
|
if readMaxId >= data.maxOutgoingReadId {
|
||||||
data.maxOutgoingReadId = readMaxId
|
data.maxOutgoingReadId = readMaxId
|
||||||
|
|
||||||
if let entry = StoredMessageHistoryThreadInfo(data) {
|
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: peerAndThreadId.threadId, info: entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4746,12 +4994,12 @@ func replayFinalState(
|
|||||||
if finalState.state.resetForumTopicLists[topicId.peerId] == nil {
|
if finalState.state.resetForumTopicLists[topicId.peerId] == nil {
|
||||||
let _ = pts
|
let _ = pts
|
||||||
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: topicId.peerId, threadId: Int64(topicId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: topicId.peerId, threadId: topicId.threadId, info: entry)
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: topicId.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
||||||
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: Int64(topicId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: topicId.peerId, threadId: topicId.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
||||||
}
|
}
|
||||||
case let .UpdateStory(peerId, story):
|
case let .UpdateStory(peerId, story):
|
||||||
var updatedPeerEntries: [StoryItemsTableEntry] = transaction.getStoryItems(peerId: peerId)
|
var updatedPeerEntries: [StoryItemsTableEntry] = transaction.getStoryItems(peerId: peerId)
|
||||||
|
@ -299,8 +299,8 @@ public final class AccountStateManager {
|
|||||||
return self.authorizationListUpdatesPipe.signal()
|
return self.authorizationListUpdatesPipe.signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
private let threadReadStateUpdatesPipe = ValuePipe<(incoming: [MessageId: MessageId.Id], outgoing: [MessageId: MessageId.Id])>()
|
private let threadReadStateUpdatesPipe = ValuePipe<(incoming: [PeerAndBoundThreadId: MessageId.Id], outgoing: [PeerAndBoundThreadId: MessageId.Id])>()
|
||||||
var threadReadStateUpdates: Signal<(incoming: [MessageId: MessageId.Id], outgoing: [MessageId: MessageId.Id]), NoError> {
|
var threadReadStateUpdates: Signal<(incoming: [PeerAndBoundThreadId: MessageId.Id], outgoing: [PeerAndBoundThreadId: MessageId.Id]), NoError> {
|
||||||
return self.threadReadStateUpdatesPipe.signal()
|
return self.threadReadStateUpdatesPipe.signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1916,7 +1916,7 @@ public final class AccountStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var threadReadStateUpdates: Signal<(incoming: [MessageId: MessageId.Id], outgoing: [MessageId: MessageId.Id]), NoError> {
|
var threadReadStateUpdates: Signal<(incoming: [PeerAndBoundThreadId: MessageId.Id], outgoing: [PeerAndBoundThreadId: MessageId.Id]), NoError> {
|
||||||
return self.impl.signalWith { impl, subscriber in
|
return self.impl.signalWith { impl, subscriber in
|
||||||
return impl.threadReadStateUpdates.start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
return impl.threadReadStateUpdates.start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
}
|
}
|
||||||
|
@ -2138,8 +2138,6 @@ public final class AccountViewTracker {
|
|||||||
var isSimpleThread = false
|
var isSimpleThread = false
|
||||||
if peerId == account.peerId {
|
if peerId == account.peerId {
|
||||||
isSimpleThread = true
|
isSimpleThread = true
|
||||||
} else if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
|
||||||
isSimpleThread = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSimpleThread {
|
if isSimpleThread {
|
||||||
|
@ -204,7 +204,7 @@ struct FetchedChatList {
|
|||||||
var pinnedItemIds: [PeerId]?
|
var pinnedItemIds: [PeerId]?
|
||||||
var folderSummaries: [PeerGroupId: PeerGroupUnreadCountersSummary]
|
var folderSummaries: [PeerGroupId: PeerGroupUnreadCountersSummary]
|
||||||
var peerGroupIds: [PeerId: PeerGroupId]
|
var peerGroupIds: [PeerId: PeerGroupId]
|
||||||
var threadInfos: [MessageId: StoreMessageHistoryThreadData]
|
var threadInfos: [PeerAndBoundThreadId: StoreMessageHistoryThreadData]
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchChatList(accountPeerId: PeerId, postbox: Postbox, network: Network, location: FetchChatListLocation, upperBound: MessageIndex, hash: Int64, limit: Int32) -> Signal<FetchedChatList?, NoError> {
|
func fetchChatList(accountPeerId: PeerId, postbox: Postbox, network: Network, location: FetchChatListLocation, upperBound: MessageIndex, hash: Int64, limit: Int32) -> Signal<FetchedChatList?, NoError> {
|
||||||
@ -398,7 +398,7 @@ func fetchChatList(accountPeerId: PeerId, postbox: Postbox, network: Network, lo
|
|||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: storeMessages, reactions: [], result: result)
|
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: storeMessages, reactions: [], result: result)
|
||||||
|> mapToSignal { result in
|
|> mapToSignal { result in
|
||||||
if let result = result {
|
if let result = result {
|
||||||
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, fetchedChatList: result)
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: .network(network), fetchedChatList: result)
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
} else {
|
} else {
|
||||||
return .single(result)
|
return .single(result)
|
||||||
|
@ -189,11 +189,12 @@ func resolveUnknownEmojiFiles<T>(postbox: Postbox, source: FetchMessageHistoryHo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, parsedPeers: AccumulatedPeers, storeMessages: [StoreMessage], _ f: @escaping (Transaction, AccumulatedPeers, [StoreMessage]) -> T) -> Signal<T, NoError> {
|
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, parsedPeers: AccumulatedPeers, storeMessages: [StoreMessage], resolveThreads: Bool, _ f: @escaping (Transaction, AccumulatedPeers, [StoreMessage]) -> T) -> Signal<T, NoError> {
|
||||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||||
var storedIds = Set<MessageId>()
|
var storedIds = Set<MessageId>()
|
||||||
var referencedReplyIds = ReferencedReplyMessageIds()
|
var referencedReplyIds = ReferencedReplyMessageIds()
|
||||||
var referencedGeneralIds = Set<MessageId>()
|
var referencedGeneralIds = Set<MessageId>()
|
||||||
|
var threadIds = Set<PeerAndBoundThreadId>()
|
||||||
for message in storeMessages {
|
for message in storeMessages {
|
||||||
guard case let .Id(id) = message.id else {
|
guard case let .Id(id) = message.id else {
|
||||||
continue
|
continue
|
||||||
@ -206,6 +207,9 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
|||||||
referencedGeneralIds.formUnion(attribute.associatedMessageIds)
|
referencedGeneralIds.formUnion(attribute.associatedMessageIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let threadId = message.threadId {
|
||||||
|
threadIds.insert(PeerAndBoundThreadId(peerId: id.peerId, threadId: threadId))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let allPossiblyStoredReferencedIds = referencedGeneralIds.union(referencedReplyIds.targetIdsBySourceId.keys)
|
let allPossiblyStoredReferencedIds = referencedGeneralIds.union(referencedReplyIds.targetIdsBySourceId.keys)
|
||||||
@ -219,11 +223,20 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
|||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: parsedPeers, result: Void())
|
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: parsedPeers, result: Void())
|
||||||
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
|
if resolveThreads && !threadIds.isEmpty {
|
||||||
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds))
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return postbox.transaction { transaction -> T in
|
return postbox.transaction { transaction -> T in
|
||||||
return f(transaction, parsedPeers, [])
|
return f(transaction, parsedPeers, [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return postbox.transaction { transaction -> T in
|
||||||
|
return f(transaction, parsedPeers, [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
||||||
@ -309,16 +322,33 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
|||||||
additionalPeers = additionalPeers.union(with: AccumulatedPeers(transaction: transaction, chats: chats, users: users))
|
additionalPeers = additionalPeers.union(with: AccumulatedPeers(transaction: transaction, chats: chats, users: users))
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, reactions: [], result: Void())
|
let combinedMessages = storeMessages + additionalMessages
|
||||||
|
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: combinedMessages, reactions: [], result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: parsedPeers.union(with: additionalPeers), result: Void())
|
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: parsedPeers.union(with: additionalPeers), result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
|
var threadIds = Set<PeerAndBoundThreadId>()
|
||||||
|
for message in combinedMessages {
|
||||||
|
if case let .Id(id) = message.id, let threadId = message.threadId {
|
||||||
|
threadIds.insert(PeerAndBoundThreadId(peerId: id.peerId, threadId: threadId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolveThreads && !threadIds.isEmpty {
|
||||||
|
return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds))
|
||||||
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
|
return postbox.transaction { transaction -> T in
|
||||||
|
return f(transaction, parsedPeers, [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return postbox.transaction { transaction -> T in
|
return postbox.transaction { transaction -> T in
|
||||||
return f(transaction, additionalPeers, additionalMessages)
|
return f(transaction, additionalPeers, additionalMessages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -916,7 +946,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: source, accountPeerId: accountPeerId, parsedPeers: parsedPeers, storeMessages: storeMessages, { transaction, additionalParsedPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
return withResolvedAssociatedMessages(postbox: postbox, source: source, accountPeerId: accountPeerId, parsedPeers: parsedPeers, storeMessages: storeMessages, resolveThreads: true, { transaction, additionalParsedPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
||||||
let _ = transaction.addMessages(storeMessages, location: .Random)
|
let _ = transaction.addMessages(storeMessages, location: .Random)
|
||||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||||
var filledRange: ClosedRange<MessageId.Id>
|
var filledRange: ClosedRange<MessageId.Id>
|
||||||
@ -1076,15 +1106,15 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
|||||||
}
|
}
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, resolveThreads: false, { transaction, additionalPeers, additionalMessages -> Void in
|
||||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: fetchedChats.peers.union(with: additionalPeers))
|
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: fetchedChats.peers.union(with: additionalPeers))
|
||||||
|
|
||||||
for (threadMessageId, data) in fetchedChats.threadInfos {
|
for (threadMessageId, data) in fetchedChats.threadInfos {
|
||||||
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, info: entry)
|
||||||
}
|
}
|
||||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
||||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
||||||
|
@ -14,7 +14,7 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
|||||||
guard let fetchedChats = fetchedChats else {
|
guard let fetchedChats = fetchedChats else {
|
||||||
return .never()
|
return .never()
|
||||||
}
|
}
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, resolveThreads: false, { transaction, additionalPeers, additionalMessages -> Void in
|
||||||
for peerId in transaction.chatListGetAllPeerIds() {
|
for peerId in transaction.chatListGetAllPeerIds() {
|
||||||
if peerId.namespace != Namespaces.Peer.SecretChat {
|
if peerId.namespace != Namespaces.Peer.SecretChat {
|
||||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||||
@ -44,10 +44,10 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
|||||||
|
|
||||||
for (threadMessageId, data) in fetchedChats.threadInfos {
|
for (threadMessageId, data) in fetchedChats.threadInfos {
|
||||||
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||||
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, info: entry)
|
||||||
}
|
}
|
||||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadMentionCount, maxId: data.topMessageId)
|
||||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: threadMessageId.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: data.unreadReactionCount, maxId: data.topMessageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
||||||
|
@ -251,7 +251,7 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
|
|||||||
}
|
}
|
||||||
if markedUnread {
|
if markedUnread {
|
||||||
pushSignal = pushSignal
|
pushSignal = pushSignal
|
||||||
|> then(network.request(Api.functions.messages.markDialogUnread(flags: 1 << 0, peer: .inputDialogPeer(peer: inputPeer)))
|
|> then(network.request(Api.functions.messages.markDialogUnread(flags: 1 << 0, parentPeer: nil, peer: .inputDialogPeer(peer: inputPeer)))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
|
|||||||
|
|
||||||
if markedUnread {
|
if markedUnread {
|
||||||
pushSignal = pushSignal
|
pushSignal = pushSignal
|
||||||
|> then(network.request(Api.functions.messages.markDialogUnread(flags: 1 << 0, peer: .inputDialogPeer(peer: inputPeer)))
|
|> then(network.request(Api.functions.messages.markDialogUnread(flags: 1 << 0, parentPeer: nil, peer: .inputDialogPeer(peer: inputPeer)))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ extension Api.Update {
|
|||||||
} else {
|
} else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
case let .updateDraftMessage(_, peer, _, _):
|
case let .updateDraftMessage(_, peer, _, _, _):
|
||||||
return [peer.peerId]
|
return [peer.peerId]
|
||||||
case let .updateNewScheduledMessage(message):
|
case let .updateNewScheduledMessage(message):
|
||||||
return apiMessagePeerIds(message)
|
return apiMessagePeerIds(message)
|
||||||
|
@ -385,7 +385,11 @@ public extension TelegramEngine.EngineData.Item {
|
|||||||
if let cachedPeerData = view.cachedData as? CachedUserData {
|
if let cachedPeerData = view.cachedData as? CachedUserData {
|
||||||
return cachedPeerData.sendPaidMessageStars
|
return cachedPeerData.sendPaidMessageStars
|
||||||
} else if let channel = peerViewMainPeer(view) as? TelegramChannel {
|
} else if let channel = peerViewMainPeer(view) as? TelegramChannel {
|
||||||
|
if channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = view.peers[linkedMonoforumId] as? TelegramChannel {
|
||||||
|
return mainChannel.sendPaidMessageStars
|
||||||
|
} else {
|
||||||
return channel.sendPaidMessageStars
|
return channel.sendPaidMessageStars
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -116,11 +116,10 @@ func _internal_togglePeerUnreadMarkInteractively(postbox: Postbox, network: Netw
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
//TODO:release monoforums
|
|
||||||
guard let peer = transaction.getPeer(peerId) else {
|
guard let peer = transaction.getPeer(peerId) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let channel = peer as? TelegramChannel, channel.flags.contains(.isForum) else {
|
guard let channel = peer as? TelegramChannel, channel.isForumOrMonoForum else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) else {
|
guard var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) else {
|
||||||
@ -138,15 +137,19 @@ func _internal_markForumThreadAsReadInteractively(transaction: Transaction, netw
|
|||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if channel.flags.contains(.isForum) {
|
||||||
if let inputPeer = apiInputPeer(channel) {
|
if let inputPeer = apiInputPeer(channel) {
|
||||||
//TODO:loc
|
|
||||||
let _ = network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: threadId), readMaxId: messageIndex.id.id)).start()
|
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_togglePeerUnreadMarkInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, peerId: PeerId, setToValue: Bool? = nil) {
|
func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, peerId: PeerId, setToValue: Bool? = nil) {
|
||||||
//TODO:release monoforums
|
|
||||||
guard let peer = transaction.getPeer(peerId) else {
|
guard let peer = transaction.getPeer(peerId) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -156,7 +159,8 @@ func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, netwo
|
|||||||
displayAsRegularChat = cachedData.viewForumAsMessages.knownValue ?? false
|
displayAsRegularChat = cachedData.viewForumAsMessages.knownValue ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isForum), !displayAsRegularChat {
|
if let channel = peer as? TelegramChannel {
|
||||||
|
if channel.isForumOrMonoForum, !displayAsRegularChat {
|
||||||
for item in transaction.getMessageHistoryThreadIndex(peerId: peerId, limit: 20) {
|
for item in transaction.getMessageHistoryThreadIndex(peerId: peerId, limit: 20) {
|
||||||
guard var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: item.threadId)?.data.get(MessageHistoryThreadData.self) else {
|
guard var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: item.threadId)?.data.get(MessageHistoryThreadData.self) else {
|
||||||
continue
|
continue
|
||||||
@ -173,10 +177,16 @@ func _internal_togglePeerUnreadMarkInteractively(transaction: Transaction, netwo
|
|||||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: item.threadId, info: entry)
|
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: item.threadId, info: entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if channel.flags.contains(.isForum) {
|
||||||
if let inputPeer = apiInputPeer(channel) {
|
if let inputPeer = apiInputPeer(channel) {
|
||||||
//TODO:loc
|
|
||||||
let _ = network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: item.threadId), readMaxId: messageIndex.id.id)).start()
|
let _ = network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: item.threadId), readMaxId: messageIndex.id.id)).start()
|
||||||
}
|
}
|
||||||
|
} else if channel.flags.contains(.isMonoforum) {
|
||||||
|
if let inputPeer = apiInputPeer(channel), let subPeer = transaction.getPeer(PeerId(item.threadId)).flatMap(apiInputPeer) {
|
||||||
|
let _ = network.request(Api.functions.messages.readSavedHistory(parentPeer: inputPeer, peer: subPeer, maxId: messageIndex.id.id)).start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,9 +20,11 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network,
|
|||||||
|
|
||||||
for update in updates {
|
for update in updates {
|
||||||
switch update {
|
switch update {
|
||||||
case let .updateDraftMessage(_, peer, topMsgId, _):
|
case let .updateDraftMessage(_, peer, topMsgId, savedPeerId, _):
|
||||||
var threadId: Int64?
|
var threadId: Int64?
|
||||||
if let topMsgId = topMsgId {
|
if let savedPeerId {
|
||||||
|
threadId = savedPeerId.peerId.toInt64()
|
||||||
|
} else if let topMsgId {
|
||||||
threadId = Int64(topMsgId)
|
threadId = Int64(topMsgId)
|
||||||
}
|
}
|
||||||
keys.insert(Key(peerId: peer.peerId, threadId: threadId))
|
keys.insert(Key(peerId: peer.peerId, threadId: threadId))
|
||||||
|
@ -6,7 +6,7 @@ import MtProtoKit
|
|||||||
|
|
||||||
|
|
||||||
func _internal_markAllChatsAsRead(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
func _internal_markAllChatsAsRead(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||||
return network.request(Api.functions.messages.getDialogUnreadMarks())
|
return network.request(Api.functions.messages.getDialogUnreadMarks(flags: 0, parentPeer: nil))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<[Api.DialogPeer]?, NoError> in
|
|> `catch` { _ -> Signal<[Api.DialogPeer]?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
|
@ -138,7 +138,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let value = outgoing[referencedMessageId] {
|
if let value = outgoing[PeerAndBoundThreadId(peerId: referencedMessageId.peerId, threadId: Int64(referencedMessageId.id))] {
|
||||||
strongSelf.maxReadOutgoingMessageIdValue = MessageId(peerId: data.peerId, namespace: Namespaces.Message.Cloud, id: value)
|
strongSelf.maxReadOutgoingMessageIdValue = MessageId(peerId: data.peerId, namespace: Namespaces.Message.Cloud, id: value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -338,7 +338,11 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
|
|
||||||
let account = self.account
|
let account = self.account
|
||||||
|
|
||||||
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, MessageId?, Int?) in
|
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, Api.InputPeer?, MessageId?, Int?) in
|
||||||
|
guard let peer = transaction.getPeer(peerId) else {
|
||||||
|
return (nil, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||||
if messageIndex.id.id >= data.maxIncomingReadId {
|
if messageIndex.id.id >= data.maxIncomingReadId {
|
||||||
if let count = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
if let count = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
||||||
@ -364,6 +368,10 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var subPeerId: Api.InputPeer?
|
||||||
|
if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum) {
|
||||||
|
subPeerId = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer)
|
||||||
|
} else {
|
||||||
let referencedMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
|
let referencedMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
|
||||||
if let message = transaction.getMessage(referencedMessageId) {
|
if let message = transaction.getMessage(referencedMessageId) {
|
||||||
for attribute in message.attributes {
|
for attribute in message.attributes {
|
||||||
@ -400,19 +408,19 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let inputPeer = transaction.getPeer(messageIndex.id.peerId).flatMap(apiInputPeer)
|
let inputPeer = transaction.getPeer(messageIndex.id.peerId).flatMap(apiInputPeer)
|
||||||
let readCount = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: fromIdExclusive, toIndex: toIndex)
|
let readCount = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: fromIdExclusive, toIndex: toIndex)
|
||||||
let topMessageId = transaction.getMessagesWithThreadId(peerId: peerId, namespace: Namespaces.Message.Cloud, threadId: threadId, from: MessageIndex.upperBound(peerId: peerId, namespace: Namespaces.Message.Cloud), includeFrom: false, to: MessageIndex.lowerBound(peerId: peerId, namespace: Namespaces.Message.Cloud), limit: 1).first?.id
|
let topMessageId = transaction.getMessagesWithThreadId(peerId: peerId, namespace: Namespaces.Message.Cloud, threadId: threadId, from: MessageIndex.upperBound(peerId: peerId, namespace: Namespaces.Message.Cloud), includeFrom: false, to: MessageIndex.lowerBound(peerId: peerId, namespace: Namespaces.Message.Cloud), limit: 1).first?.id
|
||||||
|
|
||||||
return (inputPeer, topMessageId, readCount)
|
return (inputPeer, subPeerId, topMessageId, readCount)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] inputPeer, topMessageId, readCount in
|
|> deliverOnMainQueue).start(next: { [weak self] inputPeer, subPeerId, topMessageId, readCount in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
guard let inputPeer else {
|
||||||
guard let inputPeer = inputPeer else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +456,16 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let subPeerId {
|
||||||
|
let signal = strongSelf.account.network.request(Api.functions.messages.readSavedHistory(parentPeer: inputPeer, peer: subPeerId, maxId: messageIndex.id.id))
|
||||||
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
|
return .single(.boolFalse)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
if revalidate {
|
||||||
|
}
|
||||||
|
strongSelf.readDisposable.set(signal.start())
|
||||||
|
} else {
|
||||||
var signal = strongSelf.account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: threadId), readMaxId: messageIndex.id.id))
|
var signal = strongSelf.account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: threadId), readMaxId: messageIndex.id.id))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .single(.boolFalse)
|
return .single(.boolFalse)
|
||||||
@ -481,6 +499,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
|> then(validateSignal)
|
|> then(validateSignal)
|
||||||
}
|
}
|
||||||
strongSelf.readDisposable.set(signal.start())
|
strongSelf.readDisposable.set(signal.start())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||||||
subPeer = transaction.getPeer(PeerId(threadId))
|
subPeer = transaction.getPeer(PeerId(threadId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (peer: peer, additionalPeer: additionalPeer, from: fromId.flatMap(transaction.getPeer), subPeer)
|
return (peer: peer, additionalPeer: additionalPeer, from: fromId.flatMap(transaction.getPeer), subPeer: subPeer)
|
||||||
}
|
}
|
||||||
|> mapToSignal { values -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
|> mapToSignal { values -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
||||||
guard let values = values else {
|
guard let values = values else {
|
||||||
@ -408,7 +408,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||||||
} else {
|
} else {
|
||||||
let lowerBound = state?.main.messages.last.flatMap({ $0.index })
|
let lowerBound = state?.main.messages.last.flatMap({ $0.index })
|
||||||
let signal: Signal<Api.messages.Messages, MTRpcError>
|
let signal: Signal<Api.messages.Messages, MTRpcError>
|
||||||
if peer.id.namespace == Namespaces.Peer.CloudChannel && query.isEmpty && fromId == nil && tags == nil && minDate == nil && maxDate == nil {
|
if peer.id.namespace == Namespaces.Peer.CloudChannel && query.isEmpty && fromId == nil && tags == nil && minDate == nil && maxDate == nil && threadId == nil {
|
||||||
signal = account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: lowerBound?.id.id ?? 0, offsetDate: 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
signal = account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: lowerBound?.id.id ?? 0, offsetDate: 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||||
} else {
|
} else {
|
||||||
var savedReactions: [Api.Reaction]?
|
var savedReactions: [Api.Reaction]?
|
||||||
|
@ -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, channel.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.adminRights != nil, case .peer = item.chatLocation {
|
||||||
if incoming {
|
if incoming {
|
||||||
needsShareButton = true
|
needsShareButton = true
|
||||||
}
|
}
|
||||||
|
@ -324,6 +324,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible
|
|||||||
if case .replyThread = chatLocation {
|
if case .replyThread = chatLocation {
|
||||||
displayAuthorInfo = false
|
displayAuthorInfo = false
|
||||||
} else {
|
} else {
|
||||||
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {
|
||||||
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)] {
|
||||||
@ -333,6 +334,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.effectiveAuthorId = effectiveAuthor?.id
|
self.effectiveAuthorId = effectiveAuthor?.id
|
||||||
|
|
||||||
|
@ -574,6 +574,7 @@ private final class PeerInfoInteraction {
|
|||||||
let editingOpenStars: () -> Void
|
let editingOpenStars: () -> Void
|
||||||
let openParticipantsSection: (PeerInfoParticipantsSection) -> Void
|
let openParticipantsSection: (PeerInfoParticipantsSection) -> Void
|
||||||
let openRecentActions: () -> Void
|
let openRecentActions: () -> Void
|
||||||
|
let openChannelMessages: () -> Void
|
||||||
let openStats: (ChannelStatsSection) -> Void
|
let openStats: (ChannelStatsSection) -> Void
|
||||||
let editingOpenPreHistorySetup: () -> Void
|
let editingOpenPreHistorySetup: () -> Void
|
||||||
let editingOpenAutoremoveMesages: () -> Void
|
let editingOpenAutoremoveMesages: () -> Void
|
||||||
@ -647,6 +648,7 @@ private final class PeerInfoInteraction {
|
|||||||
editingOpenStars: @escaping () -> Void,
|
editingOpenStars: @escaping () -> Void,
|
||||||
openParticipantsSection: @escaping (PeerInfoParticipantsSection) -> Void,
|
openParticipantsSection: @escaping (PeerInfoParticipantsSection) -> Void,
|
||||||
openRecentActions: @escaping () -> Void,
|
openRecentActions: @escaping () -> Void,
|
||||||
|
openChannelMessages: @escaping () -> Void,
|
||||||
openStats: @escaping (ChannelStatsSection) -> Void,
|
openStats: @escaping (ChannelStatsSection) -> Void,
|
||||||
editingOpenPreHistorySetup: @escaping () -> Void,
|
editingOpenPreHistorySetup: @escaping () -> Void,
|
||||||
editingOpenAutoremoveMesages: @escaping () -> Void,
|
editingOpenAutoremoveMesages: @escaping () -> Void,
|
||||||
@ -719,6 +721,7 @@ private final class PeerInfoInteraction {
|
|||||||
self.editingOpenStars = editingOpenStars
|
self.editingOpenStars = editingOpenStars
|
||||||
self.openParticipantsSection = openParticipantsSection
|
self.openParticipantsSection = openParticipantsSection
|
||||||
self.openRecentActions = openRecentActions
|
self.openRecentActions = openRecentActions
|
||||||
|
self.openChannelMessages = openChannelMessages
|
||||||
self.openStats = openStats
|
self.openStats = openStats
|
||||||
self.editingOpenPreHistorySetup = editingOpenPreHistorySetup
|
self.editingOpenPreHistorySetup = editingOpenPreHistorySetup
|
||||||
self.editingOpenAutoremoveMesages = editingOpenAutoremoveMesages
|
self.editingOpenAutoremoveMesages = editingOpenAutoremoveMesages
|
||||||
@ -2166,8 +2169,9 @@ private func editingItems(data: PeerInfoScreenData?, boostStatus: ChannelBoostSt
|
|||||||
let ItemBanned = 11
|
let ItemBanned = 11
|
||||||
let ItemRecentActions = 12
|
let ItemRecentActions = 12
|
||||||
let ItemAffiliatePrograms = 13
|
let ItemAffiliatePrograms = 13
|
||||||
//let ItemPostSuggestionsSettings = 14
|
let ItemPostSuggestionsSettings = 14
|
||||||
let ItemPeerAutoTranslate = 15
|
let ItemPeerAutoTranslate = 15
|
||||||
|
let ItemChannelMessages = 16
|
||||||
|
|
||||||
let isCreator = channel.flags.contains(.isCreator)
|
let isCreator = channel.flags.contains(.isCreator)
|
||||||
|
|
||||||
@ -2216,9 +2220,9 @@ private func editingItems(data: PeerInfoScreenData?, boostStatus: ChannelBoostSt
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
/*items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text("Off"), additionalBadgeLabel: presentationData.strings.Settings_New, text: "Post Suggestions", icon: UIImage(bundleImageName: "Chat/Info/PostSuggestionsIcon"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text(channel.linkedMonoforumId == nil ? "Off" : "On"), additionalBadgeLabel: presentationData.strings.Settings_New, text: "Message Channel", icon: UIImage(bundleImageName: "Chat/Info/PostSuggestionsIcon"), action: {
|
||||||
interaction.editingOpenPostSuggestionsSetup()
|
interaction.editingOpenPostSuggestionsSetup()
|
||||||
}))*/
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if isCreator || (channel.adminRights?.rights.contains(.canChangeInfo) == true) {
|
if isCreator || (channel.adminRights?.rights.contains(.canChangeInfo) == true) {
|
||||||
@ -2351,6 +2355,13 @@ private func editingItems(data: PeerInfoScreenData?, boostStatus: ChannelBoostSt
|
|||||||
items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemRecentActions, label: .none, text: presentationData.strings.Group_Info_AdminLog, icon: UIImage(bundleImageName: "Chat/Info/RecentActionsIcon"), action: {
|
items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemRecentActions, label: .none, text: presentationData.strings.Group_Info_AdminLog, icon: UIImage(bundleImageName: "Chat/Info/RecentActionsIcon"), action: {
|
||||||
interaction.openRecentActions()
|
interaction.openRecentActions()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
if channel.linkedMonoforumId != nil {
|
||||||
|
//TODO:localize
|
||||||
|
items[.peerAdditionalSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemChannelMessages, label: .none, text: "Channel Messages", icon: UIImage(bundleImageName: "Chat/Info/RecentActionsIcon"), action: {
|
||||||
|
interaction.openChannelMessages()
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.hasPermission(.changeInfo) {
|
if channel.hasPermission(.changeInfo) {
|
||||||
@ -3043,6 +3054,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
openRecentActions: { [weak self] in
|
openRecentActions: { [weak self] in
|
||||||
self?.openRecentActions()
|
self?.openRecentActions()
|
||||||
},
|
},
|
||||||
|
openChannelMessages: { [weak self] in
|
||||||
|
self?.openChannelMessages()
|
||||||
|
},
|
||||||
openStats: { [weak self] section in
|
openStats: { [weak self] section in
|
||||||
self?.openStats(section: section)
|
self?.openStats(section: section)
|
||||||
},
|
},
|
||||||
@ -9295,6 +9309,23 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
self.controller?.push(controller)
|
self.controller?.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func openChannelMessages() {
|
||||||
|
guard let channel = self.data?.peer as? TelegramChannel, let linkedMonoforumId = channel.linkedMonoforumId else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = (self.context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Peer.Peer(id: linkedMonoforumId)
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
|
||||||
|
guard let self, let peer else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController {
|
||||||
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private func editingOpenPreHistorySetup() {
|
private func editingOpenPreHistorySetup() {
|
||||||
guard let data = self.data, let peer = data.peer else {
|
guard let data = self.data, let peer = data.peer else {
|
||||||
return
|
return
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -603,6 +603,7 @@ func updateChatPresentationInterfaceStateImpl(
|
|||||||
selfController.chatLocation = selfController.presentationInterfaceState.chatLocation
|
selfController.chatLocation = selfController.presentationInterfaceState.chatLocation
|
||||||
selfController.reloadChatLocation()
|
selfController.reloadChatLocation()
|
||||||
selfController.reloadCachedData()
|
selfController.reloadCachedData()
|
||||||
|
selfController.setupChatHistoryNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
selfController.updateDownButtonVisibility()
|
selfController.updateDownButtonVisibility()
|
||||||
|
@ -543,7 +543,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var hasEmbeddedTitleContent = false
|
var hasEmbeddedTitleContent = false
|
||||||
var isEmbeddedTitleContentHidden = false
|
var isEmbeddedTitleContentHidden = false
|
||||||
|
|
||||||
let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
var chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||||
|
|
||||||
weak var attachmentController: AttachmentController?
|
weak var attachmentController: AttachmentController?
|
||||||
|
|
||||||
@ -7921,7 +7921,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 channel.adminRights != nil, let sendAsPeerId = self.presentationInterfaceState.currentSendAsPeerId {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = self.presentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, let sendAsPeerId = self.presentationInterfaceState.currentSendAsPeerId {
|
||||||
attributes.append(SendAsMessageAttribute(peerId: sendAsPeerId))
|
attributes.append(SendAsMessageAttribute(peerId: sendAsPeerId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ class HistoryNodeContainer: ASDisplayNode {
|
|||||||
class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
private(set) var chatLocation: ChatLocation
|
private(set) var chatLocation: ChatLocation
|
||||||
private let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
private var chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||||
let controllerInteraction: ChatControllerInteraction
|
let controllerInteraction: ChatControllerInteraction
|
||||||
private weak var controller: ChatControllerImpl?
|
private weak var controller: ChatControllerImpl?
|
||||||
|
|
||||||
@ -4914,6 +4914,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
self.chatLocation = chatLocation
|
self.chatLocation = chatLocation
|
||||||
|
|
||||||
|
self.chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||||
let historyNode = ChatHistoryListNodeImpl(
|
let historyNode = ChatHistoryListNodeImpl(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
updatedPresentationData: self.controller?.updatedPresentationData ?? (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData),
|
updatedPresentationData: self.controller?.updatedPresentationData ?? (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData),
|
||||||
|
@ -102,7 +102,7 @@ func chatHistoryViewForLocation(
|
|||||||
if tag != nil {
|
if tag != nil {
|
||||||
requestAroundId = true
|
requestAroundId = true
|
||||||
}
|
}
|
||||||
if case let .replyThread(message) = chatLocation, (message.peerId == context.account.peerId || message.isMonoforumPost) {
|
if case let .replyThread(message) = chatLocation, (message.peerId == context.account.peerId) {
|
||||||
preFixedReadState = .peer([:])
|
preFixedReadState = .peer([:])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,12 +151,14 @@ func chatHistoryViewForLocation(
|
|||||||
var scrollPosition: ChatHistoryViewScrollPosition?
|
var scrollPosition: ChatHistoryViewScrollPosition?
|
||||||
|
|
||||||
let canScrollToRead: Bool
|
let canScrollToRead: Bool
|
||||||
if case let .replyThread(message) = chatLocation, !message.isForumPost {
|
if case let .replyThread(message) = chatLocation, !message.isForumPost, !message.isMonoforumPost {
|
||||||
if message.peerId == context.account.peerId {
|
if message.peerId == context.account.peerId {
|
||||||
canScrollToRead = false
|
canScrollToRead = false
|
||||||
} else {
|
} else {
|
||||||
canScrollToRead = true
|
canScrollToRead = true
|
||||||
}
|
}
|
||||||
|
} else if case let .replyThread(message) = chatLocation, message.isMonoforumPost {
|
||||||
|
canScrollToRead = true
|
||||||
} else if view.isAddedToChatList {
|
} else if view.isAddedToChatList {
|
||||||
canScrollToRead = true
|
canScrollToRead = true
|
||||||
} else {
|
} else {
|
||||||
|
@ -344,6 +344,8 @@ func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceS
|
|||||||
}
|
}
|
||||||
if case .broadcast = channel.info {
|
if case .broadcast = channel.info {
|
||||||
canReply = true
|
canReply = true
|
||||||
|
} else if channel.isMonoForum {
|
||||||
|
canReply = true
|
||||||
}
|
}
|
||||||
} else if let group = peer as? TelegramGroup {
|
} else if let group = peer as? TelegramGroup {
|
||||||
if case .Member = group.membership {
|
if case .Member = group.membership {
|
||||||
|
@ -230,7 +230,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
|
|
||||||
if channel.flags.contains(.isMonoforum) {
|
if channel.flags.contains(.isMonoforum) {
|
||||||
if channel.adminRights != nil, case .peer = chatPresentationInterfaceState.chatLocation {
|
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, 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) {
|
||||||
|
@ -99,6 +99,16 @@ func rightNavigationButtonForChatInterfaceState(context: AccountContext, present
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let channel = presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isMonoForum, case .peer = presentationInterfaceState.chatLocation {
|
||||||
|
if case .search(false) = currentButton?.action {
|
||||||
|
return currentButton
|
||||||
|
} else {
|
||||||
|
let buttonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationCompactSearchIcon(presentationInterfaceState.theme), style: .plain, target: target, action: selector)
|
||||||
|
buttonItem.accessibilityLabel = strings.Conversation_Search
|
||||||
|
return ChatNavigationButton(action: .search(hasTags: false), buttonItem: buttonItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let channel = presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, let moreInfoNavigationButton = moreInfoNavigationButton {
|
if let channel = presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, let moreInfoNavigationButton = moreInfoNavigationButton {
|
||||||
if case .replyThread = presentationInterfaceState.chatLocation {
|
if case .replyThread = presentationInterfaceState.chatLocation {
|
||||||
} else {
|
} else {
|
||||||
|
@ -232,7 +232,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, channel.adminRights != nil {
|
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 {
|
||||||
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 {
|
||||||
@ -253,8 +253,7 @@ func sidePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, channel.adminRights != nil {
|
|
||||||
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
|
||||||
if case .side = topicListDisplayMode {
|
if case .side = topicListDisplayMode {
|
||||||
return AnyComponentWithIdentity(
|
return AnyComponentWithIdentity(
|
||||||
|
@ -108,9 +108,9 @@ private final class OverlayTransitionContainerController: ViewController, Standa
|
|||||||
public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTransitionNode, ChatMessageTransitionProtocol {
|
public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTransitionNode, ChatMessageTransitionProtocol {
|
||||||
static let animationDuration: Double = 0.3
|
static let animationDuration: Double = 0.3
|
||||||
|
|
||||||
static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
public static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
||||||
static let verticalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(verticalAnimationControlPoints.0, verticalAnimationControlPoints.1, verticalAnimationControlPoints.2, verticalAnimationControlPoints.3)
|
public static let verticalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(verticalAnimationControlPoints.0, verticalAnimationControlPoints.1, verticalAnimationControlPoints.2, verticalAnimationControlPoints.3)
|
||||||
static let horizontalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(0.23, 1.0, 0.32, 1.0)
|
public static let horizontalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(0.23, 1.0, 0.32, 1.0)
|
||||||
|
|
||||||
final class ReplyPanel {
|
final class ReplyPanel {
|
||||||
let titleNode: ASDisplayNode
|
let titleNode: ASDisplayNode
|
||||||
|
@ -15,6 +15,173 @@ import SwiftSignalKit
|
|||||||
import BundleIconComponent
|
import BundleIconComponent
|
||||||
import AvatarNode
|
import AvatarNode
|
||||||
|
|
||||||
|
private final class CustomBadgeComponent: Component {
|
||||||
|
public let text: String
|
||||||
|
public let font: UIFont
|
||||||
|
public let background: UIColor
|
||||||
|
public let foreground: UIColor
|
||||||
|
public let insets: UIEdgeInsets
|
||||||
|
|
||||||
|
public init(
|
||||||
|
text: String,
|
||||||
|
font: UIFont,
|
||||||
|
background: UIColor,
|
||||||
|
foreground: UIColor,
|
||||||
|
insets: UIEdgeInsets,
|
||||||
|
) {
|
||||||
|
self.text = text
|
||||||
|
self.font = font
|
||||||
|
self.background = background
|
||||||
|
self.foreground = foreground
|
||||||
|
self.insets = insets
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: CustomBadgeComponent, rhs: CustomBadgeComponent) -> Bool {
|
||||||
|
if lhs.text != rhs.text {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.font != rhs.font {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.background != rhs.background {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.foreground != rhs.foreground {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.insets != rhs.insets {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct TextLayout {
|
||||||
|
var size: CGSize
|
||||||
|
var opticalBounds: CGRect
|
||||||
|
|
||||||
|
init(size: CGSize, opticalBounds: CGRect) {
|
||||||
|
self.size = size
|
||||||
|
self.opticalBounds = opticalBounds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class View: UIView {
|
||||||
|
private let backgroundView: UIImageView
|
||||||
|
private let textContentsView: UIImageView
|
||||||
|
|
||||||
|
private var textLayout: TextLayout?
|
||||||
|
|
||||||
|
private var component: CustomBadgeComponent?
|
||||||
|
|
||||||
|
override public init(frame: CGRect) {
|
||||||
|
self.backgroundView = UIImageView()
|
||||||
|
|
||||||
|
self.textContentsView = UIImageView()
|
||||||
|
self.textContentsView.layer.anchorPoint = CGPoint()
|
||||||
|
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.addSubview(self.backgroundView)
|
||||||
|
self.addSubview(self.textContentsView)
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(component: CustomBadgeComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
let previousComponent = self.component
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
if component.text != previousComponent?.text || component.font != previousComponent?.font {
|
||||||
|
let attributedText = NSAttributedString(string: component.text, attributes: [
|
||||||
|
NSAttributedString.Key.font: component.font,
|
||||||
|
NSAttributedString.Key.foregroundColor: UIColor.white
|
||||||
|
])
|
||||||
|
|
||||||
|
var boundingRect = attributedText.boundingRect(with: availableSize, options: .usesLineFragmentOrigin, context: nil)
|
||||||
|
boundingRect.size.width = ceil(boundingRect.size.width)
|
||||||
|
boundingRect.size.height = ceil(boundingRect.size.height)
|
||||||
|
|
||||||
|
if let context = DrawingContext(size: boundingRect.size, scale: 0.0, opaque: false, clear: true) {
|
||||||
|
context.withContext { c in
|
||||||
|
UIGraphicsPushContext(c)
|
||||||
|
defer {
|
||||||
|
UIGraphicsPopContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
attributedText.draw(at: CGPoint())
|
||||||
|
}
|
||||||
|
var minFilledLineY = Int(context.scaledSize.height) - 1
|
||||||
|
var maxFilledLineY = 0
|
||||||
|
var minFilledLineX = Int(context.scaledSize.width) - 1
|
||||||
|
var maxFilledLineX = 0
|
||||||
|
for y in 0 ..< Int(context.scaledSize.height) {
|
||||||
|
let linePtr = context.bytes.advanced(by: max(0, y) * context.bytesPerRow).assumingMemoryBound(to: UInt32.self)
|
||||||
|
|
||||||
|
for x in 0 ..< Int(context.scaledSize.width) {
|
||||||
|
let pixelPtr = linePtr.advanced(by: x)
|
||||||
|
if pixelPtr.pointee != 0 {
|
||||||
|
minFilledLineY = min(y, minFilledLineY)
|
||||||
|
maxFilledLineY = max(y, maxFilledLineY)
|
||||||
|
minFilledLineX = min(x, minFilledLineX)
|
||||||
|
maxFilledLineX = max(x, maxFilledLineX)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var opticalBounds = CGRect()
|
||||||
|
if minFilledLineX <= maxFilledLineX && minFilledLineY <= maxFilledLineY {
|
||||||
|
opticalBounds.origin.x = CGFloat(minFilledLineX) / context.scale
|
||||||
|
opticalBounds.origin.y = CGFloat(minFilledLineY) / context.scale
|
||||||
|
opticalBounds.size.width = CGFloat(maxFilledLineX - minFilledLineX) / context.scale
|
||||||
|
opticalBounds.size.height = CGFloat(maxFilledLineY - minFilledLineY) / context.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
self.textContentsView.image = context.generateImage()?.withRenderingMode(.alwaysTemplate)
|
||||||
|
self.textLayout = TextLayout(size: boundingRect.size, opticalBounds: opticalBounds)
|
||||||
|
} else {
|
||||||
|
self.textLayout = TextLayout(size: boundingRect.size, opticalBounds: CGRect(origin: CGPoint(), size: boundingRect.size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let textSize = self.textLayout?.size ?? CGSize(width: 1.0, height: 1.0)
|
||||||
|
|
||||||
|
var size = CGSize(width: textSize.width + component.insets.left + component.insets.right, height: textSize.height + component.insets.top + component.insets.bottom)
|
||||||
|
size.width = max(size.width, size.height)
|
||||||
|
|
||||||
|
let backgroundFrame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
transition.setFrame(view: self.backgroundView, frame: backgroundFrame)
|
||||||
|
|
||||||
|
let textFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) * 0.5), y: component.insets.top + UIScreenPixel), size: textSize)
|
||||||
|
/*if let textLayout = self.textLayout {
|
||||||
|
textFrame.origin.x = textLayout.opticalBounds.minX + floorToScreenPixels((backgroundFrame.width - textLayout.opticalBounds.width) * 0.5)
|
||||||
|
textFrame.origin.y = textLayout.opticalBounds.minY + floorToScreenPixels((backgroundFrame.height - textLayout.opticalBounds.height) * 0.5)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
transition.setPosition(view: self.textContentsView, position: textFrame.origin)
|
||||||
|
self.textContentsView.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
||||||
|
|
||||||
|
if size.height != self.backgroundView.image?.size.height {
|
||||||
|
self.backgroundView.image = generateStretchableFilledCircleImage(diameter: size.height, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.backgroundView.tintColor = component.background
|
||||||
|
self.textContentsView.tintColor = component.foreground
|
||||||
|
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeView() -> View {
|
||||||
|
return View(frame: CGRect())
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, ASScrollViewDelegate {
|
final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, ASScrollViewDelegate {
|
||||||
private struct Params: Equatable {
|
private struct Params: Equatable {
|
||||||
var width: CGFloat
|
var width: CGFloat
|
||||||
@ -82,6 +249,7 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C
|
|||||||
private let icon = ComponentView<Empty>()
|
private let icon = ComponentView<Empty>()
|
||||||
private var avatarNode: AvatarNode?
|
private var avatarNode: AvatarNode?
|
||||||
private let title = ComponentView<Empty>()
|
private let title = ComponentView<Empty>()
|
||||||
|
private var badge: ComponentView<Empty>?
|
||||||
|
|
||||||
init(context: AccountContext, action: @escaping (() -> Void), contextGesture: @escaping (ContextGesture, ContextExtractedContentContainingNode) -> Void) {
|
init(context: AccountContext, action: @escaping (() -> Void), contextGesture: @escaping (ContextGesture, ContextExtractedContentContainingNode) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -146,7 +314,10 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C
|
|||||||
}
|
}
|
||||||
|
|
||||||
func update(context: AccountContext, item: Item, isSelected: Bool, theme: PresentationTheme, height: CGFloat, transition: ComponentTransition) -> CGSize {
|
func update(context: AccountContext, item: Item, isSelected: Bool, theme: PresentationTheme, height: CGFloat, transition: ComponentTransition) -> CGSize {
|
||||||
|
let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.25)
|
||||||
|
|
||||||
let spacing: CGFloat = 3.0
|
let spacing: CGFloat = 3.0
|
||||||
|
let badgeSpacing: CGFloat = 4.0
|
||||||
|
|
||||||
let avatarIconContent: EmojiStatusComponent.Content
|
let avatarIconContent: EmojiStatusComponent.Content
|
||||||
if case let .forum(topicId) = item.item.id, topicId != 1, let threadData = item.item.threadData {
|
if case let .forum(topicId) = item.item.id, topicId != 1, let threadData = item.item.threadData {
|
||||||
@ -184,7 +355,37 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C
|
|||||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
let contentSize: CGFloat = iconSize.width + spacing + titleSize.width
|
var badgeSize: CGSize?
|
||||||
|
if let readCounters = item.item.readCounters, readCounters.count > 0 {
|
||||||
|
let badge: ComponentView<Empty>
|
||||||
|
var badgeTransition = transition
|
||||||
|
if let current = self.badge {
|
||||||
|
badge = current
|
||||||
|
} else {
|
||||||
|
badgeTransition = .immediate
|
||||||
|
badge = ComponentView<Empty>()
|
||||||
|
self.badge = badge
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeSize = badge.update(
|
||||||
|
transition: badgeTransition,
|
||||||
|
component: AnyComponent(CustomBadgeComponent(
|
||||||
|
text: "\(readCounters.count)",
|
||||||
|
font: Font.regular(12.0),
|
||||||
|
background: theme.list.itemCheckColors.fillColor,
|
||||||
|
foreground: theme.list.itemCheckColors.foregroundColor,
|
||||||
|
insets: UIEdgeInsets(top: 1.0, left: 5.0, bottom: 2.0, right: 5.0)
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var contentSize: CGFloat = iconSize.width + spacing + titleSize.width
|
||||||
|
if let badgeSize {
|
||||||
|
contentSize += badgeSpacing + badgeSize.width
|
||||||
|
}
|
||||||
|
|
||||||
let size = CGSize(width: contentSize, height: height)
|
let size = CGSize(width: contentSize, height: height)
|
||||||
|
|
||||||
let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: 5.0 + floor((size.height - iconSize.height) * 0.5)), size: iconSize)
|
let iconFrame = CGRect(origin: CGPoint(x: 0.0, y: 5.0 + floor((size.height - iconSize.height) * 0.5)), size: iconSize)
|
||||||
@ -233,6 +434,33 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C
|
|||||||
titleView.frame = titleFrame
|
titleView.frame = titleFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let badgeSize, let badge = self.badge {
|
||||||
|
let badgeFrame = CGRect(origin: CGPoint(x: titleFrame.maxX + badgeSpacing, y: titleFrame.minY + floorToScreenPixels((titleFrame.height - badgeSize.height) * 0.5)), size: badgeSize)
|
||||||
|
|
||||||
|
if let badgeView = badge.view {
|
||||||
|
if badgeView.superview == nil {
|
||||||
|
badgeView.isUserInteractionEnabled = false
|
||||||
|
self.containerButton.addSubview(badgeView)
|
||||||
|
badgeView.frame = badgeFrame
|
||||||
|
badgeView.alpha = 0.0
|
||||||
|
}
|
||||||
|
transition.setPosition(view: badgeView, position: badgeFrame.center)
|
||||||
|
transition.setBounds(view: badgeView, bounds: CGRect(origin: CGPoint(), size: badgeFrame.size))
|
||||||
|
transition.setScale(view: badgeView, scale: 1.0)
|
||||||
|
alphaTransition.setAlpha(view: badgeView, alpha: 1.0)
|
||||||
|
}
|
||||||
|
} else if let badge = self.badge {
|
||||||
|
self.badge = nil
|
||||||
|
if let badgeView = badge.view {
|
||||||
|
let badgeFrame = CGRect(origin: CGPoint(x: titleFrame.maxX + badgeSpacing, y: titleFrame.minX + floorToScreenPixels((titleFrame.height - badgeView.bounds.height) * 0.5)), size: badgeView.bounds.size)
|
||||||
|
transition.setPosition(view: badgeView, position: badgeFrame.center)
|
||||||
|
transition.setScale(view: badgeView, scale: 0.001)
|
||||||
|
alphaTransition.setAlpha(view: badgeView, alpha: 0.0, completion: { [weak badgeView] _ in
|
||||||
|
badgeView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
transition.setFrame(view: self.containerButton, frame: CGRect(origin: CGPoint(), size: size))
|
transition.setFrame(view: self.containerButton, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: size)
|
self.extractedContainerNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
@ -563,7 +791,8 @@ final class ChatTopicListTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, C
|
|||||||
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: EnginePeerReadCounters(
|
||||||
|
incomingReadId: 0, outgoingReadId: 0, count: Int32(item.unreadCount), markedUnread: false),
|
||||||
isMuted: false,
|
isMuted: false,
|
||||||
draft: sourceId == accountPeerId ? draft : nil,
|
draft: sourceId == accountPeerId ? draft : nil,
|
||||||
threadData: nil,
|
threadData: nil,
|
||||||
|
@ -28,7 +28,19 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
|
|
||||||
var viewForumAsMessages: Signal<Bool, NoError> = .single(false)
|
var viewForumAsMessages: Signal<Bool, NoError> = .single(false)
|
||||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum) {
|
||||||
|
if let linkedMonoforumId = channel.linkedMonoforumId {
|
||||||
|
viewForumAsMessages = params.context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Peer.Peer(id: linkedMonoforumId)
|
||||||
|
)
|
||||||
|
|> map { peer -> Bool in
|
||||||
|
guard case let .channel(channel) = peer else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return channel.adminRights == nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
viewForumAsMessages = .single(false)
|
viewForumAsMessages = .single(false)
|
||||||
|
}
|
||||||
} else if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
} else if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||||
viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)])
|
viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)])
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -54,11 +66,6 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
let _ = (viewForumAsMessages
|
let _ = (viewForumAsMessages
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { viewForumAsMessages in
|
|> deliverOnMainQueue).start(next: { viewForumAsMessages in
|
||||||
var viewForumAsMessages = viewForumAsMessages
|
|
||||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isMonoforum), channel.adminRights == nil {
|
|
||||||
viewForumAsMessages = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum), !viewForumAsMessages {
|
if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum), !viewForumAsMessages {
|
||||||
for controller in params.navigationController.viewControllers.reversed() {
|
for controller in params.navigationController.viewControllers.reversed() {
|
||||||
var chatListController: ChatListControllerImpl?
|
var chatListController: ChatListControllerImpl?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user