mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Fix loading foreign channels
This commit is contained in:
parent
eb480074fd
commit
a6955ea613
@ -904,20 +904,20 @@ public final class MessageHistoryView {
|
||||
public let isLoading: Bool
|
||||
public let isAddedToChatList: Bool
|
||||
|
||||
public init(tagMask: MessageTags?, namespaces: MessageIdNamespaces, entries: [MessageHistoryEntry], holeEarlier: Bool) {
|
||||
public init(tagMask: MessageTags?, namespaces: MessageIdNamespaces, entries: [MessageHistoryEntry], holeEarlier: Bool, holeLater: Bool, isLoading: Bool) {
|
||||
self.tagMask = tagMask
|
||||
self.namespaces = namespaces
|
||||
self.anchorIndex = .lowerBound
|
||||
self.earlierId = nil
|
||||
self.laterId = nil
|
||||
self.holeEarlier = holeEarlier
|
||||
self.holeLater = false
|
||||
self.holeLater = holeLater
|
||||
self.entries = entries
|
||||
self.maxReadIndex = nil
|
||||
self.fixedReadStates = nil
|
||||
self.topTaggedMessages = []
|
||||
self.additionalData = []
|
||||
self.isLoading = false
|
||||
self.isLoading = isLoading
|
||||
self.isAddedToChatList = false
|
||||
}
|
||||
|
||||
|
@ -1172,7 +1172,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration,
|
||||
|
||||
#if DEBUG
|
||||
//debugSaveState(basePath: basePath, name: "previous1")
|
||||
//debugRestoreState(basePath: basePath, name: "previous1")
|
||||
debugRestoreState(basePath: basePath, name: "previous1")
|
||||
#endif
|
||||
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
|
@ -1676,49 +1676,49 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable
|
||||
}
|
||||
}
|
||||
|
||||
func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||
let signal: Signal<Void, NoError> = postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
if let accountState = (transaction.getState() as? AuthorizedAccountState)?.state, let peer = transaction.getPeer(peerId) {
|
||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
if let channelState = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
channelStates[peerId] = AccountStateChannelState(pts: channelState.pts)
|
||||
}
|
||||
let initialPeers: [PeerId: Peer] = [peerId: peer]
|
||||
var peerChatInfos: [PeerId: PeerChatInfo] = [:]
|
||||
let inclusion = transaction.getPeerChatListInclusion(peerId)
|
||||
var hasValidInclusion = false
|
||||
switch inclusion {
|
||||
case .ifHasMessagesOrOneOf:
|
||||
hasValidInclusion = true
|
||||
case .notIncluded:
|
||||
hasValidInclusion = false
|
||||
}
|
||||
if hasValidInclusion {
|
||||
if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings {
|
||||
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
||||
}
|
||||
}
|
||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||
return pollChannel(network: network, peer: peer, state: initialState)
|
||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Void, NoError> in
|
||||
return resolveAssociatedMessages(network: network, state: finalState)
|
||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
||||
|> map { resultingState, _ -> AccountFinalState in
|
||||
return AccountFinalState(state: resultingState, shouldPoll: false, incomplete: false, missingUpdatesFromChannels: Set(), discard: false)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { finalState -> Signal<Void, NoError> in
|
||||
return stateManager.addReplayAsynchronouslyBuiltFinalState(finalState)
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete() |> delay(Double(timeout ?? 30), queue: Queue.concurrentDefaultQueue())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal<Int32, NoError> {
|
||||
let signal: Signal<Int32, NoError> = postbox.transaction { transaction -> Signal<Int32, NoError> in
|
||||
guard let accountState = (transaction.getState() as? AuthorizedAccountState)?.state, let peer = transaction.getPeer(peerId) else {
|
||||
return .complete()
|
||||
|> delay(30.0, queue: Queue.concurrentDefaultQueue())
|
||||
}
|
||||
|
||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
if let channelState = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
channelStates[peerId] = AccountStateChannelState(pts: channelState.pts)
|
||||
}
|
||||
let initialPeers: [PeerId: Peer] = [peerId: peer]
|
||||
var peerChatInfos: [PeerId: PeerChatInfo] = [:]
|
||||
let inclusion = transaction.getPeerChatListInclusion(peerId)
|
||||
var hasValidInclusion = false
|
||||
switch inclusion {
|
||||
case .ifHasMessagesOrOneOf:
|
||||
hasValidInclusion = true
|
||||
case .notIncluded:
|
||||
hasValidInclusion = false
|
||||
}
|
||||
if hasValidInclusion {
|
||||
if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings {
|
||||
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
||||
}
|
||||
}
|
||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||
return pollChannel(network: network, peer: peer, state: initialState)
|
||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
|
||||
return resolveAssociatedMessages(network: network, state: finalState)
|
||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
||||
|> map { resultingState, _ -> AccountFinalState in
|
||||
return AccountFinalState(state: resultingState, shouldPoll: false, incomplete: false, missingUpdatesFromChannels: Set(), discard: false)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { finalState -> Signal<Int32, NoError> in
|
||||
return stateManager.addReplayAsynchronouslyBuiltFinalState(finalState)
|
||||
|> mapToSignal { _ -> Signal<Int32, NoError> in
|
||||
return .single(timeout ?? 30) |> then(.complete() |> delay(Double(timeout ?? 30), queue: Queue.concurrentDefaultQueue()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> switchToLatest
|
||||
|> restart
|
||||
|
@ -224,9 +224,21 @@ private final class CachedChannelParticipantsContext {
|
||||
private final class ChannelPollingContext {
|
||||
var subscribers = Bag<Void>()
|
||||
let disposable = MetaDisposable()
|
||||
let isUpdated = Promise<Bool>(false)
|
||||
|
||||
private(set) var isUpdatedValue: Bool = false
|
||||
private var isUpdatedDisposable: Disposable?
|
||||
|
||||
init(queue: Queue) {
|
||||
self.isUpdatedDisposable = (self.isUpdated.get()
|
||||
|> deliverOn(queue)).start(next: { [weak self] value in
|
||||
self?.isUpdatedValue = value
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
self.isUpdatedDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1302,13 +1314,27 @@ public final class AccountViewTracker {
|
||||
if let current = self.channelPollingContexts[peerId] {
|
||||
context = current
|
||||
} else {
|
||||
context = ChannelPollingContext()
|
||||
context = ChannelPollingContext(queue: self.queue)
|
||||
self.channelPollingContexts[peerId] = context
|
||||
}
|
||||
|
||||
if context.subscribers.isEmpty {
|
||||
if let account = self.account {
|
||||
context.disposable.set(keepPollingChannel(postbox: account.postbox, network: account.network, peerId: peerId, stateManager: account.stateManager).start())
|
||||
let queue = self.queue
|
||||
context.disposable.set(keepPollingChannel(postbox: account.postbox, network: account.network, peerId: peerId, stateManager: account.stateManager).start(next: { [weak context] isValidForTimeout in
|
||||
queue.async {
|
||||
guard let context = context else {
|
||||
return
|
||||
}
|
||||
context.isUpdated.set(
|
||||
.single(true)
|
||||
|> then(
|
||||
.single(false)
|
||||
|> delay(Double(isValidForTimeout), queue: queue)
|
||||
)
|
||||
)
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1378,34 +1404,54 @@ public final class AccountViewTracker {
|
||||
peerId = peerIdValue
|
||||
}
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
return Signal { subscriber in
|
||||
return Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { subscriber in
|
||||
let combinedDisposable = MetaDisposable()
|
||||
self.queue.async {
|
||||
let polled = self.polledChannel(peerId: peerId).start()
|
||||
|
||||
var addHole = false
|
||||
let historyIsValid: Signal<Bool, NoError>
|
||||
if let context = self.channelPollingContexts[peerId] {
|
||||
if context.subscribers.isEmpty {
|
||||
if !context.isUpdatedValue {
|
||||
addHole = true
|
||||
}
|
||||
historyIsValid = context.isUpdated.get()
|
||||
} else {
|
||||
addHole = true
|
||||
historyIsValid = .single(true)
|
||||
}
|
||||
if addHole {
|
||||
let _ = self.account?.postbox.transaction({ transaction -> Void in
|
||||
if transaction.getPeerChatListIndex(peerId) == nil {
|
||||
if let message = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) {
|
||||
//transaction.addHole(peerId: peerId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: message.id + 1 ... (Int32.max - 1))
|
||||
}
|
||||
transaction.addHole(peerId: peerId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1))
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
let disposable = history.start(next: { next in
|
||||
|
||||
let validHistory = historyIsValid
|
||||
|> distinctUntilChanged
|
||||
|> take(until: { next in
|
||||
if next {
|
||||
return SignalTakeAction(passthrough: true, complete: true)
|
||||
} else {
|
||||
return SignalTakeAction(passthrough: true, complete: false)
|
||||
}
|
||||
})
|
||||
|> mapToSignal { isValid -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
||||
if isValid {
|
||||
return history
|
||||
} else {
|
||||
let view = MessageHistoryView(tagMask: nil, namespaces: .all, entries: [], holeEarlier: true, holeLater: true, isLoading: true)
|
||||
return .single((view, .Initial, nil))
|
||||
}
|
||||
}
|
||||
|
||||
let disposable = validHistory.start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}, error: { error in
|
||||
subscriber.putError(error)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
let polled = self.polledChannel(peerId: peerId).start()
|
||||
|
||||
combinedDisposable.set(ActionDisposable {
|
||||
disposable.dispose()
|
||||
polled.dispose()
|
||||
|
@ -750,7 +750,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
scrollPosition = nil
|
||||
}
|
||||
|
||||
return (ChatHistoryViewUpdate.HistoryView(view: MessageHistoryView(tagMask: nil, namespaces: .all, entries: messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: hasMore), type: .Generic(type: ViewUpdateType.Initial), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: nil, buttonKeyboardMessage: nil, cachedData: nil, cachedDataMessages: nil, readStateData: nil), id: 0), version, nil)
|
||||
return (ChatHistoryViewUpdate.HistoryView(view: MessageHistoryView(tagMask: nil, namespaces: .all, entries: messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: hasMore, holeLater: false, isLoading: false), type: .Generic(type: ViewUpdateType.Initial), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: nil, buttonKeyboardMessage: nil, cachedData: nil, cachedDataMessages: nil, readStateData: nil), id: 0), version, nil)
|
||||
}
|
||||
} else {
|
||||
historyViewUpdate = self.chatHistoryLocationPromise.get()
|
||||
@ -906,9 +906,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
let historyView = (strongSelf.opaqueTransactionState as? ChatHistoryTransactionOpaqueState)?.historyView
|
||||
let displayRange = strongSelf.displayedItemRange
|
||||
if let filteredEntries = historyView?.filteredEntries, let visibleRange = displayRange.visibleRange {
|
||||
let lastEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.lastIndex]
|
||||
let firstEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.firstIndex]
|
||||
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount, highlight: false), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount, highlight: false), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else {
|
||||
if let subject = subject, case let .message(messageId, highlight) = subject {
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: highlight), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
|
@ -94,12 +94,14 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
|
||||
|
||||
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
|
||||
|
||||
if view.isLoading {
|
||||
preloaded = false
|
||||
return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
|
||||
}
|
||||
|
||||
if preloaded {
|
||||
return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id)
|
||||
} else {
|
||||
if view.isLoading {
|
||||
return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
|
||||
}
|
||||
var scrollPosition: ChatHistoryViewScrollPosition?
|
||||
|
||||
let canScrollToRead: Bool
|
||||
@ -180,6 +182,11 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, context: A
|
||||
|
||||
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
|
||||
|
||||
if view.isLoading {
|
||||
preloaded = false
|
||||
return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
|
||||
}
|
||||
|
||||
if preloaded {
|
||||
return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id)
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user