mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Stories
This commit is contained in:
parent
3150e296a3
commit
f3ee06dd32
@ -1645,7 +1645,7 @@ private final class NotificationServiceHandler {
|
||||
}
|
||||
|> then(
|
||||
stateManager.postbox.transaction { transaction -> (MediaResourceReference, Int64?)? in
|
||||
guard let state = transaction.getPeerStoryState(peerId: peerId)?.get(Stories.PeerState.self) else {
|
||||
guard let state = transaction.getPeerStoryState(peerId: peerId)?.entry.get(Stories.PeerState.self) else {
|
||||
return nil
|
||||
}
|
||||
let firstUnseenItem = transaction.getStoryItems(peerId: peerId).first(where: { entry in
|
||||
|
@ -36,7 +36,11 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
|
||||
|> mapToSignal { view -> Signal<[INMessage], NoError> in
|
||||
var signals: [Signal<[INMessage], NoError>] = []
|
||||
for entry in view.0.entries {
|
||||
if case let .MessageEntry(index, _, readState, isMuted, _, _, _, _, _, _, _, _, _) = entry {
|
||||
if case let .MessageEntry(entryData) = entry {
|
||||
let index = entryData.index
|
||||
let readState = entryData.readState
|
||||
let isMuted = entryData.isRemovedFromTotalUnreadCount
|
||||
|
||||
if index.messageIndex.id.peerId.namespace != Namespaces.Peer.CloudUser {
|
||||
continue
|
||||
}
|
||||
|
@ -178,6 +178,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|
||||
private var powerSavingMonitoringDisposable: Disposable?
|
||||
|
||||
private var rawStoryArchiveSubscriptions: EngineStorySubscriptions?
|
||||
private var storyArchiveSubscriptionsDisposable: Disposable?
|
||||
|
||||
private var rawStorySubscriptions: EngineStorySubscriptions?
|
||||
private var shouldFixStorySubscriptionOrder: Bool = false
|
||||
private var fixedStorySubscriptionOrder: [EnginePeer.Id] = []
|
||||
@ -756,6 +759,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.actionDisposables.dispose()
|
||||
self.powerSavingMonitoringDisposable?.dispose()
|
||||
self.storySubscriptionsDisposable?.dispose()
|
||||
self.storyArchiveSubscriptionsDisposable?.dispose()
|
||||
self.preloadStorySubscriptionsDisposable?.dispose()
|
||||
self.storyProgressDisposable?.dispose()
|
||||
self.storiesPostingAvailabilityDisposable?.dispose()
|
||||
@ -1243,10 +1247,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
|
||||
switch item.content {
|
||||
case let .groupReference(groupId, _, _, _, _):
|
||||
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
||||
case let .groupReference(groupReference):
|
||||
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .chatList(groupId: groupReference.groupId), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
||||
chatListController.navigationPresentation = .master
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupId._asGroup(), chatListController: strongSelf) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupReference.groupId._asGroup(), chatListController: strongSelf) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
||||
strongSelf.presentInGlobalOverlay(contextController)
|
||||
case let .peer(peerData):
|
||||
let peer = peerData.peer
|
||||
@ -1306,16 +1310,30 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
}
|
||||
|
||||
self.chatListDisplayNode.mainContainerNode.openStories = { [weak self] peerId, itemNode in
|
||||
self.chatListDisplayNode.mainContainerNode.openStories = { [weak self] subject, itemNode in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peerId, singlePeer: true)
|
||||
let isHidden: Bool
|
||||
let focusedPeerId: EnginePeer.Id?
|
||||
let singlePeer: Bool
|
||||
switch subject {
|
||||
case let .peer(peerId):
|
||||
isHidden = self.location == .chatList(groupId: .archive)
|
||||
focusedPeerId = peerId
|
||||
singlePeer = true
|
||||
case .archive:
|
||||
isHidden = true
|
||||
focusedPeerId = nil
|
||||
singlePeer = false
|
||||
}
|
||||
|
||||
let storyContent = StoryContentContextImpl(context: self.context, isHidden: isHidden, focusedPeerId: focusedPeerId, singlePeer: singlePeer)
|
||||
let _ = (storyContent.state
|
||||
|> filter { $0.slice != nil }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak itemNode] _ in
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak itemNode] state in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -1337,10 +1355,30 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
transitionIn: transitionIn,
|
||||
transitionOut: { _, _ in
|
||||
if let itemNode = itemNode as? ChatListItemNode {
|
||||
let rect = itemNode.avatarNode.view.convert(itemNode.avatarNode.view.bounds, to: itemNode.view)
|
||||
let transitionView = itemNode.avatarNode.view
|
||||
let destinationView = itemNode.view
|
||||
let rect = transitionView.convert(transitionView.bounds, to: destinationView)
|
||||
return StoryContainerScreen.TransitionOut(
|
||||
destinationView: itemNode.view,
|
||||
transitionView: nil,
|
||||
destinationView: destinationView,
|
||||
transitionView: StoryContainerScreen.TransitionView(
|
||||
makeView: { [weak transitionView] in
|
||||
let parentView = UIView()
|
||||
if let copyView = transitionView?.snapshotContentTree(unhide: true) {
|
||||
parentView.addSubview(copyView)
|
||||
}
|
||||
return parentView
|
||||
},
|
||||
updateView: { copyView, state, transition in
|
||||
guard let view = copyView.subviews.first else {
|
||||
return
|
||||
}
|
||||
let size = state.sourceSize.interpolate(to: CGSize(width: state.destinationSize.width, height: state.destinationSize.height), amount: state.progress)
|
||||
let scaleSize = state.sourceSize.interpolate(to: CGSize(width: state.destinationSize.width - 7.0, height: state.destinationSize.height - 7.0), amount: state.progress)
|
||||
transition.setPosition(view: view, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5))
|
||||
transition.setScale(view: view, scale: scaleSize.width / state.destinationSize.width)
|
||||
},
|
||||
insertCloneTransitionView: nil
|
||||
),
|
||||
destinationRect: rect,
|
||||
destinationCornerRadius: rect.height * 0.5,
|
||||
destinationIsAvatar: true,
|
||||
@ -1789,7 +1827,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
if case .chatList(.root) = self.location {
|
||||
if case .chatList = self.location {
|
||||
let automaticDownloadNetworkType = context.account.networkType
|
||||
|> map { type -> MediaAutoDownloadNetworkType in
|
||||
switch type {
|
||||
@ -1802,7 +1840,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|> distinctUntilChanged
|
||||
|
||||
self.preloadStorySubscriptionsDisposable = (combineLatest(queue: .mainQueue(),
|
||||
self.context.engine.messages.preloadStorySubscriptions(isHidden: false),
|
||||
self.context.engine.messages.preloadStorySubscriptions(isHidden: self.location == .chatList(groupId: .archive)),
|
||||
self.context.sharedContext.automaticMediaDownloadSettings,
|
||||
automaticDownloadNetworkType
|
||||
)
|
||||
@ -1842,7 +1880,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.preloadStoryResourceDisposables.removeValue(forKey: id)
|
||||
}
|
||||
})
|
||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: false)
|
||||
|
||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: self.location == .chatList(groupId: .archive))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] rawStorySubscriptions in
|
||||
guard let self else {
|
||||
return
|
||||
@ -1880,7 +1919,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.requestLayout(transition: transition)
|
||||
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
|
||||
|
||||
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
||||
if rawStorySubscriptions.items.isEmpty {
|
||||
self.chatListDisplayNode.scrollToTopIfStoriesAreExpanded()
|
||||
}
|
||||
|
||||
/*self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
||||
var chatListState = chatListState
|
||||
|
||||
var peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState] = [:]
|
||||
@ -1896,7 +1939,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
chatListState.peerStoryMapping = peerStoryMapping
|
||||
|
||||
return chatListState
|
||||
}
|
||||
}*/
|
||||
|
||||
self.storiesReady.set(.single(true))
|
||||
|
||||
@ -1914,6 +1957,41 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
self.updateStoryUploadProgress(progress)
|
||||
})
|
||||
|
||||
if case .chatList(.root) = self.location {
|
||||
self.storyArchiveSubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: true)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] rawStoryArchiveSubscriptions in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.rawStoryArchiveSubscriptions = rawStoryArchiveSubscriptions
|
||||
|
||||
let hasUnseenArchive: Bool?
|
||||
if rawStoryArchiveSubscriptions.items.isEmpty {
|
||||
hasUnseenArchive = nil
|
||||
} else {
|
||||
hasUnseenArchive = rawStoryArchiveSubscriptions.items.contains(where: { $0.hasUnseen })
|
||||
}
|
||||
|
||||
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
||||
var chatListState = chatListState
|
||||
|
||||
chatListState.hasUnseenArchiveStories = hasUnseenArchive
|
||||
|
||||
return chatListState
|
||||
}
|
||||
|
||||
self.storiesReady.set(.single(true))
|
||||
|
||||
Queue.mainQueue().after(1.0, { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.maybeDisplayStoryTooltip()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2540,7 +2618,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.chatListDisplayNode.scrollToTop()
|
||||
}
|
||||
|
||||
if case .chatList(.root) = self.location, let componentView = self.chatListHeaderView() {
|
||||
if case .chatList = self.location, let componentView = self.chatListHeaderView() {
|
||||
componentView.storyPeerAction = { [weak self] peer in
|
||||
guard let self else {
|
||||
return
|
||||
@ -2703,15 +2781,26 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
})))
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: "Hide \(peer.compactDisplayTitle)", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MoveToContacts"), color: theme.contextMenu.primaryColor)
|
||||
let hideText: String
|
||||
if self.location == .chatList(groupId: .archive) {
|
||||
hideText = "Unarchive"
|
||||
} else {
|
||||
hideText = "Archive"
|
||||
}
|
||||
let iconName = self.location == .chatList(groupId: .archive) ? "Chat/Context Menu/MoveToChats" : "Chat/Context Menu/MoveToContacts"
|
||||
items.append(.action(ContextMenuActionItem(text: hideText, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: iconName), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, f in
|
||||
f(.dismissWithoutContent)
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.context.engine.peers.updatePeerStoriesHidden(id: peer.id, isHidden: true)
|
||||
if self.location == .chatList(groupId: .archive) {
|
||||
self.context.engine.peers.updatePeerStoriesHidden(id: peer.id, isHidden: false)
|
||||
} else {
|
||||
self.context.engine.peers.updatePeerStoriesHidden(id: peer.id, isHidden: true)
|
||||
}
|
||||
|
||||
guard let parentController = self.parent as? TabBarController, let contactsController = (self.navigationController as? TelegramRootControllerInterface)?.getContactsController(), let sourceFrame = parentController.frameForControllerTab(controller: contactsController) else {
|
||||
return
|
||||
@ -3442,7 +3531,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.shouldFixStorySubscriptionOrder = true
|
||||
}
|
||||
}
|
||||
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peerId, singlePeer: false, fixedOrder: self.fixedStorySubscriptionOrder)
|
||||
let storyContent = StoryContentContextImpl(context: self.context, isHidden: self.location == .chatList(groupId: .archive), focusedPeerId: peerId, singlePeer: false, fixedOrder: self.fixedStorySubscriptionOrder)
|
||||
let _ = (storyContent.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
||||
|
@ -925,10 +925,10 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
return
|
||||
}
|
||||
|
||||
if itemNode.listNode.isTracking && !self.currentItemNode.startedScrollingAtUpperBound && self.tempTopInset == 0.0 {
|
||||
if !self.isInlineMode, itemNode.listNode.isTracking && !self.currentItemNode.startedScrollingAtUpperBound && self.tempTopInset == 0.0 {
|
||||
if case let .known(value) = offset {
|
||||
if value < -1.0 {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
||||
self.currentItemNode.startedScrollingAtUpperBound = true
|
||||
self.tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
||||
}
|
||||
@ -939,7 +939,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
self.contentOffset = offset
|
||||
self.contentOffsetChanged?(offset)
|
||||
|
||||
if self.currentItemNode.startedScrollingAtUpperBound && self.tempTopInset != 0.0 {
|
||||
if !self.isInlineMode, self.currentItemNode.startedScrollingAtUpperBound && self.tempTopInset != 0.0 {
|
||||
if case let .known(value) = offset {
|
||||
if value > 4.0 {
|
||||
self.currentItemNode.startedScrollingAtUpperBound = false
|
||||
@ -954,12 +954,12 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
}
|
||||
}
|
||||
itemNode.listNode.didBeginInteractiveDragging = { [weak self] _ in
|
||||
guard let self else {
|
||||
guard let self, !self.isInlineMode else {
|
||||
return
|
||||
}
|
||||
let tempTopInset: CGFloat
|
||||
if self.currentItemNode.startedScrollingAtUpperBound && !self.isInlineMode {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
||||
tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
||||
} else {
|
||||
tempTopInset = 0.0
|
||||
@ -1001,8 +1001,8 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
itemNode.listNode.activateChatPreview = { [weak self] item, threadId, sourceNode, gesture, location in
|
||||
self?.activateChatPreview?(item, threadId, sourceNode, gesture, location)
|
||||
}
|
||||
itemNode.listNode.openStories = { [weak self] peerId, itemNode in
|
||||
self?.openStories?(peerId, itemNode)
|
||||
itemNode.listNode.openStories = { [weak self] subject, itemNode in
|
||||
self?.openStories?(subject, itemNode)
|
||||
}
|
||||
itemNode.listNode.addedVisibleChatsWithPeerIds = { [weak self] ids in
|
||||
self?.addedVisibleChatsWithPeerIds?(ids)
|
||||
@ -1076,7 +1076,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
var endedInteractiveDragging: ((ListView) -> Void)?
|
||||
var shouldStopScrolling: ((ListView, CGFloat) -> Bool)?
|
||||
var activateChatPreview: ((ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
|
||||
var openStories: ((EnginePeer.Id, ASDisplayNode?) -> Void)?
|
||||
var openStories: ((ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void)?
|
||||
var addedVisibleChatsWithPeerIds: (([EnginePeer.Id]) -> Void)?
|
||||
var didBeginSelectingChats: (() -> Void)?
|
||||
var canExpandHiddenItems: (() -> Bool)?
|
||||
@ -1802,7 +1802,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return false
|
||||
}
|
||||
|
||||
if let storySubscriptions = controller.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
if let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
||||
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
|
||||
if navigationBarComponentView.storiesUnlocked {
|
||||
return true
|
||||
@ -1946,7 +1946,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
secondaryContent: headerContent?.secondaryContent,
|
||||
secondaryTransition: self.inlineStackContainerTransitionFraction,
|
||||
storySubscriptions: self.controller?.orderedStorySubscriptions,
|
||||
storiesIncludeHidden: false,
|
||||
storiesIncludeHidden: self.location == .chatList(groupId: .archive),
|
||||
uploadProgress: self.controller?.storyUploadProgress,
|
||||
tabsNode: tabsNode,
|
||||
tabsNodeIsSearch: tabsNodeIsSearch,
|
||||
@ -2534,4 +2534,20 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
self.mainContainerNode.scrollToTop(animated: true, adjustForTempInset: false)
|
||||
}
|
||||
}
|
||||
|
||||
func scrollToTopIfStoriesAreExpanded() {
|
||||
if let contentOffset = self.mainContainerNode.contentOffset, case let .known(offset) = contentOffset, offset < 0.0 {
|
||||
self.mainContainerNode.scrollToTop(animated: true, adjustForTempInset: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shouldDisplayStoriesInChatListHeader(storySubscriptions: EngineStorySubscriptions, isHidden: Bool) -> Bool {
|
||||
if !storySubscriptions.items.isEmpty {
|
||||
return true
|
||||
}
|
||||
if !isHidden, let accountItem = storySubscriptions.accountItem, (accountItem.hasUnseen || accountItem.hasPending) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -3244,8 +3244,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
switch item.content {
|
||||
case let .peer(peerData):
|
||||
return (selectedItemNode.view, bounds, peerData.messages.last?.id ?? peerData.peer.peerId)
|
||||
case let .groupReference(groupId, _, _, _, _):
|
||||
return (selectedItemNode.view, bounds, groupId)
|
||||
case let .groupReference(groupReference):
|
||||
return (selectedItemNode.view, bounds, groupReference.groupId)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -66,14 +66,14 @@ public enum ChatListItemContent {
|
||||
}
|
||||
|
||||
public struct StoryState: Equatable {
|
||||
public var hasUnseen: Bool
|
||||
public var stats: EngineChatList.StoryStats
|
||||
public var hasUnseenCloseFriends: Bool
|
||||
|
||||
public init(
|
||||
hasUnseen: Bool,
|
||||
stats: EngineChatList.StoryStats,
|
||||
hasUnseenCloseFriends: Bool
|
||||
) {
|
||||
self.hasUnseen = hasUnseen
|
||||
self.stats = stats
|
||||
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||
}
|
||||
}
|
||||
@ -138,9 +138,34 @@ public enum ChatListItemContent {
|
||||
self.storyState = storyState
|
||||
}
|
||||
}
|
||||
|
||||
public struct GroupReferenceData {
|
||||
public var groupId: EngineChatList.Group
|
||||
public var peers: [EngineChatList.GroupItem.Item]
|
||||
public var message: EngineMessage?
|
||||
public var unreadCount: Int
|
||||
public var hiddenByDefault: Bool
|
||||
public var storyState: StoryState?
|
||||
|
||||
public init(
|
||||
groupId: EngineChatList.Group,
|
||||
peers: [EngineChatList.GroupItem.Item],
|
||||
message: EngineMessage?,
|
||||
unreadCount: Int,
|
||||
hiddenByDefault: Bool,
|
||||
storyState: StoryState?
|
||||
) {
|
||||
self.groupId = groupId
|
||||
self.peers = peers
|
||||
self.message = message
|
||||
self.unreadCount = unreadCount
|
||||
self.hiddenByDefault = hiddenByDefault
|
||||
self.storyState = storyState
|
||||
}
|
||||
}
|
||||
|
||||
case peer(PeerData)
|
||||
case groupReference(groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, unreadCount: Int, hiddenByDefault: Bool)
|
||||
case groupReference(GroupReferenceData)
|
||||
|
||||
public var chatLocation: ChatLocation? {
|
||||
switch self {
|
||||
@ -267,8 +292,8 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
||||
} else if let peer = peerData.peer.peers[peerData.peer.peerId] {
|
||||
self.interaction.peerSelected(peer, nil, nil, peerData.promoInfo)
|
||||
}
|
||||
case let .groupReference(groupId, _, _, _, _):
|
||||
self.interaction.groupSelected(groupId)
|
||||
case let .groupReference(groupReferenceData):
|
||||
self.interaction.groupSelected(groupReferenceData.groupId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1005,9 +1030,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
return nil
|
||||
}
|
||||
switch item.content {
|
||||
case let .groupReference(_, _, _, unreadCount, _):
|
||||
case let .groupReference(groupReferenceData):
|
||||
var result = item.presentationData.strings.ChatList_ArchivedChatsTitle
|
||||
let allCount = unreadCount
|
||||
let allCount = groupReferenceData.unreadCount
|
||||
if allCount > 0 {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_Chat_UnreadMessages(Int32(allCount)))"
|
||||
}
|
||||
@ -1037,7 +1062,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
return nil
|
||||
}
|
||||
switch item.content {
|
||||
case let .groupReference(_, peers, messageValue, _, _):
|
||||
case let .groupReference(groupReferenceData):
|
||||
let peers = groupReferenceData.peers
|
||||
let messageValue = groupReferenceData.message
|
||||
if let message = messageValue, let peer = peers.first?.peer {
|
||||
let messages = [message]
|
||||
var result = ""
|
||||
@ -1314,12 +1341,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if peerData.peer.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
enablePreview = false
|
||||
}
|
||||
case let .groupReference(_, _, _, _, hiddenByDefault):
|
||||
if let previousItem = previousItem, case let .groupReference(_, _, _, _, previousHiddenByDefault) = previousItem.content, hiddenByDefault != previousHiddenByDefault {
|
||||
case let .groupReference(groupReferenceData):
|
||||
if let previousItem = previousItem, case let .groupReference(previousGroupReferenceData) = previousItem.content, groupReferenceData.hiddenByDefault != previousGroupReferenceData.hiddenByDefault {
|
||||
UIView.transition(with: self.avatarNode.view, duration: 0.3, options: [.transitionCrossDissolve], animations: {
|
||||
}, completion: nil)
|
||||
}
|
||||
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: .archivedChatsIcon(hiddenByDefault: hiddenByDefault), emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: .archivedChatsIcon(hiddenByDefault: groupReferenceData.hiddenByDefault), emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
}
|
||||
|
||||
if let peer = peer {
|
||||
@ -1628,7 +1655,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
promoInfo = promoInfoValue
|
||||
displayAsMessage = displayAsMessageValue
|
||||
hasFailedMessages = messagesValue.last?.flags.contains(.Failed) ?? false // hasFailedMessagesValue
|
||||
case let .groupReference(_, peers, messageValue, unreadCountValue, hiddenByDefault):
|
||||
case let .groupReference(groupReferenceData):
|
||||
let peers = groupReferenceData.peers
|
||||
let messageValue = groupReferenceData.message
|
||||
let unreadCountValue = groupReferenceData.unreadCount
|
||||
let hiddenByDefault = groupReferenceData.hiddenByDefault
|
||||
|
||||
if let _ = messageValue, !peers.isEmpty {
|
||||
contentPeer = .chat(peers[0].peer)
|
||||
} else {
|
||||
@ -2150,8 +2182,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let dateText: String
|
||||
var topIndex: MessageIndex?
|
||||
switch item.content {
|
||||
case let .groupReference(_, _, message, _, _):
|
||||
topIndex = message?.index
|
||||
case let .groupReference(groupReferenceData):
|
||||
topIndex = groupReferenceData.message?.index
|
||||
case let .peer(peerData):
|
||||
topIndex = peerData.messages.first?.index
|
||||
}
|
||||
@ -2763,6 +2795,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var storyState: ChatListItemContent.StoryState?
|
||||
if case let .peer(peerData) = item.content {
|
||||
storyState = peerData.storyState
|
||||
} else if case let .groupReference(groupReference) = item.content {
|
||||
storyState = groupReference.storyState
|
||||
}
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - avatarLeftInset + editingOffset + 10.0 + revealOffset, y: floor((itemHeight - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter))
|
||||
@ -2805,12 +2839,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let _ = avatarStoryIndicator.update(
|
||||
transition: indicatorTransition,
|
||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||
hasUnseen: storyState.hasUnseen,
|
||||
hasUnseen: storyState.stats.unseenCount != 0,
|
||||
hasUnseenCloseFriendsItems: storyState.hasUnseenCloseFriends,
|
||||
theme: item.presentationData.theme,
|
||||
activeLineWidth: 2.0,
|
||||
inactiveLineWidth: 1.0 + UIScreenPixel,
|
||||
counters: nil
|
||||
counters: AvatarStoryIndicatorComponent.Counters(
|
||||
totalCount: storyState.stats.totalCount,
|
||||
unseenCount: storyState.stats.unseenCount
|
||||
)
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: indicatorFrame.size
|
||||
@ -3504,7 +3541,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
let separatorInset: CGFloat
|
||||
if case let .groupReference(_, _, _, _, hiddenByDefault) = item.content, hiddenByDefault {
|
||||
if case let .groupReference(groupReferenceData) = item.content, groupReferenceData.hiddenByDefault {
|
||||
separatorInset = 0.0
|
||||
} else if (!nextIsPinned && isPinned) || last {
|
||||
separatorInset = 0.0
|
||||
@ -3526,7 +3563,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
backgroundColor = theme.itemSelectedBackgroundColor
|
||||
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
|
||||
} else if isPinned {
|
||||
if case let .groupReference(_, _, _, _, hiddenByDefault) = item.content, hiddenByDefault {
|
||||
if case let .groupReference(groupReferenceData) = item.content, groupReferenceData.hiddenByDefault {
|
||||
backgroundColor = theme.itemBackgroundColor
|
||||
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
|
||||
} else {
|
||||
@ -3873,10 +3910,16 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
@objc private func avatarStoryTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
guard let item = self.item, case let .peer(peerData) = item.content else {
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
item.interaction.openStories(peerData.peer.peerId, self)
|
||||
switch item.content {
|
||||
case let .peer(peerData):
|
||||
item.interaction.openStories(.peer(peerData.peer.peerId), self)
|
||||
case .groupReference:
|
||||
item.interaction.openStories(.archive, self)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public final class ChatListNodeInteraction {
|
||||
let openPremiumIntro: () -> Void
|
||||
let openChatFolderUpdates: () -> Void
|
||||
let hideChatFolderUpdates: () -> Void
|
||||
let openStories: (EnginePeer.Id, ASDisplayNode?) -> Void
|
||||
let openStories: (ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void
|
||||
|
||||
public var searchTextHighightState: String?
|
||||
var highlightedChatLocation: ChatListHighlightedLocation?
|
||||
@ -148,7 +148,7 @@ public final class ChatListNodeInteraction {
|
||||
openPremiumIntro: @escaping () -> Void,
|
||||
openChatFolderUpdates: @escaping () -> Void,
|
||||
hideChatFolderUpdates: @escaping () -> Void,
|
||||
openStories: @escaping (EnginePeer.Id, ASDisplayNode?) -> Void
|
||||
openStories: @escaping (ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void
|
||||
) {
|
||||
self.activateSearch = activateSearch
|
||||
self.peerSelected = peerSelected
|
||||
@ -219,11 +219,11 @@ private func areFoundPeerArraysEqual(_ lhs: [(EnginePeer, EnginePeer?)], _ rhs:
|
||||
|
||||
public struct ChatListNodeState: Equatable {
|
||||
public struct StoryState: Equatable {
|
||||
public var hasUnseen: Bool
|
||||
public var stats: EngineChatList.StoryStats
|
||||
public var hasUnseenCloseFriends: Bool
|
||||
|
||||
public init(hasUnseen: Bool, hasUnseenCloseFriends: Bool) {
|
||||
self.hasUnseen = hasUnseen
|
||||
public init(stats: EngineChatList.StoryStats, hasUnseenCloseFriends: Bool) {
|
||||
self.stats = stats
|
||||
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||
}
|
||||
}
|
||||
@ -251,7 +251,7 @@ public struct ChatListNodeState: Equatable {
|
||||
public var foundPeers: [(EnginePeer, EnginePeer?)]
|
||||
public var selectedPeerMap: [EnginePeer.Id: EnginePeer]
|
||||
public var selectedThreadIds: Set<Int64>
|
||||
public var peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState]
|
||||
public var hasUnseenArchiveStories: Bool?
|
||||
|
||||
public init(
|
||||
presentationData: ChatListPresentationData,
|
||||
@ -267,7 +267,7 @@ public struct ChatListNodeState: Equatable {
|
||||
hiddenItemShouldBeTemporaryRevealed: Bool,
|
||||
hiddenPsaPeerId: EnginePeer.Id?,
|
||||
selectedThreadIds: Set<Int64>,
|
||||
peerStoryMapping: [EnginePeer.Id: ChatListNodeState.StoryState]
|
||||
hasUnseenArchiveStories: Bool?
|
||||
) {
|
||||
self.presentationData = presentationData
|
||||
self.editing = editing
|
||||
@ -282,7 +282,7 @@ public struct ChatListNodeState: Equatable {
|
||||
self.hiddenItemShouldBeTemporaryRevealed = hiddenItemShouldBeTemporaryRevealed
|
||||
self.hiddenPsaPeerId = hiddenPsaPeerId
|
||||
self.selectedThreadIds = selectedThreadIds
|
||||
self.peerStoryMapping = peerStoryMapping
|
||||
self.hasUnseenArchiveStories = hasUnseenArchiveStories
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListNodeState, rhs: ChatListNodeState) -> Bool {
|
||||
@ -325,7 +325,7 @@ public struct ChatListNodeState: Equatable {
|
||||
if lhs.selectedThreadIds != rhs.selectedThreadIds {
|
||||
return false
|
||||
}
|
||||
if lhs.peerStoryMapping != rhs.peerStoryMapping {
|
||||
if lhs.hasUnseenArchiveStories != rhs.hasUnseenArchiveStories {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -408,7 +408,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
||||
storyState: peerEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
hasUnseen: storyState.hasUnseen,
|
||||
stats: storyState.stats,
|
||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||
)
|
||||
}
|
||||
@ -623,26 +623,32 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
case let .HoleEntry(_, theme):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListHoleItem(theme: theme), directionHint: entry.directionHint)
|
||||
case let .GroupReferenceEntry(index, presentationData, groupId, peers, message, editing, unreadCount, revealed, hiddenByDefault):
|
||||
case let .GroupReferenceEntry(groupReferenceEntry):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
||||
presentationData: presentationData,
|
||||
presentationData: groupReferenceEntry.presentationData,
|
||||
context: context,
|
||||
chatListLocation: location,
|
||||
filterData: filterData,
|
||||
index: index,
|
||||
content: .groupReference(
|
||||
groupId: groupId,
|
||||
peers: peers,
|
||||
message: message,
|
||||
unreadCount: unreadCount,
|
||||
hiddenByDefault: hiddenByDefault
|
||||
),
|
||||
editing: editing,
|
||||
index: groupReferenceEntry.index,
|
||||
content: .groupReference(ChatListItemContent.GroupReferenceData(
|
||||
groupId: groupReferenceEntry.groupId,
|
||||
peers: groupReferenceEntry.peers,
|
||||
message: groupReferenceEntry.message,
|
||||
unreadCount: groupReferenceEntry.unreadCount,
|
||||
hiddenByDefault: groupReferenceEntry.hiddenByDefault,
|
||||
storyState: groupReferenceEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
stats: storyState.stats,
|
||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||
)
|
||||
}
|
||||
)),
|
||||
editing: groupReferenceEntry.editing,
|
||||
hasActiveRevealControls: false,
|
||||
selected: false,
|
||||
header: nil,
|
||||
enableContextActions: true,
|
||||
hiddenOffset: hiddenByDefault && !revealed,
|
||||
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
||||
interaction: nodeInteraction
|
||||
), directionHint: entry.directionHint)
|
||||
case let .ContactEntry(contactEntry):
|
||||
@ -759,7 +765,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
autoremoveTimeout: peerEntry.autoremoveTimeout,
|
||||
storyState: peerEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
hasUnseen: storyState.hasUnseen,
|
||||
stats: storyState.stats,
|
||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||
)
|
||||
}
|
||||
@ -928,26 +934,32 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
case let .HoleEntry(_, theme):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListHoleItem(theme: theme), directionHint: entry.directionHint)
|
||||
case let .GroupReferenceEntry(index, presentationData, groupId, peers, message, editing, unreadCount, revealed, hiddenByDefault):
|
||||
case let .GroupReferenceEntry(groupReferenceEntry):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(
|
||||
presentationData: presentationData,
|
||||
presentationData: groupReferenceEntry.presentationData,
|
||||
context: context,
|
||||
chatListLocation: location,
|
||||
filterData: filterData,
|
||||
index: index,
|
||||
content: .groupReference(
|
||||
groupId: groupId,
|
||||
peers: peers,
|
||||
message: message,
|
||||
unreadCount: unreadCount,
|
||||
hiddenByDefault: hiddenByDefault
|
||||
),
|
||||
editing: editing,
|
||||
index: groupReferenceEntry.index,
|
||||
content: .groupReference(ChatListItemContent.GroupReferenceData(
|
||||
groupId: groupReferenceEntry.groupId,
|
||||
peers: groupReferenceEntry.peers,
|
||||
message: groupReferenceEntry.message,
|
||||
unreadCount: groupReferenceEntry.unreadCount,
|
||||
hiddenByDefault: groupReferenceEntry.hiddenByDefault,
|
||||
storyState: groupReferenceEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
stats: storyState.stats,
|
||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||
)
|
||||
}
|
||||
)),
|
||||
editing: groupReferenceEntry.editing,
|
||||
hasActiveRevealControls: false,
|
||||
selected: false,
|
||||
header: nil,
|
||||
enableContextActions: true,
|
||||
hiddenOffset: hiddenByDefault && !revealed,
|
||||
hiddenOffset: groupReferenceEntry.hiddenByDefault && !groupReferenceEntry.revealed,
|
||||
interaction: nodeInteraction
|
||||
), directionHint: entry.directionHint)
|
||||
case let .ContactEntry(contactEntry):
|
||||
@ -1069,6 +1081,11 @@ public enum ChatListNodeEmptyState: Equatable {
|
||||
}
|
||||
|
||||
public final class ChatListNode: ListView {
|
||||
public enum OpenStoriesSubject {
|
||||
case peer(EnginePeer.Id)
|
||||
case archive
|
||||
}
|
||||
|
||||
private let fillPreloadItems: Bool
|
||||
private let context: AccountContext
|
||||
private let location: ChatListControllerLocation
|
||||
@ -1106,7 +1123,7 @@ public final class ChatListNode: ListView {
|
||||
public var toggleArchivedFolderHiddenByDefault: (() -> Void)?
|
||||
public var hidePsa: ((EnginePeer.Id) -> Void)?
|
||||
public var activateChatPreview: ((ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
|
||||
public var openStories: ((EnginePeer.Id, ASDisplayNode?) -> Void)?
|
||||
public var openStories: ((ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void)?
|
||||
|
||||
private var theme: PresentationTheme
|
||||
|
||||
@ -1234,7 +1251,7 @@ public final class ChatListNode: ListView {
|
||||
isSelecting = true
|
||||
}
|
||||
|
||||
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: isSelecting, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), foundPeers: [], selectedPeerMap: [:], selectedAdditionalCategoryIds: Set(), peerInputActivities: nil, pendingRemovalItemIds: Set(), pendingClearHistoryPeerIds: Set(), hiddenItemShouldBeTemporaryRevealed: false, hiddenPsaPeerId: nil, selectedThreadIds: Set(), peerStoryMapping: [:])
|
||||
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: isSelecting, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), foundPeers: [], selectedPeerMap: [:], selectedAdditionalCategoryIds: Set(), peerInputActivities: nil, pendingRemovalItemIds: Set(), pendingClearHistoryPeerIds: Set(), hiddenItemShouldBeTemporaryRevealed: false, hiddenPsaPeerId: nil, selectedThreadIds: Set(), hasUnseenArchiveStories: nil)
|
||||
self.statePromise = ValuePromise(self.currentState, ignoreRepeated: true)
|
||||
|
||||
self.theme = theme
|
||||
@ -1573,11 +1590,11 @@ public final class ChatListNode: ListView {
|
||||
let _ = self.context.engine.peers.hideChatFolderUpdates(folderId: localFilterId).start()
|
||||
}
|
||||
})
|
||||
}, openStories: { [weak self] peerId, itemNode in
|
||||
}, openStories: { [weak self] subject, itemNode in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.openStories?(peerId, itemNode)
|
||||
self.openStories?(subject, itemNode)
|
||||
})
|
||||
nodeInteraction.isInlineMode = isInlineMode
|
||||
|
||||
@ -1889,6 +1906,8 @@ public final class ChatListNode: ListView {
|
||||
contacts = .single([])
|
||||
}
|
||||
|
||||
let accountPeerId = context.account.peerId
|
||||
|
||||
let chatListNodeViewTransition = combineLatest(
|
||||
queue: viewProcessingQueue,
|
||||
hideArchivedFolderByDefault,
|
||||
@ -1914,7 +1933,7 @@ public final class ChatListNode: ListView {
|
||||
notice = nil
|
||||
}
|
||||
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, notice: notice, mode: mode, chatListLocation: location, contacts: contacts)
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(view: update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, notice: notice, mode: mode, chatListLocation: location, contacts: contacts, accountPeerId: accountPeerId)
|
||||
var isEmpty = true
|
||||
var entries = rawEntries.filter { entry in
|
||||
switch entry {
|
||||
@ -2260,8 +2279,8 @@ public final class ChatListNode: ListView {
|
||||
didIncludeRemovingPeerId = true
|
||||
}
|
||||
}
|
||||
} else if case let .GroupReferenceEntry(_, _, _, _, _, _, _, _, hiddenByDefault) = entry {
|
||||
didIncludeHiddenByDefaultArchive = hiddenByDefault
|
||||
} else if case let .GroupReferenceEntry(groupReferenceEntry) = entry {
|
||||
didIncludeHiddenByDefaultArchive = groupReferenceEntry.hiddenByDefault
|
||||
} else if case .Notice = entry {
|
||||
didIncludeNotice = true
|
||||
}
|
||||
@ -2296,9 +2315,9 @@ public final class ChatListNode: ListView {
|
||||
doesIncludeRemovingPeerId = true
|
||||
}
|
||||
}
|
||||
} else if case let .GroupReferenceEntry(_, _, _, _, _, _, _, _, hiddenByDefault) = entry {
|
||||
} else if case let .GroupReferenceEntry(groupReferenceEntry) = entry {
|
||||
doesIncludeArchive = true
|
||||
doesIncludeHiddenByDefaultArchive = hiddenByDefault
|
||||
doesIncludeHiddenByDefaultArchive = groupReferenceEntry.hiddenByDefault
|
||||
} else if case .Notice = entry {
|
||||
doesIncludeNotice = true
|
||||
}
|
||||
@ -2836,8 +2855,8 @@ public final class ChatListNode: ListView {
|
||||
isHiddenItemVisible = true
|
||||
}
|
||||
}
|
||||
if case let .groupReference(_, _, _, _, hiddenByDefault) = item.content {
|
||||
if hiddenByDefault {
|
||||
if case let .groupReference(groupReference) = item.content {
|
||||
if groupReference.hiddenByDefault {
|
||||
isHiddenItemVisible = true
|
||||
}
|
||||
}
|
||||
|
@ -302,10 +302,82 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
struct GroupReferenceEntryData: Equatable {
|
||||
var index: EngineChatList.Item.Index
|
||||
var presentationData: ChatListPresentationData
|
||||
var groupId: EngineChatList.Group
|
||||
var peers: [EngineChatList.GroupItem.Item]
|
||||
var message: EngineMessage?
|
||||
var editing: Bool
|
||||
var unreadCount: Int
|
||||
var revealed: Bool
|
||||
var hiddenByDefault: Bool
|
||||
var storyState: ChatListNodeState.StoryState?
|
||||
|
||||
init(
|
||||
index: EngineChatList.Item.Index,
|
||||
presentationData: ChatListPresentationData,
|
||||
groupId: EngineChatList.Group,
|
||||
peers: [EngineChatList.GroupItem.Item],
|
||||
message: EngineMessage?,
|
||||
editing: Bool,
|
||||
unreadCount: Int,
|
||||
revealed: Bool,
|
||||
hiddenByDefault: Bool,
|
||||
storyState: ChatListNodeState.StoryState?
|
||||
) {
|
||||
self.index = index
|
||||
self.presentationData = presentationData
|
||||
self.groupId = groupId
|
||||
self.peers = peers
|
||||
self.message = message
|
||||
self.editing = editing
|
||||
self.unreadCount = unreadCount
|
||||
self.revealed = revealed
|
||||
self.hiddenByDefault = hiddenByDefault
|
||||
self.storyState = storyState
|
||||
}
|
||||
|
||||
static func ==(lhs: GroupReferenceEntryData, rhs: GroupReferenceEntryData) -> Bool {
|
||||
if lhs.index != rhs.index {
|
||||
return false
|
||||
}
|
||||
if lhs.presentationData !== rhs.presentationData {
|
||||
return false
|
||||
}
|
||||
if lhs.groupId != rhs.groupId {
|
||||
return false
|
||||
}
|
||||
if lhs.peers != rhs.peers {
|
||||
return false
|
||||
}
|
||||
if lhs.message?.stableId != rhs.message?.stableId {
|
||||
return false
|
||||
}
|
||||
if lhs.editing != rhs.editing {
|
||||
return false
|
||||
}
|
||||
if lhs.unreadCount != rhs.unreadCount {
|
||||
return false
|
||||
}
|
||||
if lhs.revealed != rhs.revealed {
|
||||
return false
|
||||
}
|
||||
if lhs.hiddenByDefault != rhs.hiddenByDefault {
|
||||
return false
|
||||
}
|
||||
if lhs.storyState != rhs.storyState {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case HeaderEntry
|
||||
case PeerEntry(PeerEntryData)
|
||||
case HoleEntry(EngineMessage.Index, theme: PresentationTheme)
|
||||
case GroupReferenceEntry(index: EngineChatList.Item.Index, presentationData: ChatListPresentationData, groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, editing: Bool, unreadCount: Int, revealed: Bool, hiddenByDefault: Bool)
|
||||
case GroupReferenceEntry(GroupReferenceEntryData)
|
||||
case ContactEntry(ContactEntryData)
|
||||
case ArchiveIntro(presentationData: ChatListPresentationData)
|
||||
case EmptyIntro(presentationData: ChatListPresentationData)
|
||||
@ -321,8 +393,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
return .index(peerEntry.index)
|
||||
case let .HoleEntry(holeIndex, _):
|
||||
return .index(.chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: holeIndex)))
|
||||
case let .GroupReferenceEntry(index, _, _, _, _, _, _, _, _):
|
||||
return .index(index)
|
||||
case let .GroupReferenceEntry(groupReferenceEntry):
|
||||
return .index(groupReferenceEntry.index)
|
||||
case let .ContactEntry(contactEntry):
|
||||
return .contact(id: contactEntry.peer.id, presence: contactEntry.presence)
|
||||
case .ArchiveIntro:
|
||||
@ -351,8 +423,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
case let .HoleEntry(holeIndex, _):
|
||||
return .Hole(Int64(holeIndex.id.id))
|
||||
case let .GroupReferenceEntry(_, _, groupId, _, _, _, _, _, _):
|
||||
return .GroupId(groupId)
|
||||
case let .GroupReferenceEntry(groupReferenceEntry):
|
||||
return .GroupId(groupReferenceEntry.groupId)
|
||||
case let .ContactEntry(contactEntry):
|
||||
return .ContactId(contactEntry.peer.id)
|
||||
case .ArchiveIntro:
|
||||
@ -393,35 +465,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case let .GroupReferenceEntry(lhsIndex, lhsPresentationData, lhsGroupId, lhsPeers, lhsMessage, lhsEditing, lhsUnreadState, lhsRevealed, lhsHiddenByDefault):
|
||||
if case let .GroupReferenceEntry(rhsIndex, rhsPresentationData, rhsGroupId, rhsPeers, rhsMessage, rhsEditing, rhsUnreadState, rhsRevealed, rhsHiddenByDefault) = rhs {
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
if lhsGroupId != rhsGroupId {
|
||||
return false
|
||||
}
|
||||
if lhsPeers != rhsPeers {
|
||||
return false
|
||||
}
|
||||
if lhsMessage?.stableId != rhsMessage?.stableId {
|
||||
return false
|
||||
}
|
||||
if lhsEditing != rhsEditing {
|
||||
return false
|
||||
}
|
||||
if lhsUnreadState != rhsUnreadState {
|
||||
return false
|
||||
}
|
||||
if lhsRevealed != rhsRevealed {
|
||||
return false
|
||||
}
|
||||
if lhsHiddenByDefault != rhsHiddenByDefault {
|
||||
return false
|
||||
}
|
||||
case let .GroupReferenceEntry(groupReferenceEntry):
|
||||
if case .GroupReferenceEntry(groupReferenceEntry) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -523,7 +568,7 @@ struct ChatListContactPeer {
|
||||
}
|
||||
}
|
||||
|
||||
func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, notice: ChatListNotice?, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation, contacts: [ChatListContactPeer]) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, notice: ChatListNotice?, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation, contacts: [ChatListContactPeer], accountPeerId: EnginePeer.Id) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
var result: [ChatListNodeEntry] = []
|
||||
|
||||
if !view.hasEarlier {
|
||||
@ -639,7 +684,12 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
||||
forumTopicData: entry.forumTopicData,
|
||||
topForumTopicItems: entry.topForumTopicItems,
|
||||
revealed: threadId == 1 && (state.hiddenItemShouldBeTemporaryRevealed || state.editing),
|
||||
storyState: state.peerStoryMapping[entry.renderedPeer.peerId]
|
||||
storyState: entry.renderedPeer.peerId == accountPeerId ? nil : entry.storyStats.flatMap { stats -> ChatListNodeState.StoryState in
|
||||
return ChatListNodeState.StoryState(
|
||||
stats: stats,
|
||||
hasUnseenCloseFriends: false
|
||||
)
|
||||
}
|
||||
))
|
||||
|
||||
if let threadInfo, threadInfo.isHidden {
|
||||
@ -783,7 +833,16 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
||||
if !view.hasLater, case .chatList = mode {
|
||||
for groupReference in view.groupItems {
|
||||
let messageIndex = EngineMessage.Index(id: EngineMessage.Id(peerId: EnginePeer.Id(0), namespace: 0, id: 0), timestamp: 1)
|
||||
result.append(.GroupReferenceEntry(
|
||||
var mappedStoryState: ChatListNodeState.StoryState?
|
||||
if let hasUnseenArchiveStories = state.hasUnseenArchiveStories {
|
||||
mappedStoryState = ChatListNodeState.StoryState(
|
||||
stats: EngineChatList.StoryStats(
|
||||
totalCount: 1, unseenCount: hasUnseenArchiveStories ? 1 : 0
|
||||
),
|
||||
hasUnseenCloseFriends: false
|
||||
)
|
||||
}
|
||||
result.append(.GroupReferenceEntry(ChatListNodeEntry.GroupReferenceEntryData(
|
||||
index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: pinningIndex, messageIndex: messageIndex)),
|
||||
presentationData: state.presentationData,
|
||||
groupId: groupReference.id,
|
||||
@ -792,8 +851,9 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
||||
editing: state.editing,
|
||||
unreadCount: groupReference.unreadCount,
|
||||
revealed: state.hiddenItemShouldBeTemporaryRevealed,
|
||||
hiddenByDefault: hideArchivedFolderByDefault
|
||||
))
|
||||
hiddenByDefault: hideArchivedFolderByDefault,
|
||||
storyState: mappedStoryState
|
||||
)))
|
||||
if pinningIndex != 0 {
|
||||
pinningIndex -= 1
|
||||
}
|
||||
|
@ -288,7 +288,8 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
isContact: false,
|
||||
autoremoveTimeout: nil
|
||||
autoremoveTimeout: nil,
|
||||
storyStats: nil
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -1236,8 +1236,8 @@ public final class ContactListNode: ASDisplayNode {
|
||||
return context.engine.data.get(EngineDataMap(
|
||||
view.entries.compactMap { entry -> EnginePeer.Id? in
|
||||
switch entry {
|
||||
case let .MessageEntry(_, _, _, _, _, renderedPeer, _, _, _, _, _, _, _):
|
||||
if let peer = renderedPeer.peer {
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peer {
|
||||
if let channel = peer as? TelegramChannel, case .group = channel.info {
|
||||
return peer.id
|
||||
}
|
||||
@ -1252,8 +1252,8 @@ public final class ContactListNode: ASDisplayNode {
|
||||
var peers: [(EnginePeer, Int32)] = []
|
||||
for entry in view.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(_, _, _, _, _, renderedPeer, _, _, _, _, _, _, _):
|
||||
if let peer = renderedPeer.peer {
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peer {
|
||||
if peer is TelegramGroup {
|
||||
peers.append((EnginePeer(peer), 0))
|
||||
} else if let channel = peer as? TelegramChannel, case .group = channel.info {
|
||||
|
@ -233,7 +233,10 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return self.contentScrollingEnded(listView: listView)
|
||||
}
|
||||
|
||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: true)
|
||||
self.contactListNode.storySubscriptions.set(.single(nil))
|
||||
self.storiesReady.set(.single(true))
|
||||
|
||||
/*self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: true)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||
guard let self else {
|
||||
return
|
||||
@ -243,7 +246,7 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
self.contactListNode.storySubscriptions.set(.single(storySubscriptions))
|
||||
|
||||
self.storiesReady.set(.single(true))
|
||||
})
|
||||
})*/
|
||||
|
||||
self.contactListNode.openStories = { [weak self] peer, sourceNode in
|
||||
guard let self else {
|
||||
|
@ -145,11 +145,11 @@ final class InstantPagePeerReferenceNode: ASDisplayNode, InstantPageNode {
|
||||
self.joinNode.addTarget(self, action: #selector(self.joinPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
let account = self.context.account
|
||||
let context = self.context
|
||||
let signal: Signal<EnginePeer, NoError> = actualizedPeer(postbox: account.postbox, network: account.network, peer: initialPeer._asPeer())
|
||||
let engine = context.engine
|
||||
let signal: Signal<EnginePeer, NoError> = actualizedPeer(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, peer: initialPeer._asPeer())
|
||||
|> mapToSignal({ peer -> Signal<EnginePeer, NoError> in
|
||||
if let peer = peer as? TelegramChannel, let username = peer.addressName, peer.accessHash == nil {
|
||||
return .single(.channel(peer)) |> then(context.engine.peers.resolvePeerByName(name: username)
|
||||
return .single(.channel(peer)) |> then(engine.peers.resolvePeerByName(name: username)
|
||||
|> mapToSignal({ updatedPeer -> Signal<EnginePeer, NoError> in
|
||||
if let updatedPeer = updatedPeer {
|
||||
return .single(updatedPeer)
|
||||
|
@ -214,7 +214,7 @@ public final class SecureIdAuthController: ViewController, StandalonePresentable
|
||||
|
||||
switch self.mode {
|
||||
case let .form(peerId, scope, publicKey, callbackUrl, _, _):
|
||||
self.formDisposable = (combineLatest(requestSecureIdForm(postbox: context.account.postbox, network: context.account.network, peerId: peerId, scope: scope, publicKey: publicKey), secureIdConfiguration(postbox: context.account.postbox, network: context.account.network) |> castError(RequestSecureIdFormError.self))
|
||||
self.formDisposable = (combineLatest(requestSecureIdForm(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network, peerId: peerId, scope: scope, publicKey: publicKey), secureIdConfiguration(postbox: context.account.postbox, network: context.account.network) |> castError(RequestSecureIdFormError.self))
|
||||
|> mapToSignal { form, configuration -> Signal<SecureIdEncryptedFormData, RequestSecureIdFormError> in
|
||||
return context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
|
||||
|
@ -111,85 +111,144 @@ public struct ChatListForumTopicData: Equatable {
|
||||
}
|
||||
|
||||
public enum ChatListEntry: Comparable {
|
||||
case MessageEntry(index: ChatListIndex, messages: [Message], readState: ChatListViewReadState?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, summaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: ChatListForumTopicData?, topForumTopics: [ChatListForumTopicData], hasFailed: Bool, isContact: Bool, autoremoveTimeout: Int32?)
|
||||
public struct MessageEntryData: Equatable {
|
||||
public var index: ChatListIndex
|
||||
public var messages: [Message]
|
||||
public var readState: ChatListViewReadState?
|
||||
public var isRemovedFromTotalUnreadCount: Bool
|
||||
public var embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||
public var renderedPeer: RenderedPeer
|
||||
public var presence: PeerPresence?
|
||||
public var summaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo]
|
||||
public var forumTopicData: ChatListForumTopicData?
|
||||
public var topForumTopics: [ChatListForumTopicData]
|
||||
public var hasFailed: Bool
|
||||
public var isContact: Bool
|
||||
public var autoremoveTimeout: Int32?
|
||||
public var storyStats: PeerStoryStats?
|
||||
|
||||
public init(
|
||||
index: ChatListIndex,
|
||||
messages: [Message],
|
||||
readState: ChatListViewReadState?,
|
||||
isRemovedFromTotalUnreadCount: Bool,
|
||||
embeddedInterfaceState: StoredPeerChatInterfaceState?,
|
||||
renderedPeer: RenderedPeer,
|
||||
presence: PeerPresence?,
|
||||
summaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo],
|
||||
forumTopicData: ChatListForumTopicData?,
|
||||
topForumTopics: [ChatListForumTopicData],
|
||||
hasFailed: Bool,
|
||||
isContact: Bool,
|
||||
autoremoveTimeout: Int32?,
|
||||
storyStats: PeerStoryStats?
|
||||
) {
|
||||
self.index = index
|
||||
self.messages = messages
|
||||
self.readState = readState
|
||||
self.isRemovedFromTotalUnreadCount = isRemovedFromTotalUnreadCount
|
||||
self.embeddedInterfaceState = embeddedInterfaceState
|
||||
self.renderedPeer = renderedPeer
|
||||
self.presence = presence
|
||||
self.summaryInfo = summaryInfo
|
||||
self.forumTopicData = forumTopicData
|
||||
self.topForumTopics = topForumTopics
|
||||
self.hasFailed = hasFailed
|
||||
self.isContact = isContact
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.storyStats = storyStats
|
||||
}
|
||||
|
||||
public static func ==(lhs: MessageEntryData, rhs: MessageEntryData) -> Bool {
|
||||
if lhs.index != rhs.index {
|
||||
return false
|
||||
}
|
||||
if lhs.readState != rhs.readState {
|
||||
return false
|
||||
}
|
||||
if lhs.messages.count != rhs.messages.count {
|
||||
return false
|
||||
}
|
||||
for i in 0 ..< lhs.messages.count {
|
||||
if lhs.messages[i].stableVersion != rhs.messages[i].stableVersion {
|
||||
return false
|
||||
}
|
||||
if lhs.messages[i].associatedStories != rhs.messages[i].associatedStories {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if lhs.isRemovedFromTotalUnreadCount != rhs.isRemovedFromTotalUnreadCount {
|
||||
return false
|
||||
}
|
||||
if let lhsEmbeddedState = lhs.embeddedInterfaceState, let rhsEmbeddedState = rhs.embeddedInterfaceState {
|
||||
if lhsEmbeddedState != rhsEmbeddedState {
|
||||
return false
|
||||
}
|
||||
} else if (lhs.embeddedInterfaceState != nil) != (rhs.embeddedInterfaceState != nil) {
|
||||
return false
|
||||
}
|
||||
if lhs.renderedPeer != rhs.renderedPeer {
|
||||
return false
|
||||
}
|
||||
if let lhsPresence = lhs.presence, let rhsPresence = rhs.presence {
|
||||
if !lhsPresence.isEqual(to: rhsPresence) {
|
||||
return false
|
||||
}
|
||||
} else if (lhs.presence != nil) != (rhs.presence != nil) {
|
||||
return false
|
||||
}
|
||||
if lhs.summaryInfo != rhs.summaryInfo {
|
||||
return false
|
||||
}
|
||||
if lhs.forumTopicData != rhs.forumTopicData {
|
||||
return false
|
||||
}
|
||||
if lhs.topForumTopics != rhs.topForumTopics {
|
||||
return false
|
||||
}
|
||||
if lhs.hasFailed != rhs.hasFailed {
|
||||
return false
|
||||
}
|
||||
if lhs.isContact != rhs.isContact {
|
||||
return false
|
||||
}
|
||||
if lhs.autoremoveTimeout != rhs.autoremoveTimeout {
|
||||
return false
|
||||
}
|
||||
if lhs.storyStats != rhs.storyStats {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case MessageEntry(MessageEntryData)
|
||||
case HoleEntry(ChatListHole)
|
||||
|
||||
public var index: ChatListIndex {
|
||||
switch self {
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return index
|
||||
case let .HoleEntry(hole):
|
||||
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
||||
case let .MessageEntry(entryData):
|
||||
return entryData.index
|
||||
case let .HoleEntry(hole):
|
||||
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListEntry, rhs: ChatListEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .MessageEntry(lhsIndex, lhsMessages, lhsReadState, lhsIsRemovedFromTotalUnreadCount, lhsEmbeddedState, lhsPeer, lhsPresence, lhsInfo, lhsForumTopicData, lhsTopForumTopics, lhsHasFailed, lhsIsContact, lhsAutoremoveTimeout):
|
||||
switch rhs {
|
||||
case let .MessageEntry(rhsIndex, rhsMessages, rhsReadState, rhsIsRemovedFromTotalUnreadCount, rhsEmbeddedState, rhsPeer, rhsPresence, rhsInfo, rhsForumTopicData, rhsTopForumTopics, rhsHasFailed, rhsIsContact, rhsAutoremoveTimeout):
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
if lhsReadState != rhsReadState {
|
||||
return false
|
||||
}
|
||||
if lhsMessages.count != rhsMessages.count {
|
||||
return false
|
||||
}
|
||||
for i in 0 ..< lhsMessages.count {
|
||||
if lhsMessages[i].stableVersion != rhsMessages[i].stableVersion {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if lhsIsRemovedFromTotalUnreadCount != rhsIsRemovedFromTotalUnreadCount {
|
||||
return false
|
||||
}
|
||||
if let lhsEmbeddedState = lhsEmbeddedState, let rhsEmbeddedState = rhsEmbeddedState {
|
||||
if lhsEmbeddedState != rhsEmbeddedState {
|
||||
return false
|
||||
}
|
||||
} else if (lhsEmbeddedState != nil) != (rhsEmbeddedState != nil) {
|
||||
return false
|
||||
}
|
||||
if lhsPeer != rhsPeer {
|
||||
return false
|
||||
}
|
||||
if let lhsPresence = lhsPresence, let rhsPresence = rhsPresence {
|
||||
if !lhsPresence.isEqual(to: rhsPresence) {
|
||||
return false
|
||||
}
|
||||
} else if (lhsPresence != nil) != (rhsPresence != nil) {
|
||||
return false
|
||||
}
|
||||
if lhsInfo != rhsInfo {
|
||||
return false
|
||||
}
|
||||
if lhsForumTopicData != rhsForumTopicData {
|
||||
return false
|
||||
}
|
||||
if lhsTopForumTopics != rhsTopForumTopics {
|
||||
return false
|
||||
}
|
||||
if lhsHasFailed != rhsHasFailed {
|
||||
return false
|
||||
}
|
||||
if lhsIsContact != rhsIsContact {
|
||||
return false
|
||||
}
|
||||
if lhsAutoremoveTimeout != rhsAutoremoveTimeout {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case let .HoleEntry(hole):
|
||||
if case .HoleEntry(hole) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .MessageEntry(entryData):
|
||||
if case .MessageEntry(entryData) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .HoleEntry(hole):
|
||||
if case .HoleEntry(hole) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,9 +257,89 @@ public enum ChatListEntry: Comparable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct PeerStoryStats: Equatable {
|
||||
public var totalCount: Int
|
||||
public var unseenCount: Int
|
||||
|
||||
public init(totalCount: Int, unseenCount: Int) {
|
||||
self.totalCount = totalCount
|
||||
self.unseenCount = unseenCount
|
||||
}
|
||||
}
|
||||
|
||||
func fetchPeerStoryStats(postbox: PostboxImpl, peerId: PeerId) -> PeerStoryStats? {
|
||||
guard let topItems = postbox.storyTopItemsTable.get(peerId: peerId) else {
|
||||
return nil
|
||||
}
|
||||
if topItems.id == 0 {
|
||||
return nil
|
||||
}
|
||||
guard let state = postbox.storyPeerStatesTable.get(key: .peer(peerId)) else {
|
||||
return nil
|
||||
}
|
||||
if topItems.isExact {
|
||||
let stats = postbox.storyItemsTable.getStats(peerId: peerId, maxSeenId: state.maxSeenId)
|
||||
return PeerStoryStats(totalCount: stats.total, unseenCount: stats.unseen)
|
||||
} else {
|
||||
return PeerStoryStats(totalCount: 1, unseenCount: topItems.id > state.maxSeenId ? 1 : 0)
|
||||
}
|
||||
}
|
||||
|
||||
enum MutableChatListEntry: Equatable {
|
||||
struct MessageEntryData {
|
||||
var index: ChatListIndex
|
||||
var messages: [Message]
|
||||
var readState: ChatListViewReadState?
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
var isRemovedFromTotalUnreadCount: Bool
|
||||
var embeddedInterfaceState: StoredPeerChatInterfaceState?
|
||||
var renderedPeer: RenderedPeer
|
||||
var presence: PeerPresence?
|
||||
var tagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo]
|
||||
var forumTopicData: ChatListForumTopicData?
|
||||
var topForumTopics: [ChatListForumTopicData]
|
||||
var hasFailedMessages: Bool
|
||||
var isContact: Bool
|
||||
var autoremoveTimeout: Int32?
|
||||
var storyStats: PeerStoryStats?
|
||||
|
||||
init(
|
||||
index: ChatListIndex,
|
||||
messages: [Message],
|
||||
readState: ChatListViewReadState?,
|
||||
notificationSettings: PeerNotificationSettings?,
|
||||
isRemovedFromTotalUnreadCount: Bool,
|
||||
embeddedInterfaceState: StoredPeerChatInterfaceState?,
|
||||
renderedPeer: RenderedPeer,
|
||||
presence: PeerPresence?,
|
||||
tagSummaryInfo: [ChatListEntryMessageTagSummaryKey : ChatListMessageTagSummaryInfo],
|
||||
forumTopicData: ChatListForumTopicData?,
|
||||
topForumTopics: [ChatListForumTopicData],
|
||||
hasFailedMessages: Bool,
|
||||
isContact: Bool,
|
||||
autoremoveTimeout: Int32?,
|
||||
storyStats: PeerStoryStats?
|
||||
) {
|
||||
self.index = index
|
||||
self.messages = messages
|
||||
self.readState = readState
|
||||
self.notificationSettings = notificationSettings
|
||||
self.isRemovedFromTotalUnreadCount = isRemovedFromTotalUnreadCount
|
||||
self.embeddedInterfaceState = embeddedInterfaceState
|
||||
self.renderedPeer = renderedPeer
|
||||
self.presence = presence
|
||||
self.tagSummaryInfo = tagSummaryInfo
|
||||
self.forumTopicData = forumTopicData
|
||||
self.topForumTopics = topForumTopics
|
||||
self.hasFailedMessages = hasFailedMessages
|
||||
self.isContact = isContact
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.storyStats = storyStats
|
||||
}
|
||||
}
|
||||
|
||||
case IntermediateMessageEntry(index: ChatListIndex, messageIndex: MessageIndex?)
|
||||
case MessageEntry(index: ChatListIndex, messages: [Message], readState: ChatListViewReadState?, notificationSettings: PeerNotificationSettings?, isRemovedFromTotalUnreadCount: Bool, embeddedInterfaceState: StoredPeerChatInterfaceState?, renderedPeer: RenderedPeer, presence: PeerPresence?, tagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo], forumTopicData: ChatListForumTopicData?, topForumTopics: [ChatListForumTopicData], hasFailedMessages: Bool, isContact: Bool, autoremoveTimeout: Int32?)
|
||||
case MessageEntry(MessageEntryData)
|
||||
case HoleEntry(ChatListHole)
|
||||
|
||||
init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) {
|
||||
@ -214,12 +353,12 @@ enum MutableChatListEntry: Equatable {
|
||||
|
||||
var index: ChatListIndex {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(index, _):
|
||||
return index
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return index
|
||||
case let .HoleEntry(hole):
|
||||
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
||||
case let .IntermediateMessageEntry(index, _):
|
||||
return index
|
||||
case let .MessageEntry(data):
|
||||
return data.index
|
||||
case let .HoleEntry(hole):
|
||||
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,7 +881,25 @@ final class MutableChatListView {
|
||||
autoremoveTimeout = postbox.seedConfiguration.decodeAutoremoveTimeout(cachedData)
|
||||
}
|
||||
|
||||
return .MessageEntry(index: index, messages: renderedMessages, readState: readState, notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: false, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: renderedPeer, presence: presence, tagSummaryInfo: [:], forumTopicData: forumTopicData, topForumTopics: topForumTopics, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId), isContact: isContact, autoremoveTimeout: autoremoveTimeout)
|
||||
let storyStats = fetchPeerStoryStats(postbox: postbox, peerId: index.messageIndex.id.peerId)
|
||||
|
||||
return .MessageEntry(MutableChatListEntry.MessageEntryData(
|
||||
index: index,
|
||||
messages: renderedMessages,
|
||||
readState: readState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: false,
|
||||
embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId),
|
||||
renderedPeer: renderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: [:],
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId),
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: autoremoveTimeout,
|
||||
storyStats: storyStats
|
||||
))
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -771,8 +928,23 @@ public final class ChatListView {
|
||||
var entries: [ChatListEntry] = []
|
||||
for entry in mutableView.sampledState.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, combinedReadState, _, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, forumTopicData, topForumTopics, hasFailed, isContact, autoremoveTimeout):
|
||||
entries.append(.MessageEntry(index: index, messages: messages, readState: combinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedState, renderedPeer: peer, presence: peerPresence, summaryInfo: summaryInfo, forumTopicData: forumTopicData, topForumTopics: topForumTopics, hasFailed: hasFailed, isContact: isContact, autoremoveTimeout: autoremoveTimeout))
|
||||
case let .MessageEntry(entryData):
|
||||
entries.append(.MessageEntry(ChatListEntry.MessageEntryData(
|
||||
index: entryData.index,
|
||||
messages: entryData.messages,
|
||||
readState: entryData.readState,
|
||||
isRemovedFromTotalUnreadCount: entryData.isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: entryData.embeddedInterfaceState,
|
||||
renderedPeer: entryData.renderedPeer,
|
||||
presence: entryData.presence,
|
||||
summaryInfo: entryData.tagSummaryInfo,
|
||||
forumTopicData: entryData.forumTopicData,
|
||||
topForumTopics: entryData.topForumTopics,
|
||||
hasFailed: entryData.hasFailedMessages,
|
||||
isContact: entryData.isContact,
|
||||
autoremoveTimeout: entryData.autoremoveTimeout,
|
||||
storyStats: entryData.storyStats
|
||||
)))
|
||||
case let .HoleEntry(hole):
|
||||
entries.append(.HoleEntry(hole))
|
||||
case .IntermediateMessageEntry:
|
||||
@ -789,9 +961,24 @@ public final class ChatListView {
|
||||
var additionalItemEntries: [ChatListAdditionalItemEntry] = []
|
||||
for entry in mutableView.additionalItemEntries {
|
||||
switch entry.entry {
|
||||
case let .MessageEntry(index, messages, combinedReadState, _, isExcludedFromUnreadCount, embeddedState, peer, peerPresence, summaryInfo, forumTopicData, topForumTopics, hasFailed, isContact, autoremoveTimeout):
|
||||
case let .MessageEntry(entryData):
|
||||
additionalItemEntries.append(ChatListAdditionalItemEntry(
|
||||
entry: .MessageEntry(index: index, messages: messages, readState: combinedReadState, isRemovedFromTotalUnreadCount: isExcludedFromUnreadCount, embeddedInterfaceState: embeddedState, renderedPeer: peer, presence: peerPresence, summaryInfo: summaryInfo, forumTopicData: forumTopicData, topForumTopics: topForumTopics, hasFailed: hasFailed, isContact: isContact, autoremoveTimeout: autoremoveTimeout),
|
||||
entry: .MessageEntry(ChatListEntry.MessageEntryData(
|
||||
index: entryData.index,
|
||||
messages: entryData.messages,
|
||||
readState: entryData.readState,
|
||||
isRemovedFromTotalUnreadCount: entryData.isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: entryData.embeddedInterfaceState,
|
||||
renderedPeer: entryData.renderedPeer,
|
||||
presence: entryData.presence,
|
||||
summaryInfo: entryData.tagSummaryInfo,
|
||||
forumTopicData: entryData.forumTopicData,
|
||||
topForumTopics: entryData.topForumTopics,
|
||||
hasFailed: entryData.hasFailedMessages,
|
||||
isContact: entryData.isContact,
|
||||
autoremoveTimeout: entryData.autoremoveTimeout,
|
||||
storyStats: entryData.storyStats
|
||||
)),
|
||||
info: entry.info
|
||||
))
|
||||
case .HoleEntry:
|
||||
|
@ -533,8 +533,8 @@ private final class ChatListViewSpaceState {
|
||||
let entryPeer: Peer
|
||||
let entryNotificationsPeerId: PeerId
|
||||
switch entry {
|
||||
case let .MessageEntry(_, _, _, _, _, _, renderedPeer, _, _, _, _, _, _, _):
|
||||
if let peer = renderedPeer.peer {
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peer {
|
||||
entryPeer = peer
|
||||
entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
} else {
|
||||
@ -648,13 +648,17 @@ private final class ChatListViewSpaceState {
|
||||
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, _, _, embeddedInterfaceState, renderedPeer, presence, tagSummaryInfo, forumTopicData, topForumTopics, hasFailedMessages, isContact, autoremoveTimeout):
|
||||
if let peer = renderedPeer.peer {
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peer {
|
||||
let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
if let (_, updated) = transaction.currentUpdatedPeerNotificationSettings[notificationsPeerId] {
|
||||
let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: updated)
|
||||
|
||||
return .MessageEntry(index: index, messages: messages, readState: readState, notificationSettings: updated, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedInterfaceState, renderedPeer: renderedPeer, presence: presence, tagSummaryInfo: tagSummaryInfo, forumTopicData: forumTopicData, topForumTopics: topForumTopics, hasFailedMessages: hasFailedMessages, isContact: isContact, autoremoveTimeout: autoremoveTimeout)
|
||||
var entryData = entryData
|
||||
entryData.notificationSettings = updated
|
||||
entryData.isRemovedFromTotalUnreadCount = isRemovedFromTotalUnreadCount
|
||||
|
||||
return .MessageEntry(entryData)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -672,24 +676,11 @@ private final class ChatListViewSpaceState {
|
||||
if !transaction.updatedFailedMessagePeerIds.isEmpty {
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, renderedPeer, presence, tagSummaryInfo, forumTopicData, topForumTopics, _, isContact, autoremoveTimeout):
|
||||
if transaction.updatedFailedMessagePeerIds.contains(index.messageIndex.id.peerId) {
|
||||
return .MessageEntry(
|
||||
index: index,
|
||||
messages: messages,
|
||||
readState: readState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: embeddedInterfaceState,
|
||||
renderedPeer: renderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: tagSummaryInfo,
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId),
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: autoremoveTimeout
|
||||
)
|
||||
case let .MessageEntry(entryData):
|
||||
if transaction.updatedFailedMessagePeerIds.contains(entryData.index.messageIndex.id.peerId) {
|
||||
var entryData = entryData
|
||||
entryData.hasFailedMessages = postbox.messageHistoryFailedTable.contains(peerId: entryData.index.messageIndex.id.peerId)
|
||||
return .MessageEntry(entryData)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -704,8 +695,8 @@ private final class ChatListViewSpaceState {
|
||||
if !transaction.currentUpdatedPeers.isEmpty {
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, entryRenderedPeer, presence, tagSummaryInfo, forumTopicData, topForumTopics, hasFailedMessages, isContact, autoremoveTimeout):
|
||||
var updatedMessages: [Message] = messages
|
||||
case let .MessageEntry(entryData):
|
||||
var updatedMessages: [Message] = entryData.messages
|
||||
var hasUpdatedMessages = false
|
||||
for i in 0 ..< updatedMessages.count {
|
||||
if let updatedMessage = updateMessagePeers(updatedMessages[i], updatedPeers: transaction.currentUpdatedPeers) {
|
||||
@ -713,25 +704,14 @@ private final class ChatListViewSpaceState {
|
||||
hasUpdatedMessages = true
|
||||
}
|
||||
}
|
||||
let renderedPeer = updatedRenderedPeer(postbox: postbox, renderedPeer: entryRenderedPeer, updatedPeers: transaction.currentUpdatedPeers)
|
||||
let renderedPeer = updatedRenderedPeer(postbox: postbox, renderedPeer: entryData.renderedPeer, updatedPeers: transaction.currentUpdatedPeers)
|
||||
|
||||
var entryData = entryData
|
||||
entryData.messages = updatedMessages
|
||||
entryData.renderedPeer = renderedPeer ?? entryData.renderedPeer
|
||||
|
||||
if hasUpdatedMessages || renderedPeer != nil {
|
||||
return .MessageEntry(
|
||||
index: index,
|
||||
messages: updatedMessages,
|
||||
readState: readState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: embeddedInterfaceState,
|
||||
renderedPeer: renderedPeer ?? entryRenderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: tagSummaryInfo,
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: hasFailedMessages,
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: autoremoveTimeout
|
||||
)
|
||||
return .MessageEntry(entryData)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -746,28 +726,15 @@ private final class ChatListViewSpaceState {
|
||||
if !transaction.currentUpdatedPeerPresences.isEmpty {
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, entryRenderedPeer, _, tagSummaryInfo, forumTopicData, topForumTopics, hasFailedMessages, isContact, autoremoveTimeout):
|
||||
var presencePeerId = entryRenderedPeer.peerId
|
||||
if let peer = entryRenderedPeer.peers[entryRenderedPeer.peerId], let associatedPeerId = peer.associatedPeerId {
|
||||
case let .MessageEntry(entryData):
|
||||
var presencePeerId = entryData.renderedPeer.peerId
|
||||
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], let associatedPeerId = peer.associatedPeerId {
|
||||
presencePeerId = associatedPeerId
|
||||
}
|
||||
if let presence = transaction.currentUpdatedPeerPresences[presencePeerId] {
|
||||
return .MessageEntry(
|
||||
index: index,
|
||||
messages: messages,
|
||||
readState: readState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: embeddedInterfaceState,
|
||||
renderedPeer: entryRenderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: tagSummaryInfo,
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: hasFailedMessages,
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: autoremoveTimeout
|
||||
)
|
||||
var entryData = entryData
|
||||
entryData.presence = presence
|
||||
return .MessageEntry(entryData)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -785,8 +752,8 @@ private final class ChatListViewSpaceState {
|
||||
let entryPeer: Peer
|
||||
let entryNotificationsPeerId: PeerId
|
||||
switch entry {
|
||||
case let .MessageEntry(_, _, _, _, _, _, entryRenderedPeer, _, _, _, _, _, _, _):
|
||||
if let peer = entryRenderedPeer.peer {
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peer {
|
||||
entryPeer = peer
|
||||
entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id
|
||||
} else {
|
||||
@ -913,17 +880,17 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
}
|
||||
|
||||
if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty || !transaction.updatedPeerThreadsSummaries.isEmpty || cachedPeerDataUpdated {
|
||||
if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty || !transaction.updatedPeerThreadsSummaries.isEmpty || cachedPeerDataUpdated || !transaction.currentStoryTopItemEvents.isEmpty || !transaction.storyPeerStatesEvents.isEmpty {
|
||||
if self.orderedEntries.mutableScan({ entry in
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, notificationSettings, isRemovedFromTotalUnreadCount, embeddedInterfaceState, entryRenderedPeer, presence, tagSummaryInfo, forumTopicData, topForumTopics, hasFailedMessages, isContact, autoremoveTimeout):
|
||||
var updatedChatListMessageTagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo] = tagSummaryInfo
|
||||
case let .MessageEntry(entryData):
|
||||
var updatedChatListMessageTagSummaryInfo: [ChatListEntryMessageTagSummaryKey: ChatListMessageTagSummaryInfo] = entryData.tagSummaryInfo
|
||||
var didUpdateSummaryInfo = false
|
||||
|
||||
for (key, component) in self.summaryComponents.components {
|
||||
var updatedTagSummaryCount: Int32?
|
||||
if let tagSummary = component.tagSummary {
|
||||
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace)
|
||||
let key = MessageHistoryTagsSummaryKey(tag: key.tag, peerId: entryData.index.messageIndex.id.peerId, threadId: nil, namespace: tagSummary.namespace)
|
||||
if let summary = transaction.currentUpdatedMessageTagSummaries[key] {
|
||||
updatedTagSummaryCount = summary.count
|
||||
}
|
||||
@ -931,7 +898,7 @@ private final class ChatListViewSpaceState {
|
||||
|
||||
var updatedActionsSummaryCount: Int32?
|
||||
if let actionsSummary = component.actionsSummary {
|
||||
let key = PendingMessageActionsSummaryKey(type: key.actionType, peerId: index.messageIndex.id.peerId, namespace: actionsSummary.namespace)
|
||||
let key = PendingMessageActionsSummaryKey(type: key.actionType, peerId: entryData.index.messageIndex.id.peerId, namespace: actionsSummary.namespace)
|
||||
if let count = transaction.currentUpdatedMessageActionsSummaries[key] {
|
||||
updatedActionsSummaryCount = count
|
||||
}
|
||||
@ -946,8 +913,8 @@ private final class ChatListViewSpaceState {
|
||||
}
|
||||
}
|
||||
|
||||
var updatedReadState = readState
|
||||
if let peer = postbox.peerTable.get(index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
var updatedReadState = entryData.readState
|
||||
if let peer = postbox.peerTable.get(entryData.index.messageIndex.id.peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
|
||||
let summary = postbox.peerThreadsSummaryTable.get(peerId: peer.id)
|
||||
|
||||
var count: Int32 = 0
|
||||
@ -961,40 +928,35 @@ private final class ChatListViewSpaceState {
|
||||
|
||||
updatedReadState = ChatListViewReadState(state: CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 0, maxKnownId: 0, count: count, markedUnread: false))]), isMuted: isMuted)
|
||||
} else {
|
||||
updatedReadState = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId).flatMap { state in
|
||||
updatedReadState = postbox.readStateTable.getCombinedState(entryData.index.messageIndex.id.peerId).flatMap { state in
|
||||
return ChatListViewReadState(state: state, isMuted: false)
|
||||
}
|
||||
}
|
||||
|
||||
if updatedReadState != readState {
|
||||
if updatedReadState != entryData.readState {
|
||||
didUpdateSummaryInfo = true
|
||||
}
|
||||
|
||||
var updatedAutoremoveTimeout: Int32?
|
||||
if let cachedData = postbox.cachedPeerDataTable.get(index.messageIndex.id.peerId) {
|
||||
if let cachedData = postbox.cachedPeerDataTable.get(entryData.index.messageIndex.id.peerId) {
|
||||
updatedAutoremoveTimeout = postbox.seedConfiguration.decodeAutoremoveTimeout(cachedData)
|
||||
if updatedAutoremoveTimeout != autoremoveTimeout {
|
||||
if updatedAutoremoveTimeout != entryData.autoremoveTimeout {
|
||||
didUpdateSummaryInfo = true
|
||||
}
|
||||
}
|
||||
|
||||
let storyStats = fetchPeerStoryStats(postbox: postbox, peerId: entryData.index.messageIndex.id.peerId)
|
||||
if entryData.storyStats != storyStats {
|
||||
didUpdateSummaryInfo = true
|
||||
}
|
||||
|
||||
if didUpdateSummaryInfo {
|
||||
return .MessageEntry(
|
||||
index: index,
|
||||
messages: messages,
|
||||
readState: updatedReadState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: embeddedInterfaceState,
|
||||
renderedPeer: entryRenderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: updatedChatListMessageTagSummaryInfo,
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: hasFailedMessages,
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: updatedAutoremoveTimeout
|
||||
)
|
||||
var entryData = entryData
|
||||
entryData.readState = updatedReadState
|
||||
entryData.tagSummaryInfo = updatedChatListMessageTagSummaryInfo
|
||||
entryData.autoremoveTimeout = updatedAutoremoveTimeout
|
||||
entryData.storyStats = storyStats
|
||||
return .MessageEntry(entryData)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -1127,8 +1089,8 @@ private extension MutableChatListEntry {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(index, _):
|
||||
return index.messageIndex.id.peerId
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return index.messageIndex.id.peerId
|
||||
case let .MessageEntry(entryData):
|
||||
return entryData.index.messageIndex.id.peerId
|
||||
case .HoleEntry:
|
||||
return nil
|
||||
}
|
||||
@ -1138,8 +1100,8 @@ private extension MutableChatListEntry {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(index, _):
|
||||
return MutableChatListEntryIndex(index: index, isMessage: true)
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return MutableChatListEntryIndex(index: index, isMessage: true)
|
||||
case let .MessageEntry(entryData):
|
||||
return MutableChatListEntryIndex(index: entryData.index, isMessage: true)
|
||||
case let .HoleEntry(hole):
|
||||
return MutableChatListEntryIndex(index: ChatListIndex(pinningIndex: nil, messageIndex: hole.index), isMessage: false)
|
||||
}
|
||||
@ -1149,8 +1111,8 @@ private extension MutableChatListEntry {
|
||||
switch self {
|
||||
case let .IntermediateMessageEntry(index, _):
|
||||
return .peer(index.messageIndex.id.peerId)
|
||||
case let .MessageEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return .peer(index.messageIndex.id.peerId)
|
||||
case let .MessageEntry(entryData):
|
||||
return .peer(entryData.index.messageIndex.id.peerId)
|
||||
case let .HoleEntry(hole):
|
||||
return .hole(hole.index)
|
||||
}
|
||||
@ -1635,7 +1597,25 @@ struct ChatListViewState {
|
||||
autoremoveTimeout = postbox.seedConfiguration.decodeAutoremoveTimeout(cachedData)
|
||||
}
|
||||
|
||||
let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, messages: renderedMessages, readState: readState, notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId), renderedPeer: renderedPeer, presence: presence, tagSummaryInfo: tagSummaryInfo, forumTopicData: forumTopicData, topForumTopics: topForumTopics, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId), autoremoveTimeout: autoremoveTimeout)
|
||||
let storyStats = fetchPeerStoryStats(postbox: postbox, peerId: index.messageIndex.id.peerId)
|
||||
|
||||
let updatedEntry: MutableChatListEntry = .MessageEntry(MutableChatListEntry.MessageEntryData(
|
||||
index: index,
|
||||
messages: renderedMessages,
|
||||
readState: readState,
|
||||
notificationSettings: notificationSettings,
|
||||
isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount,
|
||||
embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId),
|
||||
renderedPeer: renderedPeer,
|
||||
presence: presence,
|
||||
tagSummaryInfo: tagSummaryInfo,
|
||||
forumTopicData: forumTopicData,
|
||||
topForumTopics: topForumTopics,
|
||||
hasFailedMessages: false,
|
||||
isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId),
|
||||
autoremoveTimeout: autoremoveTimeout,
|
||||
storyStats: storyStats
|
||||
))
|
||||
if directionIndex == 0 {
|
||||
self.stateBySpace[space]!.orderedEntries.setLowerOrAtAnchorAtArrayIndex(listIndex, to: updatedEntry)
|
||||
} else {
|
||||
|
@ -1291,12 +1291,12 @@ public final class Transaction {
|
||||
self.postbox!.setLocalStoryState(state: state)
|
||||
}
|
||||
|
||||
public func getPeerStoryState(peerId: PeerId) -> CodableEntry? {
|
||||
public func getPeerStoryState(peerId: PeerId) -> StoredStoryPeerState? {
|
||||
assert(!self.disposed)
|
||||
return self.postbox!.getPeerStoryState(peerId: peerId)
|
||||
}
|
||||
|
||||
public func setPeerStoryState(peerId: PeerId, state: CodableEntry?) {
|
||||
public func setPeerStoryState(peerId: PeerId, state: StoredStoryPeerState?) {
|
||||
assert(!self.disposed)
|
||||
self.postbox!.setPeerStoryState(peerId: peerId, state: state)
|
||||
}
|
||||
@ -1306,6 +1306,11 @@ public final class Transaction {
|
||||
self.postbox!.setStoryItems(peerId: peerId, items: items)
|
||||
}
|
||||
|
||||
public func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32) {
|
||||
assert(!self.disposed)
|
||||
self.postbox!.setStoryItemsInexactMaxId(peerId: peerId, id: id)
|
||||
}
|
||||
|
||||
public func getStoryItems(peerId: PeerId) -> [StoryItemsTableEntry] {
|
||||
return self.postbox!.getStoryItems(peerId: peerId)
|
||||
}
|
||||
@ -1557,9 +1562,11 @@ final class PostboxImpl {
|
||||
private var currentHiddenChatIds: [PeerId: Bag<Void>] = [:]
|
||||
private var currentUpdatedHiddenPeerIds: Bool = false
|
||||
|
||||
private var currentStoryStatesEvents: [StoryStatesTable.Event] = []
|
||||
private var currentStoryGeneralStatesEvents: [StoryGeneralStatesTable.Event] = []
|
||||
private var currentStoryPeerStatesEvents: [StoryPeerStatesTable.Event] = []
|
||||
private var currentStorySubscriptionsEvents: [StorySubscriptionsTable.Event] = []
|
||||
private var currentStoryItemsEvents: [StoryItemsTable.Event] = []
|
||||
private var currentStoryTopItemEvents: [StoryTopItemsTable.Event] = []
|
||||
private var currentStoryEvents: [StoryTable.Event] = []
|
||||
|
||||
var hiddenChatIds: Set<PeerId> {
|
||||
@ -1680,9 +1687,11 @@ final class PostboxImpl {
|
||||
let messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable
|
||||
let groupMessageStatsTable: GroupMessageStatsTable
|
||||
let peerTimeoutPropertiesTable: PeerTimeoutPropertiesTable
|
||||
let storyStatesTable: StoryStatesTable
|
||||
let storyGeneralStatesTable: StoryGeneralStatesTable
|
||||
let storyPeerStatesTable: StoryPeerStatesTable
|
||||
let storySubscriptionsTable: StorySubscriptionsTable
|
||||
let storyItemsTable: StoryItemsTable
|
||||
let storyTopItemsTable: StoryTopItemsTable
|
||||
let storyTable: StoryTable
|
||||
|
||||
//temporary
|
||||
@ -1773,9 +1782,13 @@ final class PostboxImpl {
|
||||
self.noticeTable = NoticeTable(valueBox: self.valueBox, table: NoticeTable.tableSpec(43), useCaches: useCaches)
|
||||
self.deviceContactImportInfoTable = DeviceContactImportInfoTable(valueBox: self.valueBox, table: DeviceContactImportInfoTable.tableSpec(54), useCaches: useCaches)
|
||||
self.groupMessageStatsTable = GroupMessageStatsTable(valueBox: self.valueBox, table: GroupMessageStatsTable.tableSpec(58), useCaches: useCaches)
|
||||
self.storyStatesTable = StoryStatesTable(valueBox: self.valueBox, table: StoryStatesTable.tableSpec(65), useCaches: useCaches)
|
||||
|
||||
self.storyGeneralStatesTable = StoryGeneralStatesTable(valueBox: self.valueBox, table: StoryGeneralStatesTable.tableSpec(65), useCaches: useCaches)
|
||||
self.storyPeerStatesTable = StoryPeerStatesTable(valueBox: self.valueBox, table: StoryPeerStatesTable.tableSpec(79), useCaches: useCaches)
|
||||
|
||||
self.storySubscriptionsTable = StorySubscriptionsTable(valueBox: self.valueBox, table: StorySubscriptionsTable.tableSpec(78), useCaches: useCaches)
|
||||
self.storyItemsTable = StoryItemsTable(valueBox: self.valueBox, table: StoryItemsTable.tableSpec(69), useCaches: useCaches)
|
||||
self.storyTopItemsTable = StoryTopItemsTable(valueBox: self.valueBox, table: StoryTopItemsTable.tableSpec(80), useCaches: useCaches)
|
||||
self.storyTable = StoryTable(valueBox: self.valueBox, table: StoryTable.tableSpec(70), useCaches: useCaches)
|
||||
|
||||
var tables: [Table] = []
|
||||
@ -1844,9 +1857,11 @@ final class PostboxImpl {
|
||||
tables.append(self.messageHistoryHoleIndexTable)
|
||||
tables.append(self.groupMessageStatsTable)
|
||||
tables.append(self.peerTimeoutPropertiesTable)
|
||||
tables.append(self.storyStatesTable)
|
||||
tables.append(self.storyGeneralStatesTable)
|
||||
tables.append(self.storyPeerStatesTable)
|
||||
tables.append(self.storySubscriptionsTable)
|
||||
tables.append(self.storyItemsTable)
|
||||
tables.append(self.storyTopItemsTable)
|
||||
tables.append(self.storyTable)
|
||||
|
||||
self.tables = tables
|
||||
@ -2188,7 +2203,7 @@ final class PostboxImpl {
|
||||
|
||||
fileprivate func getAllStorySubscriptions(key: PostboxStorySubscriptionsKey) -> (state: CodableEntry?, peerIds: [PeerId]) {
|
||||
return (
|
||||
self.storyStatesTable.get(key: .subscriptions(key)),
|
||||
self.storyGeneralStatesTable.get(key: .subscriptions(key)),
|
||||
self.storySubscriptionsTable.getAll(subscriptionsKey: key)
|
||||
)
|
||||
}
|
||||
@ -2198,41 +2213,48 @@ final class PostboxImpl {
|
||||
}
|
||||
|
||||
fileprivate func replaceAllStorySubscriptions(key: PostboxStorySubscriptionsKey, state: CodableEntry?, peerIds: [PeerId]) {
|
||||
self.storyStatesTable.set(key: .subscriptions(key), value: state, events: &self.currentStoryStatesEvents)
|
||||
self.storyGeneralStatesTable.set(key: .subscriptions(key), value: state, events: &self.currentStoryGeneralStatesEvents)
|
||||
self.storySubscriptionsTable.replaceAll(subscriptionsKey: key, peerIds: peerIds, events: &self.currentStorySubscriptionsEvents)
|
||||
}
|
||||
|
||||
fileprivate func getLocalStoryState() -> CodableEntry? {
|
||||
return self.storyStatesTable.get(key: .local)
|
||||
return self.storyGeneralStatesTable.get(key: .local)
|
||||
}
|
||||
|
||||
fileprivate func getSubscriptionsStoriesState(key: PostboxStorySubscriptionsKey) -> CodableEntry? {
|
||||
return self.storyStatesTable.get(key: .subscriptions(key))
|
||||
return self.storyGeneralStatesTable.get(key: .subscriptions(key))
|
||||
}
|
||||
|
||||
fileprivate func setSubscriptionsStoriesState(key: PostboxStorySubscriptionsKey, state: CodableEntry?) {
|
||||
self.storyStatesTable.set(key: .subscriptions(key), value: state, events: &self.currentStoryStatesEvents)
|
||||
self.storyGeneralStatesTable.set(key: .subscriptions(key), value: state, events: &self.currentStoryGeneralStatesEvents)
|
||||
}
|
||||
|
||||
fileprivate func setLocalStoryState(state: CodableEntry?) {
|
||||
self.storyStatesTable.set(key: .local, value: state, events: &self.currentStoryStatesEvents)
|
||||
self.storyGeneralStatesTable.set(key: .local, value: state, events: &self.currentStoryGeneralStatesEvents)
|
||||
}
|
||||
|
||||
fileprivate func getPeerStoryState(peerId: PeerId) -> CodableEntry? {
|
||||
return self.storyStatesTable.get(key: .peer(peerId))
|
||||
fileprivate func getPeerStoryState(peerId: PeerId) -> StoredStoryPeerState? {
|
||||
return self.storyPeerStatesTable.get(key: .peer(peerId))
|
||||
}
|
||||
|
||||
fileprivate func setPeerStoryState(peerId: PeerId, state: CodableEntry?) {
|
||||
self.storyStatesTable.set(key: .peer(peerId), value: state, events: &self.currentStoryStatesEvents)
|
||||
fileprivate func setPeerStoryState(peerId: PeerId, state: StoredStoryPeerState?) {
|
||||
self.storyPeerStatesTable.set(key: .peer(peerId), value: state, events: &self.currentStoryPeerStatesEvents)
|
||||
}
|
||||
|
||||
fileprivate func setStoryItems(peerId: PeerId, items: [StoryItemsTableEntry]) {
|
||||
self.storyItemsTable.replace(peerId: peerId, entries: items, events: &self.currentStoryItemsEvents)
|
||||
self.storyItemsTable.replace(peerId: peerId, entries: items, topItemTable: self.storyTopItemsTable, events: &self.currentStoryItemsEvents, topItemEvents: &self.currentStoryTopItemEvents)
|
||||
for item in items {
|
||||
self.storyTable.set(id: StoryId(peerId: peerId, id: item.id), value: item.value, events: &self.currentStoryEvents)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func setStoryItemsInexactMaxId(peerId: PeerId, id: Int32) {
|
||||
if let value = self.storyTopItemsTable.get(peerId: peerId), value.id >= id {
|
||||
} else {
|
||||
self.storyTopItemsTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: id, isExact: false), events: &self.currentStoryTopItemEvents)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func getStoryItems(peerId: PeerId) -> [StoryItemsTableEntry] {
|
||||
return self.storyItemsTable.get(peerId: peerId)
|
||||
}
|
||||
@ -2311,7 +2333,7 @@ final class PostboxImpl {
|
||||
|
||||
let updatedPeerTimeoutAttributes = self.peerTimeoutPropertiesTable.hasUpdates
|
||||
|
||||
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), updatedPinnedThreads: self.currentUpdatedPinnedThreads, updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, storyStatesEvents: self.currentStoryStatesEvents, storySubscriptionsEvents: self.currentStorySubscriptionsEvents, storyItemsEvents: self.currentStoryItemsEvents, storyEvents: self.currentStoryEvents)
|
||||
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), updatedPinnedThreads: self.currentUpdatedPinnedThreads, updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, storyGeneralStatesEvents: self.currentStoryGeneralStatesEvents, storyPeerStatesEvents: self.currentStoryPeerStatesEvents, storySubscriptionsEvents: self.currentStorySubscriptionsEvents, storyItemsEvents: self.currentStoryItemsEvents, currentStoryTopItemEvents: self.currentStoryTopItemEvents, storyEvents: self.currentStoryEvents)
|
||||
var updatedTransactionState: Int64?
|
||||
var updatedMasterClientId: Int64?
|
||||
if !transaction.isEmpty {
|
||||
@ -2367,9 +2389,11 @@ final class PostboxImpl {
|
||||
self.currentUpdatedPinnedThreads.removeAll()
|
||||
self.currentUpdatedHiddenPeerIds = false
|
||||
self.currentNeedsReindexUnreadCounters = false
|
||||
self.currentStoryStatesEvents.removeAll()
|
||||
self.currentStoryGeneralStatesEvents.removeAll()
|
||||
self.currentStoryPeerStatesEvents.removeAll()
|
||||
self.currentStorySubscriptionsEvents.removeAll()
|
||||
self.currentStoryItemsEvents.removeAll()
|
||||
self.currentStoryTopItemEvents.removeAll()
|
||||
self.currentStoryEvents.removeAll()
|
||||
|
||||
for table in self.tables {
|
||||
|
@ -49,9 +49,11 @@ final class PostboxTransaction {
|
||||
let updatedPeerThreadsSummaries: Set<PeerId>
|
||||
let updatedPinnedThreads: Set<PeerId>
|
||||
let updatedHiddenPeerIds: Bool
|
||||
let storyStatesEvents: [StoryStatesTable.Event]
|
||||
let storyGeneralStatesEvents: [StoryGeneralStatesTable.Event]
|
||||
let storyPeerStatesEvents: [StoryPeerStatesTable.Event]
|
||||
let storySubscriptionsEvents: [StorySubscriptionsTable.Event]
|
||||
let storyItemsEvents: [StoryItemsTable.Event]
|
||||
let currentStoryTopItemEvents: [StoryTopItemsTable.Event]
|
||||
let storyEvents: [StoryTable.Event]
|
||||
|
||||
var isEmpty: Bool {
|
||||
@ -199,7 +201,10 @@ final class PostboxTransaction {
|
||||
if self.updatedHiddenPeerIds {
|
||||
return false
|
||||
}
|
||||
if !self.storyStatesEvents.isEmpty {
|
||||
if !self.storyGeneralStatesEvents.isEmpty {
|
||||
return false
|
||||
}
|
||||
if !self.storyPeerStatesEvents.isEmpty {
|
||||
return false
|
||||
}
|
||||
if !self.storySubscriptionsEvents.isEmpty {
|
||||
@ -208,13 +213,71 @@ final class PostboxTransaction {
|
||||
if !self.storyItemsEvents.isEmpty {
|
||||
return false
|
||||
}
|
||||
if !self.currentStoryTopItemEvents.isEmpty {
|
||||
return false
|
||||
}
|
||||
if !self.storyEvents.isEmpty {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>, currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState], currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [AdditionalChatListItem]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool, updatedPeerTimeoutAttributes: Bool, updatedMessageThreadPeerIds: Set<PeerId>, updatedPeerThreadCombinedStates: Set<PeerId>, updatedPeerThreadsSummaries: Set<PeerId>, updatedPinnedThreads: Set<PeerId>, updatedHiddenPeerIds: Bool, storyStatesEvents: [StoryStatesTable.Event], storySubscriptionsEvents: [StorySubscriptionsTable.Event], storyItemsEvents: [StoryItemsTable.Event], storyEvents: [StoryTable.Event]) {
|
||||
init(
|
||||
currentUpdatedState: PostboxCoding?,
|
||||
currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:],
|
||||
currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]],
|
||||
chatListOperations: [PeerGroupId: [ChatListOperation]],
|
||||
currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion],
|
||||
currentUpdatedPeers: [PeerId: Peer],
|
||||
currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?,
|
||||
PeerNotificationSettings)],
|
||||
currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp],
|
||||
currentUpdatedCachedPeerData: [PeerId: CachedPeerData],
|
||||
currentUpdatedPeerPresences: [PeerId: PeerPresence],
|
||||
currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>,
|
||||
currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState],
|
||||
currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary],
|
||||
alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState],
|
||||
currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation],
|
||||
currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation],
|
||||
unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation],
|
||||
updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?],
|
||||
currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool],
|
||||
currentPreferencesOperations: [PreferencesOperation],
|
||||
currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]],
|
||||
currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]],
|
||||
currentItemCollectionInfosOperations: [ItemCollectionInfosOperation],
|
||||
currentUpdatedPeerChatStates: Set<PeerId>,
|
||||
currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation],
|
||||
currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation],
|
||||
updatedMedia: [MediaId: Media?],
|
||||
replaceRemoteContactCount: Int32?,
|
||||
replaceContactPeerIds: Set<PeerId>?,
|
||||
currentPendingMessageActionsOperations: [PendingMessageActionsOperation],
|
||||
currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32],
|
||||
currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary],
|
||||
currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation],
|
||||
currentUpdatedPendingPeerNotificationSettings: Set<PeerId>,
|
||||
replacedAdditionalChatListItems: [AdditionalChatListItem]?,
|
||||
updatedNoticeEntryKeys: Set<NoticeEntryKey>,
|
||||
updatedCacheEntryKeys: Set<ItemCacheEntryId>,
|
||||
currentUpdatedMasterClientId: Int64?,
|
||||
updatedFailedMessagePeerIds: Set<PeerId>,
|
||||
updatedFailedMessageIds: Set<MessageId>,
|
||||
updatedGlobalNotificationSettings: Bool,
|
||||
updatedPeerTimeoutAttributes: Bool,
|
||||
updatedMessageThreadPeerIds: Set<PeerId>,
|
||||
updatedPeerThreadCombinedStates: Set<PeerId>,
|
||||
updatedPeerThreadsSummaries: Set<PeerId>,
|
||||
updatedPinnedThreads: Set<PeerId>,
|
||||
updatedHiddenPeerIds: Bool,
|
||||
storyGeneralStatesEvents: [StoryGeneralStatesTable.Event],
|
||||
storyPeerStatesEvents: [StoryPeerStatesTable.Event],
|
||||
storySubscriptionsEvents: [StorySubscriptionsTable.Event],
|
||||
storyItemsEvents: [StoryItemsTable.Event],
|
||||
currentStoryTopItemEvents: [StoryTopItemsTable.Event],
|
||||
storyEvents: [StoryTable.Event]
|
||||
) {
|
||||
self.currentUpdatedState = currentUpdatedState
|
||||
self.currentPeerHoleOperations = currentPeerHoleOperations
|
||||
self.currentOperationsByPeerId = currentOperationsByPeerId
|
||||
@ -262,9 +325,11 @@ final class PostboxTransaction {
|
||||
self.updatedPeerThreadsSummaries = updatedPeerThreadsSummaries
|
||||
self.updatedPinnedThreads = updatedPinnedThreads
|
||||
self.updatedHiddenPeerIds = updatedHiddenPeerIds
|
||||
self.storyStatesEvents = storyStatesEvents
|
||||
self.storyGeneralStatesEvents = storyGeneralStatesEvents
|
||||
self.storyPeerStatesEvents = storyPeerStatesEvents
|
||||
self.storySubscriptionsEvents = storySubscriptionsEvents
|
||||
self.storyItemsEvents = storyItemsEvents
|
||||
self.currentStoryTopItemEvents = currentStoryTopItemEvents
|
||||
self.storyEvents = storyEvents
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,75 @@ public final class StoryItemsTableEntry: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
final class StoryTopItemsTable: Table {
|
||||
struct Entry {
|
||||
var id: Int32
|
||||
var isExact: Bool
|
||||
}
|
||||
|
||||
enum Event {
|
||||
case replace(peerId: PeerId)
|
||||
}
|
||||
|
||||
private struct Key: Hashable {
|
||||
var peerId: PeerId
|
||||
}
|
||||
|
||||
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
||||
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
|
||||
}
|
||||
|
||||
private let sharedKey = ValueBoxKey(length: 8 + 4)
|
||||
|
||||
private func key(_ key: Key) -> ValueBoxKey {
|
||||
self.sharedKey.setInt64(0, value: key.peerId.toInt64())
|
||||
return self.sharedKey
|
||||
}
|
||||
|
||||
public func get(peerId: PeerId) -> Entry? {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(Key(peerId: peerId))) {
|
||||
let buffer = ReadBuffer(memoryBufferNoCopy: value)
|
||||
var version: UInt8 = 0
|
||||
buffer.read(&version, offset: 0, length: 1)
|
||||
if version != 100 {
|
||||
return nil
|
||||
}
|
||||
var maxId: Int32 = 0
|
||||
buffer.read(&maxId, offset: 0, length: 4)
|
||||
var isExact: Int8 = 0
|
||||
buffer.read(&isExact, offset: 0, length: 1)
|
||||
|
||||
return Entry(id: maxId, isExact: isExact != 0)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func set(peerId: PeerId, entry: Entry?, events: inout [Event]) {
|
||||
if let entry = entry {
|
||||
let buffer = WriteBuffer()
|
||||
|
||||
var version: UInt8 = 100
|
||||
buffer.write(&version, length: 1)
|
||||
var maxId = entry.id
|
||||
buffer.write(&maxId, length: 4)
|
||||
var isExact: Int8 = entry.isExact ? 1 : 0
|
||||
buffer.write(&isExact, length: 1)
|
||||
|
||||
self.valueBox.set(self.table, key: self.key(Key(peerId: peerId)), value: buffer.readBufferNoCopy())
|
||||
} else {
|
||||
self.valueBox.remove(self.table, key: self.key(Key(peerId: peerId)), secure: true)
|
||||
}
|
||||
}
|
||||
|
||||
override func clearMemoryCache() {
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final class StoryItemsTable: Table {
|
||||
enum Event {
|
||||
case replace(peerId: PeerId)
|
||||
@ -66,6 +135,24 @@ final class StoryItemsTable: Table {
|
||||
return key.successor
|
||||
}
|
||||
|
||||
public func getStats(peerId: PeerId, maxSeenId: Int32) -> (total: Int, unseen: Int) {
|
||||
var total = 0
|
||||
var unseen = 0
|
||||
|
||||
self.valueBox.range(self.table, start: self.lowerBound(peerId: peerId), end: self.upperBound(peerId: peerId), keys: { key in
|
||||
let id = key.getInt32(8)
|
||||
|
||||
total += 1
|
||||
if id > maxSeenId {
|
||||
unseen += 1
|
||||
}
|
||||
|
||||
return true
|
||||
}, limit: 10000)
|
||||
|
||||
return (total, unseen)
|
||||
}
|
||||
|
||||
public func get(peerId: PeerId) -> [StoryItemsTableEntry] {
|
||||
var result: [StoryItemsTableEntry] = []
|
||||
|
||||
@ -177,7 +264,7 @@ final class StoryItemsTable: Table {
|
||||
return minValue
|
||||
}
|
||||
|
||||
public func replace(peerId: PeerId, entries: [StoryItemsTableEntry], events: inout [Event]) {
|
||||
public func replace(peerId: PeerId, entries: [StoryItemsTableEntry], topItemTable: StoryTopItemsTable, events: inout [Event], topItemEvents: inout [StoryTopItemsTable.Event]) {
|
||||
var previousKeys: [ValueBoxKey] = []
|
||||
self.valueBox.range(self.table, start: self.lowerBound(peerId: peerId), end: self.upperBound(peerId: peerId), keys: { key in
|
||||
previousKeys.append(key)
|
||||
@ -208,6 +295,8 @@ final class StoryItemsTable: Table {
|
||||
}
|
||||
|
||||
events.append(.replace(peerId: peerId))
|
||||
|
||||
topItemTable.set(peerId: peerId, entry: StoryTopItemsTable.Entry(id: entries.last?.id ?? 0, isExact: true), events: &topItemEvents)
|
||||
}
|
||||
|
||||
override func clearMemoryCache() {
|
||||
|
@ -1,6 +1,50 @@
|
||||
import Foundation
|
||||
|
||||
final class StoryStatesTable: Table {
|
||||
public struct StoredStoryPeerState: Equatable {
|
||||
public var entry: CodableEntry
|
||||
public var maxSeenId: Int32
|
||||
|
||||
public init(entry: CodableEntry, maxSeenId: Int32) {
|
||||
self.entry = entry
|
||||
self.maxSeenId = maxSeenId
|
||||
}
|
||||
}
|
||||
|
||||
private extension StoredStoryPeerState {
|
||||
init?(buffer: MemoryBuffer) {
|
||||
let readBuffer = ReadBuffer(memoryBufferNoCopy: buffer)
|
||||
var version: UInt8 = 0
|
||||
readBuffer.read(&version, offset: 0, length: 1)
|
||||
if version != 100 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var entryLength: Int32 = 0
|
||||
readBuffer.read(&entryLength, offset: 0, length: 4)
|
||||
if entryLength < 0 || readBuffer.offset + Int(entryLength) > readBuffer.length {
|
||||
return nil
|
||||
}
|
||||
self.entry = CodableEntry(data: readBuffer.readData(length: Int(entryLength)))
|
||||
|
||||
var maxSeenId: Int32 = 0
|
||||
readBuffer.read(&maxSeenId, offset: 0, length: 4)
|
||||
self.maxSeenId = maxSeenId
|
||||
}
|
||||
|
||||
func serialize(buffer: WriteBuffer) {
|
||||
var version: UInt8 = 100
|
||||
buffer.write(&version, length: 1)
|
||||
|
||||
var entryLength: Int32 = Int32(self.entry.data.count)
|
||||
buffer.write(&entryLength, length: 4)
|
||||
buffer.write(self.entry.data)
|
||||
|
||||
var maxSeenId: Int32 = self.maxSeenId
|
||||
buffer.write(&maxSeenId, length: 4)
|
||||
}
|
||||
}
|
||||
|
||||
final class StoryGeneralStatesTable: Table {
|
||||
enum Event {
|
||||
case set(Key)
|
||||
}
|
||||
@ -8,7 +52,6 @@ final class StoryStatesTable: Table {
|
||||
enum Key: Hashable {
|
||||
case local
|
||||
case subscriptions(PostboxStorySubscriptionsKey)
|
||||
case peer(PeerId)
|
||||
|
||||
init?(key: ValueBoxKey) {
|
||||
switch key.getUInt8(0) {
|
||||
@ -22,11 +65,9 @@ final class StoryStatesTable: Table {
|
||||
return nil
|
||||
}
|
||||
self = .subscriptions(subscriptionsKey)
|
||||
case 2:
|
||||
self = .peer(PeerId(key.getInt64(1)))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .peer(PeerId(namespace: PeerId.Namespace._internalFromInt32Value(0), id: ._internalFromInt64Value(0)))
|
||||
self = .subscriptions(.hidden)
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,11 +82,6 @@ final class StoryStatesTable: Table {
|
||||
key.setUInt8(0, value: 1)
|
||||
key.setInt32(1, value: subscriptionsKey.rawValue)
|
||||
return key
|
||||
case let .peer(peerId):
|
||||
let key = ValueBoxKey(length: 1 + 8)
|
||||
key.setUInt8(0, value: 2)
|
||||
key.setInt64(1, value: peerId.toInt64())
|
||||
return key
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,8 +90,6 @@ final class StoryStatesTable: Table {
|
||||
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
|
||||
}
|
||||
|
||||
private let sharedKey = ValueBoxKey(length: 8 + 4)
|
||||
|
||||
func get(key: Key) -> CodableEntry? {
|
||||
return self.valueBox.get(self.table, key: key.asKey()).flatMap { CodableEntry(data: $0.makeData()) }
|
||||
}
|
||||
@ -75,3 +109,58 @@ final class StoryStatesTable: Table {
|
||||
override func beforeCommit() {
|
||||
}
|
||||
}
|
||||
|
||||
final class StoryPeerStatesTable: Table {
|
||||
enum Event {
|
||||
case set(Key)
|
||||
}
|
||||
|
||||
enum Key: Hashable {
|
||||
case peer(PeerId)
|
||||
|
||||
init?(key: ValueBoxKey) {
|
||||
switch key.getUInt8(0) {
|
||||
case 0:
|
||||
self = .peer(PeerId(key.getInt64(1)))
|
||||
default:
|
||||
assertionFailure()
|
||||
self = .peer(PeerId(namespace: PeerId.Namespace._internalFromInt32Value(0), id: ._internalFromInt64Value(0)))
|
||||
}
|
||||
}
|
||||
|
||||
func asKey() -> ValueBoxKey {
|
||||
switch self {
|
||||
case let .peer(peerId):
|
||||
let key = ValueBoxKey(length: 1 + 8)
|
||||
key.setUInt8(0, value: 2)
|
||||
key.setInt64(1, value: peerId.toInt64())
|
||||
return key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
||||
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
|
||||
}
|
||||
|
||||
func get(key: Key) -> StoredStoryPeerState? {
|
||||
return self.valueBox.get(self.table, key: key.asKey()).flatMap { StoredStoryPeerState(buffer: $0) }
|
||||
}
|
||||
|
||||
func set(key: Key, value: StoredStoryPeerState?, events: inout [Event]) {
|
||||
if let value = value {
|
||||
let buffer = WriteBuffer()
|
||||
value.serialize(buffer: buffer)
|
||||
self.valueBox.set(self.table, key: key.asKey(), value: buffer.readBufferNoCopy())
|
||||
} else {
|
||||
self.valueBox.remove(self.table, key: key.asKey(), secure: true)
|
||||
}
|
||||
events.append(.set(key))
|
||||
}
|
||||
|
||||
override func clearMemoryCache() {
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
}
|
||||
}
|
||||
|
@ -6,54 +6,60 @@ public enum PostboxStoryStatesKey: Hashable {
|
||||
case peer(PeerId)
|
||||
}
|
||||
|
||||
private extension PostboxStoryStatesKey {
|
||||
init(tableKey: StoryStatesTable.Key) {
|
||||
switch tableKey {
|
||||
case .local:
|
||||
self = .local
|
||||
case let .subscriptions(key):
|
||||
self = .subscriptions(key)
|
||||
case let .peer(peerId):
|
||||
self = .peer(peerId)
|
||||
}
|
||||
}
|
||||
|
||||
var tableKey: StoryStatesTable.Key {
|
||||
switch self {
|
||||
case .local:
|
||||
return .local
|
||||
case let .subscriptions(key):
|
||||
return .subscriptions(key)
|
||||
case let .peer(peerId):
|
||||
return .peer(peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class MutableStoryStatesView: MutablePostboxView {
|
||||
let key: PostboxStoryStatesKey
|
||||
var value: CodableEntry?
|
||||
|
||||
init(postbox: PostboxImpl, key: PostboxStoryStatesKey) {
|
||||
self.key = key
|
||||
self.value = postbox.storyStatesTable.get(key: key.tableKey)
|
||||
|
||||
let _ = self.refreshDueToExternalTransaction(postbox: postbox)
|
||||
}
|
||||
|
||||
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
|
||||
var updated = false
|
||||
if !transaction.storyStatesEvents.isEmpty {
|
||||
let tableKey = self.key.tableKey
|
||||
loop: for event in transaction.storyStatesEvents {
|
||||
switch event {
|
||||
case .set(tableKey):
|
||||
let value = postbox.storyStatesTable.get(key: self.key.tableKey)
|
||||
if value != self.value {
|
||||
self.value = value
|
||||
updated = true
|
||||
switch self.key {
|
||||
case .local, .subscriptions:
|
||||
let storyGeneralKey: StoryGeneralStatesTable.Key
|
||||
switch self.key {
|
||||
case .local:
|
||||
storyGeneralKey = .local
|
||||
case let .subscriptions(value):
|
||||
storyGeneralKey = .subscriptions(value)
|
||||
case .peer:
|
||||
assertionFailure()
|
||||
return false
|
||||
}
|
||||
if !transaction.storyGeneralStatesEvents.isEmpty {
|
||||
loop: for event in transaction.storyGeneralStatesEvents {
|
||||
switch event {
|
||||
case .set(storyGeneralKey):
|
||||
let value = postbox.storyGeneralStatesTable.get(key: storyGeneralKey)
|
||||
if value != self.value {
|
||||
self.value = value
|
||||
updated = true
|
||||
}
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .peer(peerId):
|
||||
let storyPeerKey: StoryPeerStatesTable.Key = .peer(peerId)
|
||||
if !transaction.storyPeerStatesEvents.isEmpty {
|
||||
loop: for event in transaction.storyPeerStatesEvents {
|
||||
switch event {
|
||||
case .set(storyPeerKey):
|
||||
let value = postbox.storyPeerStatesTable.get(key: storyPeerKey)?.entry
|
||||
if value != self.value {
|
||||
self.value = value
|
||||
updated = true
|
||||
}
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
break loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,7 +68,16 @@ final class MutableStoryStatesView: MutablePostboxView {
|
||||
}
|
||||
|
||||
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
|
||||
let value = postbox.storyStatesTable.get(key: self.key.tableKey)
|
||||
let value: CodableEntry?
|
||||
switch self.key {
|
||||
case .local:
|
||||
value = postbox.storyGeneralStatesTable.get(key: .local)
|
||||
case let .subscriptions(valueKey):
|
||||
value = postbox.storyGeneralStatesTable.get(key: .subscriptions(valueKey))
|
||||
case let .peer(peerId):
|
||||
value = postbox.storyPeerStatesTable.get(key: .peer(peerId))?.entry
|
||||
}
|
||||
|
||||
if value != self.value {
|
||||
self.value = value
|
||||
return true
|
||||
|
@ -1534,9 +1534,9 @@ public final class ShareController: ViewController {
|
||||
var peers: [EngineRenderedPeer] = []
|
||||
for entry in view.0.entries.reversed() {
|
||||
switch entry {
|
||||
case let .MessageEntry(_, _, _, _, _, renderedPeer, _, _, _, _, _, _, _):
|
||||
if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) {
|
||||
peers.append(EngineRenderedPeer(renderedPeer))
|
||||
case let .MessageEntry(entryData):
|
||||
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) {
|
||||
peers.append(EngineRenderedPeer(entryData.renderedPeer))
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
@ -1363,7 +1363,8 @@ private func threadList(context: AccountContext, peerId: EnginePeer.Id) -> Signa
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
isContact: false,
|
||||
autoremoveTimeout: nil
|
||||
autoremoveTimeout: nil,
|
||||
storyStats: nil
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -727,7 +727,7 @@ public func groupStatsController(context: AccountContext, updatedPresentationDat
|
||||
|
||||
actionsDisposable.add(context.account.viewTracker.peerView(peerId, updateData: true).start())
|
||||
|
||||
let statsContext = GroupStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, peerId: peerId)
|
||||
let statsContext = GroupStatsContext(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, datacenterId: datacenterId, peerId: peerId)
|
||||
let dataSignal: Signal<GroupStats?, NoError> = statsContext.state
|
||||
|> map { state in
|
||||
return state.stats
|
||||
|
@ -1002,7 +1002,7 @@ public class Account {
|
||||
self.hiddenStorySubscriptionsContext = nil
|
||||
}
|
||||
|
||||
self.callSessionManager = CallSessionManager(postbox: postbox, network: network, maxLayer: networkArguments.voipMaxLayer, versions: networkArguments.voipVersions, addUpdates: { [weak self] updates in
|
||||
self.callSessionManager = CallSessionManager(postbox: postbox, network: network, accountPeerId: peerId, maxLayer: networkArguments.voipMaxLayer, versions: networkArguments.voipVersions, addUpdates: { [weak self] updates in
|
||||
self?.stateManager?.addUpdates(updates)
|
||||
})
|
||||
|
||||
|
@ -240,7 +240,7 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title:
|
||||
}
|
||||
|> castError(CreateForumChannelTopicError.self)
|
||||
|> mapToSignal { _ -> Signal<Int64, CreateForumChannelTopicError> in
|
||||
return resolveForumThreads(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, network: account.network, ids: [MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))])
|
||||
|> castError(CreateForumChannelTopicError.self)
|
||||
|> map { _ -> Int64 in
|
||||
return topicId
|
||||
@ -265,7 +265,7 @@ func _internal_fetchForumChannelTopic(account: Account, peerId: PeerId, threadId
|
||||
if let info = info {
|
||||
return .single(info)
|
||||
} else {
|
||||
return resolveForumThreads(postbox: account.postbox, network: account.network, ids: [MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))])
|
||||
return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, ids: [MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))])
|
||||
|> mapToSignal { _ -> Signal<EngineMessageHistoryThread.Info?, NoError> in
|
||||
return account.postbox.transaction { transaction -> EngineMessageHistoryThread.Info? in
|
||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
@ -706,23 +706,8 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
||||
|
||||
func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: Transaction, results: [LoadMessageHistoryThreadsResult]) {
|
||||
for result in results {
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in result.chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in result.users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: result.chats, users: result.users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let _ = InternalAccountState.addMessages(transaction: transaction, messages: result.messages, location: .Random)
|
||||
|
||||
|
@ -3,7 +3,7 @@ import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
public func actualizedPeer(postbox: Postbox, network: Network, peer: Peer) -> Signal<Peer, NoError> {
|
||||
public func actualizedPeer(accountPeerId: PeerId, postbox: Postbox, network: Network, peer: Peer) -> Signal<Peer, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Peer, NoError> in
|
||||
var signal: Signal<Peer, NoError>
|
||||
var actualizeChannel: Api.InputChannel?
|
||||
@ -30,31 +30,30 @@ public func actualizedPeer(postbox: Postbox, network: Network, peer: Peer) -> Si
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Peer, NoError> in
|
||||
var remotePeer: Peer?
|
||||
if let result = result {
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
return postbox.transaction { transaction -> Signal<Peer, NoError> in
|
||||
var parsedPeers: AccumulatedPeers?
|
||||
if let result = result {
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
case let .chats(apiChats):
|
||||
chats = apiChats
|
||||
case let .chatsSlice(_, apiChats):
|
||||
chats = apiChats
|
||||
}
|
||||
for chat in chats {
|
||||
if let parsedPeer = parseTelegramGroupOrChannel(chat: chat), parsedPeer.id == peer.id {
|
||||
remotePeer = parsedPeer
|
||||
}
|
||||
let parsedPeersValue = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
if parsedPeersValue.allIds.contains(peer.id) {
|
||||
parsedPeers = parsedPeersValue
|
||||
}
|
||||
}
|
||||
}
|
||||
if let remotePeer = remotePeer {
|
||||
return postbox.transaction { transaction -> Peer in
|
||||
updatePeers(transaction: transaction, peers: [remotePeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return remotePeer
|
||||
if let parsedPeers = parsedPeers {
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
if let peer = transaction.getPeer(peer.id) {
|
||||
return .single(peer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
signal = signal |> then(remote)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import SwiftSignalKit
|
||||
|
||||
|
||||
public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: MessageId) -> Signal<Peer?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<Peer?, NoError> in
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let user = peer as? TelegramUser {
|
||||
@ -34,27 +35,21 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
|
||||
if let result = result {
|
||||
let apiUsers: [Api.User]
|
||||
switch result {
|
||||
case let .messages(_, _, users):
|
||||
apiUsers = users
|
||||
case let .messagesSlice(_, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
case let .channelMessages(_, _, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
case .messagesNotModified:
|
||||
apiUsers = []
|
||||
case let .messages(_, _, users):
|
||||
apiUsers = users
|
||||
case let .messagesSlice(_, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
case let .channelMessages(_, _, _, _, _, _, _, users):
|
||||
apiUsers = users
|
||||
case .messagesNotModified:
|
||||
apiUsers = []
|
||||
}
|
||||
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
if telegramUser.id == peerId, let accessHash = telegramUser.accessHash, accessHash.value != 0 {
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: [telegramUser.id: user])
|
||||
|
||||
updatePeers(transaction: transaction, peers: [telegramUser], update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
return telegramUser
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
return peer
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -421,7 +421,7 @@ final class MediaReferenceRevalidationContext {
|
||||
}
|
||||
}
|
||||
|
||||
func message(postbox: Postbox, network: Network, background: Bool, message: MessageReference) -> Signal<Message, RevalidateMediaReferenceError> {
|
||||
func message(accountPeerId: PeerId, postbox: Postbox, network: Network, background: Bool, message: MessageReference) -> Signal<Message, RevalidateMediaReferenceError> {
|
||||
return self.genericItem(key: .message(message: message), background: background, request: { next, error in
|
||||
let source: Signal<FetchMessageHistoryHoleSource, NoError>
|
||||
if background {
|
||||
@ -432,7 +432,7 @@ final class MediaReferenceRevalidationContext {
|
||||
}
|
||||
let signal = source
|
||||
|> mapToSignal { source -> Signal<Message?, NoError> in
|
||||
return fetchRemoteMessage(postbox: postbox, source: source, message: message)
|
||||
return fetchRemoteMessage(accountPeerId: accountPeerId, postbox: postbox, source: source, message: message)
|
||||
}
|
||||
return signal.start(next: { value in
|
||||
if let value = value {
|
||||
@ -544,9 +544,9 @@ final class MediaReferenceRevalidationContext {
|
||||
}
|
||||
}
|
||||
|
||||
func peer(postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<Peer, RevalidateMediaReferenceError> {
|
||||
func peer(accountPeerId: PeerId, postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<Peer, RevalidateMediaReferenceError> {
|
||||
return self.genericItem(key: .peer(peer: peer), background: background, request: { next, error in
|
||||
return (_internal_updatedRemotePeer(postbox: postbox, network: network, peer: peer)
|
||||
return (_internal_updatedRemotePeer(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer)
|
||||
|> mapError { _ -> RevalidateMediaReferenceError in
|
||||
return .generic
|
||||
}).start(next: { value in
|
||||
@ -640,9 +640,9 @@ final class MediaReferenceRevalidationContext {
|
||||
}
|
||||
}
|
||||
|
||||
func attachBot(postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<AttachMenuBot, RevalidateMediaReferenceError> {
|
||||
func attachBot(accountPeerId: PeerId, postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<AttachMenuBot, RevalidateMediaReferenceError> {
|
||||
return self.genericItem(key: .attachBot(peer: peer), background: background, request: { next, error in
|
||||
return (_internal_getAttachMenuBot(postbox: postbox, network: network, botId: peer.id, cached: false)
|
||||
return (_internal_getAttachMenuBot(accountPeerId: accountPeerId, postbox: postbox, network: network, botId: peer.id, cached: false)
|
||||
|> mapError { _ -> RevalidateMediaReferenceError in
|
||||
return .generic
|
||||
}).start(next: { value in
|
||||
@ -751,7 +751,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n
|
||||
case let .media(media, _):
|
||||
switch media {
|
||||
case let .message(message, previousMedia):
|
||||
return revalidationContext.message(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
return revalidationContext.message(accountPeerId: accountPeerId, postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
|> mapToSignal { message -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for media in message.media {
|
||||
if let updatedResource = findUpdatedMediaResource(media: media, previousMedia: previousMedia, resource: resource) {
|
||||
@ -822,7 +822,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n
|
||||
return .fail(.generic)
|
||||
}
|
||||
case let .attachBot(peer, _):
|
||||
return revalidationContext.attachBot(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|
||||
return revalidationContext.attachBot(accountPeerId: accountPeerId, postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|
||||
|> mapToSignal { attachBot -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for (_, icon) in attachBot.icons {
|
||||
if let updatedResource = findUpdatedMediaResource(media: icon, previousMedia: nil, resource: resource) {
|
||||
@ -896,7 +896,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n
|
||||
}
|
||||
}
|
||||
case let .avatar(peer, _):
|
||||
return revalidationContext.peer(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|
||||
return revalidationContext.peer(accountPeerId: accountPeerId, postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|
||||
|> mapToSignal { updatedPeer -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for representation in updatedPeer.profileImageRepresentations {
|
||||
if let updatedResource = representation.resource as? CloudPeerPhotoSizeMediaResource, let previousResource = resource as? CloudPeerPhotoSizeMediaResource {
|
||||
@ -921,7 +921,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n
|
||||
return .fail(.generic)
|
||||
}
|
||||
case let .messageAuthorAvatar(message, _):
|
||||
return revalidationContext.message(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
return revalidationContext.message(accountPeerId: accountPeerId, postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
|> mapToSignal { updatedMessage -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
guard let author = updatedMessage.author, let authorReference = PeerReference(author) else {
|
||||
return .fail(.generic)
|
||||
|
@ -666,7 +666,7 @@ public struct GroupStatsContextState: Equatable {
|
||||
public var stats: GroupStats?
|
||||
}
|
||||
|
||||
private func requestGroupStats(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId, dark: Bool = false) -> Signal<GroupStats?, NoError> {
|
||||
private func requestGroupStats(accountPeerId: PeerId, postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId, dark: Bool = false) -> Signal<GroupStats?, NoError> {
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
} |> mapToSignal { peer -> Signal<GroupStats?, NoError> in
|
||||
@ -694,13 +694,7 @@ private func requestGroupStats(postbox: Postbox, network: Network, datacenterId:
|
||||
|> mapToSignal { result -> Signal<GroupStats?, MTRpcError> in
|
||||
return postbox.transaction { transaction -> GroupStats? in
|
||||
if case let .megagroupStats(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, users) = result {
|
||||
var parsedUsers: [Peer] = []
|
||||
for user in users {
|
||||
parsedUsers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: parsedUsers, update: { existing, updated in
|
||||
return existing ?? updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
}
|
||||
return GroupStats(apiMegagroupStats: result)
|
||||
}
|
||||
@ -713,6 +707,7 @@ private func requestGroupStats(postbox: Postbox, network: Network, datacenterId:
|
||||
private final class GroupStatsContextImpl {
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let accountPeerId: PeerId
|
||||
private let datacenterId: Int32
|
||||
private let peerId: PeerId
|
||||
|
||||
@ -731,11 +726,12 @@ private final class GroupStatsContextImpl {
|
||||
private let disposable = MetaDisposable()
|
||||
private let disposables = DisposableDict<String>()
|
||||
|
||||
init(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId) {
|
||||
init(postbox: Postbox, network: Network, accountPeerId: PeerId, datacenterId: Int32, peerId: PeerId) {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.accountPeerId = accountPeerId
|
||||
self.datacenterId = datacenterId
|
||||
self.peerId = peerId
|
||||
self._state = GroupStatsContextState(stats: nil)
|
||||
@ -753,7 +749,7 @@ private final class GroupStatsContextImpl {
|
||||
private func load() {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
|
||||
self.disposable.set((requestGroupStats(postbox: self.postbox, network: self.network, datacenterId: self.datacenterId, peerId: self.peerId)
|
||||
self.disposable.set((requestGroupStats(accountPeerId: self.accountPeerId, postbox: self.postbox, network: self.network, datacenterId: self.datacenterId, peerId: self.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] stats in
|
||||
if let strongSelf = self {
|
||||
strongSelf._state = GroupStatsContextState(stats: stats)
|
||||
@ -906,9 +902,9 @@ public final class GroupStatsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public init(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId) {
|
||||
public init(postbox: Postbox, network: Network, accountPeerId: PeerId, datacenterId: Int32, peerId: PeerId) {
|
||||
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
|
||||
return GroupStatsContextImpl(postbox: postbox, network: network, datacenterId: datacenterId, peerId: peerId)
|
||||
return GroupStatsContextImpl(postbox: postbox, network: network, accountPeerId: accountPeerId, datacenterId: datacenterId, peerId: peerId)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -204,18 +204,8 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
|
||||
for update in updates {
|
||||
switch update {
|
||||
case .updateEditMessage(let message, _, _), .updateNewMessage(let message, _, _), .updateEditChannelMessage(let message, _, _), .updateNewChannelMessage(let message, _, _):
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
|
||||
let peers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
|
||||
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), case let .Id(id) = message.id {
|
||||
transaction.updateMessage(id, update: { previousMessage in
|
||||
|
@ -14,7 +14,7 @@ func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(transaction: T
|
||||
let updatedPeer = peer.withUpdatedMessageAutoremoveTimeout(timeout)
|
||||
let updatedState = state.withUpdatedMessageAutoremoveTimeout(timeout)
|
||||
if !updatedPeer.isEqual(peer) {
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { $1 })
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { $1 })
|
||||
}
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
|
@ -58,7 +58,7 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
|
||||
updatedState = secretChatAddReportCurrentLayerSupportOperationAndUpdateRequestedLayer(transaction: transaction, peerId: currentPeer.id, state: updatedState)
|
||||
|
||||
transaction.setPeerChatState(currentPeer.id, state: updatedState)
|
||||
updatePeers(transaction: transaction, peers: [currentPeer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [currentPeer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
} else {
|
||||
@ -73,7 +73,7 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
|
||||
|
||||
let state = currentState.withUpdatedEmbeddedState(.terminated)
|
||||
let peer = currentPeer.withUpdatedEmbeddedState(state.embeddedState.peerState)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
transaction.setPeerChatState(peer.id, state: state)
|
||||
transaction.operationLogRemoveAllEntries(peerId: peer.id, tag: OperationLogTags.SecretOutgoing)
|
||||
|
||||
@ -101,7 +101,7 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
|
||||
transaction.setPeerChatState(chat.peerId, state: updatedState)
|
||||
|
||||
let peer = TelegramSecretChat(id: chat.peerId, creationDate: date, regularPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), accessHash: accessHash, role: updatedState.role, embeddedState: updatedState.embeddedState.peerState, messageAutoremoveTimeout: nil)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
if folderId != nil {
|
||||
transaction.updatePeerChatListInclusion(peer.id, inclusion: .ifHasMessagesOrOneOf(groupId: Namespaces.PeerGroup.archive, pinningIndex: nil, minTimestamp: date))
|
||||
}
|
||||
@ -126,7 +126,7 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee
|
||||
if let requestData = requestData, currentPeer == nil && adminId == accountPeerId.id._internalGetInt64Value() {
|
||||
let state = SecretChatState(role: .creator, embeddedState: .handshake(.requested(g: requestData.g, p: requestData.p, a: requestData.a)), keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil)
|
||||
let peer = TelegramSecretChat(id: chat.peerId, creationDate: date, regularPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(participantId)), accessHash: accessHash, role: state.role, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: nil)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in return updated })
|
||||
transaction.setPeerChatState(peer.id, state: state)
|
||||
transaction.resetIncomingReadStates([peer.id: [
|
||||
Namespaces.Message.SecretIncoming: .indexBased(maxIncomingReadIndex: MessageIndex.lowerBound(peerId: peer.id), maxOutgoingReadIndex: MessageIndex.lowerBound(peerId: peer.id), count: 0, markedUnread: false),
|
||||
|
@ -1872,7 +1872,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab
|
||||
}
|
||||
}
|
||||
|
||||
func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -> Signal<Void, NoError> {
|
||||
func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, ids: [MessageId]) -> Signal<Void, NoError> {
|
||||
let forumThreadIds = Set(ids)
|
||||
|
||||
if forumThreadIds.isEmpty {
|
||||
@ -1965,20 +1965,8 @@ func resolveForumThreads(postbox: Postbox, network: Network, ids: [MessageId]) -
|
||||
}
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let _ = transaction.addMessages(storeMessages, location: .Random)
|
||||
}
|
||||
@ -1994,7 +1982,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
|
||||
for message in fetchedChatList.storeMessages {
|
||||
if let threadId = message.threadId {
|
||||
if let channel = fetchedChatList.peers.first(where: { $0.id == message.id.peerId }) 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) {
|
||||
forumThreadIds.insert(MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: Int32(clamping: threadId)))
|
||||
}
|
||||
}
|
||||
@ -2017,7 +2005,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
} else {
|
||||
var signals: [Signal<(Peer, Api.messages.ForumTopics)?, NoError>] = []
|
||||
for (peerId, threadIds) in missingForumThreadIds {
|
||||
guard let peer = fetchedChatList.peers.first(where: { $0.id == peerId }), let inputChannel = apiInputChannel(peer) else {
|
||||
guard let peer = fetchedChatList.peers.get(peerId), let inputChannel = apiInputChannel(peer) else {
|
||||
Logger.shared.log("resolveForumThreads", "can't fetch thread infos \(threadIds) for peer \(peerId): can't create inputChannel")
|
||||
continue
|
||||
}
|
||||
@ -2042,12 +2030,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, _):
|
||||
fetchedChatList.peers.append(contentsOf: chats.compactMap { chat in
|
||||
return parseTelegramGroupOrChannel(chat: chat)
|
||||
})
|
||||
fetchedChatList.peers.append(contentsOf: users.compactMap { user in
|
||||
return TelegramUser(user: user)
|
||||
})
|
||||
fetchedChatList.peers = fetchedChatList.peers.union(with: AccumulatedPeers(chats: chats, users: users))
|
||||
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
@ -2098,7 +2081,7 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
||||
}
|
||||
}
|
||||
|
||||
func resolveStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, storyIds: Set<StoryId>, additionalPeers: [PeerId: Peer], result: T) -> Signal<T, NoError> {
|
||||
func resolveStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, storyIds: Set<StoryId>, additionalPeers: AccumulatedPeers, result: T) -> Signal<T, NoError> {
|
||||
var storyBuckets: [PeerId: [Int32]] = [:]
|
||||
for id in storyIds {
|
||||
if storyBuckets[id.peerId] == nil {
|
||||
@ -2113,7 +2096,7 @@ func resolveStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource,
|
||||
while idOffset < allIds.count {
|
||||
let bucketLength = min(100, allIds.count - idOffset)
|
||||
let ids = Array(allIds[idOffset ..< (idOffset + bucketLength)])
|
||||
signals.append(_internal_getStoriesById(accountPeerId: accountPeerId, postbox: postbox, source: source, peerId: peerId, peerReference: additionalPeers[peerId].flatMap(PeerReference.init), ids: ids)
|
||||
signals.append(_internal_getStoriesById(accountPeerId: accountPeerId, postbox: postbox, source: source, peerId: peerId, peerReference: additionalPeers.get(peerId).flatMap(PeerReference.init), ids: ids)
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
for id in ids {
|
||||
@ -2168,7 +2151,7 @@ func resolveAssociatedStories(postbox: Postbox, network: Network, accountPeerId:
|
||||
}
|
||||
|
||||
if !missingStoryIds.isEmpty {
|
||||
return resolveStories(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, storyIds: missingStoryIds, additionalPeers: state.insertedPeers, result: state)
|
||||
return resolveStories(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, storyIds: missingStoryIds, additionalPeers: AccumulatedPeers(peers: Array(state.insertedPeers.values)), result: state)
|
||||
} else {
|
||||
return .single(state)
|
||||
}
|
||||
@ -2176,7 +2159,7 @@ func resolveAssociatedStories(postbox: Postbox, network: Network, accountPeerId:
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func resolveAssociatedStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, messages: [StoreMessage], additionalPeers: [PeerId: Peer], result: T) -> Signal<T, NoError> {
|
||||
func resolveAssociatedStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, messages: [StoreMessage], additionalPeers: AccumulatedPeers, result: T) -> Signal<T, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||
var missingStoryIds = Set<StoryId>()
|
||||
|
||||
@ -4041,32 +4024,17 @@ func replayFinalState(
|
||||
transaction.globalNotificationSettingsUpdated()
|
||||
}
|
||||
case let .MergeApiChats(chats):
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
case let .MergeApiUsers(users):
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
}
|
||||
|
||||
if let updatedAccountPeer = peers.first(where: { $0.id == accountPeerId }) as? TelegramUser, let previousAccountPeer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
if let updatedAccountPeer = parsedPeers.get(accountPeerId) as? TelegramUser, let previousAccountPeer = transaction.getPeer(accountPeerId) as? TelegramUser {
|
||||
if updatedAccountPeer.isPremium != previousAccountPeer.isPremium {
|
||||
isPremiumUpdated = true
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
updateContacts(transaction: transaction, apiUsers: users)
|
||||
case let .UpdatePeer(id, f):
|
||||
if let peer = f(transaction.getPeer(id)) {
|
||||
@ -4076,7 +4044,7 @@ func replayFinalState(
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -4530,7 +4498,7 @@ func replayFinalState(
|
||||
}
|
||||
|
||||
var appliedMaxReadId: Int32?
|
||||
if let currentState = transaction.getPeerStoryState(peerId: peerId)?.get(Stories.PeerState.self) {
|
||||
if let currentState = transaction.getPeerStoryState(peerId: peerId)?.entry.get(Stories.PeerState.self) {
|
||||
if let appliedMaxReadIdValue = appliedMaxReadId {
|
||||
appliedMaxReadId = max(appliedMaxReadIdValue, currentState.maxReadId)
|
||||
} else {
|
||||
@ -4539,9 +4507,9 @@ func replayFinalState(
|
||||
}
|
||||
|
||||
transaction.setStoryItems(peerId: peerId, items: updatedPeerEntries)
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: appliedMaxReadId ?? 0
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
|
||||
if let parsedItem = Stories.StoredItem(apiStoryItem: story, peerId: peerId, transaction: transaction) {
|
||||
storyUpdates.append(InternalStoryUpdate.added(peerId: peerId, item: parsedItem))
|
||||
@ -4550,13 +4518,13 @@ func replayFinalState(
|
||||
}
|
||||
case let .UpdateReadStories(peerId, maxId):
|
||||
var appliedMaxReadId = maxId
|
||||
if let currentState = transaction.getPeerStoryState(peerId: peerId)?.get(Stories.PeerState.self) {
|
||||
if let currentState = transaction.getPeerStoryState(peerId: peerId)?.entry.get(Stories.PeerState.self) {
|
||||
appliedMaxReadId = max(appliedMaxReadId, currentState.maxReadId)
|
||||
}
|
||||
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: appliedMaxReadId
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
|
||||
storyUpdates.append(InternalStoryUpdate.read(peerId: peerId, maxId: maxId))
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ final class AccountTaskManager {
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .emoji).start())
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .status).start())
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .avatar).start())
|
||||
tasks.add(managedSynchronizeAttachMenuBots(postbox: self.stateManager.postbox, network: self.stateManager.network, force: true).start())
|
||||
tasks.add(managedSynchronizeAttachMenuBots(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network, force: true).start())
|
||||
tasks.add(managedSynchronizeNotificationSoundList(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedChatListFilters(postbox: self.stateManager.postbox, network: self.stateManager.network, accountPeerId: self.stateManager.accountPeerId).start())
|
||||
tasks.add(managedAnimatedEmojiUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
@ -112,12 +112,12 @@ final class AccountTaskManager {
|
||||
|
||||
//tasks.add(managedVoipConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedAppConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedPremiumPromoConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedPremiumPromoConfigurationUpdates(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedAutodownloadSettingsUpdates(accountManager: self.accountManager, network: self.stateManager.network).start())
|
||||
tasks.add(managedTermsOfServiceUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
|
||||
tasks.add(managedAppUpdateInfo(network: self.stateManager.network, stateManager: self.stateManager).start())
|
||||
tasks.add(managedAppChangelog(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager, appVersion: self.networkArguments.appVersion).start())
|
||||
tasks.add(managedPromoInfoUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network, viewTracker: self.viewTracker).start())
|
||||
tasks.add(managedPromoInfoUpdates(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network, viewTracker: self.viewTracker).start())
|
||||
tasks.add(managedLocalizationUpdatesOperations(accountManager: self.accountManager, postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedPendingPeerNotificationSettings(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedSynchronizeAppLogEventsOperations(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
|
@ -62,6 +62,7 @@ private func pollMessages(entries: [MessageHistoryEntry]) -> (Set<MessageId>, [M
|
||||
}
|
||||
|
||||
private func fetchWebpage(account: Account, messageId: MessageId) -> Signal<Void, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.loadedPeerWithId(messageId.peerId)
|
||||
|> take(1)
|
||||
|> mapToSignal { peer in
|
||||
@ -105,19 +106,7 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal<Void
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for apiUser in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(apiUser.peerId) as? TelegramUser, rhs: apiUser) {
|
||||
peers.append(user)
|
||||
peerPresences[user.id] = apiUser
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum, namespace: isScheduledMessage ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) {
|
||||
@ -145,11 +134,7 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal<Void
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -688,6 +673,7 @@ public final class AccountViewTracker {
|
||||
self.nextUpdatedViewCountDisposableId += 1
|
||||
|
||||
if let account = self.account {
|
||||
let accountPeerId = account.peerId
|
||||
let signal: Signal<[MessageId: ViewCountContextState], NoError> = (account.postbox.transaction { transaction -> Signal<[MessageId: ViewCountContextState], NoError> in
|
||||
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
||||
return .complete()
|
||||
@ -703,28 +689,11 @@ public final class AccountViewTracker {
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> [MessageId: ViewCountContextState] in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
var resultStates: [MessageId: ViewCountContextState] = [:]
|
||||
|
||||
for apiUser in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(apiUser.peerId) as? TelegramUser, rhs: apiUser) {
|
||||
peers.append(user)
|
||||
peerPresences[user.id] = apiUser
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
for i in 0 ..< messageIds.count {
|
||||
if i < viewCounts.count {
|
||||
@ -1046,6 +1015,7 @@ public final class AccountViewTracker {
|
||||
self.nextUpdatedUnsupportedMediaDisposableId += 1
|
||||
|
||||
if let account = self.account {
|
||||
let accountPeerId = account.peerId
|
||||
let signal = account.postbox.transaction { transaction -> Peer? in
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
return peer
|
||||
@ -1091,26 +1061,8 @@ public final class AccountViewTracker {
|
||||
}
|
||||
|> mapToSignal { topPeer, messages, chats, users -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for apiUser in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(apiUser.peerId) as? TelegramUser, rhs: apiUser) {
|
||||
peers.append(user)
|
||||
peerPresences[user.id] = apiUser
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
for message in messages {
|
||||
guard let storeMessage = StoreMessage(apiMessage: message, peerIsForum: topPeer.isForum) else {
|
||||
|
@ -363,6 +363,7 @@ private final class CallSessionManagerContext {
|
||||
private let queue: Queue
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let accountPeerId: PeerId
|
||||
private let maxLayer: Int32
|
||||
private var versions: [CallSessionManagerImplementationVersion]
|
||||
private let addUpdates: (Api.Updates) -> Void
|
||||
@ -376,10 +377,11 @@ private final class CallSessionManagerContext {
|
||||
|
||||
private let disposables = DisposableSet()
|
||||
|
||||
init(queue: Queue, postbox: Postbox, network: Network, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
init(queue: Queue, postbox: Postbox, network: Network, accountPeerId: PeerId, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
self.queue = queue
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.accountPeerId = accountPeerId
|
||||
self.maxLayer = maxLayer
|
||||
self.versions = versions.reversed()
|
||||
self.addUpdates = addUpdates
|
||||
@ -706,7 +708,7 @@ private final class CallSessionManagerContext {
|
||||
switch context.state {
|
||||
case let .ringing(id, accessHash, gAHash, b, _):
|
||||
let acceptVersions = self.versions.map({ $0.version })
|
||||
context.state = .accepting(id: id, accessHash: accessHash, gAHash: gAHash, b: b, disposable: (acceptCallSession(postbox: self.postbox, network: self.network, stableId: id, accessHash: accessHash, b: b, maxLayer: self.maxLayer, versions: acceptVersions) |> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
context.state = .accepting(id: id, accessHash: accessHash, gAHash: gAHash, b: b, disposable: (acceptCallSession(accountPeerId: self.accountPeerId, postbox: self.postbox, network: self.network, stableId: id, accessHash: accessHash, b: b, maxLayer: self.maxLayer, versions: acceptVersions) |> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
if case .accepting = context.state {
|
||||
switch result {
|
||||
@ -1056,9 +1058,9 @@ public final class CallSessionManager {
|
||||
private let queue = Queue()
|
||||
private var contextRef: Unmanaged<CallSessionManagerContext>?
|
||||
|
||||
init(postbox: Postbox, network: Network, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
init(postbox: Postbox, network: Network, accountPeerId: PeerId, maxLayer: Int32, versions: [CallSessionManagerImplementationVersion], addUpdates: @escaping (Api.Updates) -> Void) {
|
||||
self.queue.async {
|
||||
let context = CallSessionManagerContext(queue: self.queue, postbox: postbox, network: network, maxLayer: maxLayer, versions: versions, addUpdates: addUpdates)
|
||||
let context = CallSessionManagerContext(queue: self.queue, postbox: postbox, network: network, accountPeerId: accountPeerId, maxLayer: maxLayer, versions: versions, addUpdates: addUpdates)
|
||||
self.contextRef = Unmanaged.passRetained(context)
|
||||
}
|
||||
}
|
||||
@ -1193,7 +1195,7 @@ private enum AcceptCallResult {
|
||||
case success(AcceptedCall)
|
||||
}
|
||||
|
||||
private func acceptCallSession(postbox: Postbox, network: Network, stableId: CallSessionStableId, accessHash: Int64, b: Data, maxLayer: Int32, versions: [String]) -> Signal<AcceptCallResult, NoError> {
|
||||
private func acceptCallSession(accountPeerId: PeerId, postbox: Postbox, network: Network, stableId: CallSessionStableId, accessHash: Int64, b: Data, maxLayer: Int32, versions: [String]) -> Signal<AcceptCallResult, NoError> {
|
||||
return validatedEncryptionConfig(postbox: postbox, network: network)
|
||||
|> mapToSignal { config -> Signal<AcceptCallResult, NoError> in
|
||||
var gValue: Int32 = config.g.byteSwapped
|
||||
@ -1218,13 +1220,7 @@ private func acceptCallSession(postbox: Postbox, network: Network, stableId: Cal
|
||||
return postbox.transaction { transaction -> AcceptCallResult in
|
||||
switch call {
|
||||
case let .phoneCall(phoneCall, users):
|
||||
var parsedUsers: [Peer] = []
|
||||
for user in users {
|
||||
parsedUsers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: parsedUsers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
switch phoneCall {
|
||||
case .phoneCallEmpty, .phoneCallRequested, .phoneCallAccepted, .phoneCallDiscarded:
|
||||
|
@ -354,21 +354,6 @@ final class ChatHistoryPreloadManager {
|
||||
return disposable
|
||||
}
|
||||
|
||||
/*let signal = self.postbox.tailChatListView(groupId: .root, count: 20, summaryComponents: ChatListEntrySummaryComponents())
|
||||
|> map { view -> [ChatHistoryPreloadItem] in
|
||||
var result: [ChatHistoryPreloadItem] = []
|
||||
for entry in view.0.entries {
|
||||
if case let .MessageEntry(index, _, readState, isMuted, _, _, _, _, _, _) = entry {
|
||||
var hasUnread = false
|
||||
if let readState = readState {
|
||||
hasUnread = readState.count != 0
|
||||
}
|
||||
result.append(ChatHistoryPreloadItem(index: index, isMuted: isMuted, hasUnread: hasUnread))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}*/
|
||||
|
||||
self.automaticChatListDisposable.set((combineLatest(queue: .mainQueue(), self.preloadItemsSignal, additionalPeerIds)
|
||||
|> delay(1.0, queue: .mainQueue())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] loadItems, additionalPeerIds in
|
||||
|
@ -192,7 +192,7 @@ private final class ContactSyncManagerImpl {
|
||||
case let .sync(importableContacts):
|
||||
let importSignal: Signal<PushDeviceContactsResult, NoError>
|
||||
if let importableContacts = importableContacts {
|
||||
importSignal = pushDeviceContacts(postbox: self.postbox, network: self.network, importableContacts: importableContacts, reimportAttempts: self.reimportAttempts)
|
||||
importSignal = pushDeviceContacts(accountPeerId: self.accountPeerId, postbox: self.postbox, network: self.network, importableContacts: importableContacts, reimportAttempts: self.reimportAttempts)
|
||||
} else {
|
||||
importSignal = .single(PushDeviceContactsResult(addedReimportAttempts: [:]))
|
||||
}
|
||||
@ -235,7 +235,7 @@ private struct PushDeviceContactsResult {
|
||||
let addedReimportAttempts: [TelegramDeviceContactImportIdentifier: Double]
|
||||
}
|
||||
|
||||
private func pushDeviceContacts(postbox: Postbox, network: Network, importableContacts: [DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData], reimportAttempts: [TelegramDeviceContactImportIdentifier: Double]) -> Signal<PushDeviceContactsResult, NoError> {
|
||||
private func pushDeviceContacts(accountPeerId: PeerId, postbox: Postbox, network: Network, importableContacts: [DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData], reimportAttempts: [TelegramDeviceContactImportIdentifier: Double]) -> Signal<PushDeviceContactsResult, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<PushDeviceContactsResult, NoError> in
|
||||
var noLongerImportedIdentifiers = Set<TelegramDeviceContactImportIdentifier>()
|
||||
var updatedDataIdentifiers = Set<TelegramDeviceContactImportIdentifier>()
|
||||
@ -312,14 +312,14 @@ private func pushDeviceContacts(postbox: Postbox, network: Network, importableCo
|
||||
}
|
||||
}
|
||||
|
||||
return pushDeviceContactData(postbox: postbox, network: network, contacts: preparedContactData)
|
||||
return pushDeviceContactData(accountPeerId: accountPeerId, postbox: postbox, network: network, contacts: preparedContactData)
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
private let importBatchCount: Int = 500
|
||||
|
||||
private func pushDeviceContactData(postbox: Postbox, network: Network, contacts: [(DeviceContactNormalizedPhoneNumber, ImportableDeviceContactData)]) -> Signal<PushDeviceContactsResult, NoError> {
|
||||
private func pushDeviceContactData(accountPeerId: PeerId, postbox: Postbox, network: Network, contacts: [(DeviceContactNormalizedPhoneNumber, ImportableDeviceContactData)]) -> Signal<PushDeviceContactsResult, NoError> {
|
||||
var batches: Signal<PushDeviceContactsResult, NoError> = .single(PushDeviceContactsResult(addedReimportAttempts: [:]))
|
||||
for s in stride(from: 0, to: contacts.count, by: importBatchCount) {
|
||||
let batch = Array(contacts[s ..< min(s + importBatchCount, contacts.count)])
|
||||
@ -342,10 +342,8 @@ private func pushDeviceContactData(postbox: Postbox, network: Network, contacts:
|
||||
var peerIdByClientId: [Int64: PeerId] = [:]
|
||||
switch result {
|
||||
case let .importedContacts(imported, popularInvites, retryContacts, users):
|
||||
let peers = users.map { TelegramUser(user: $0) as Peer }
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
for item in imported {
|
||||
switch item {
|
||||
case let .importedContact(userId, clientId):
|
||||
|
@ -12,8 +12,7 @@ enum FetchChatListLocation {
|
||||
|
||||
struct ParsedDialogs {
|
||||
let itemIds: [PeerId]
|
||||
let peers: [Peer]
|
||||
let peerPresences: [PeerId: Api.User]
|
||||
let peers: AccumulatedPeers
|
||||
|
||||
let notificationSettings: [PeerId: PeerNotificationSettings]
|
||||
let readStates: [PeerId: [MessageId.Namespace: PeerReadState]]
|
||||
@ -62,18 +61,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
var referencedFolders: [PeerGroupId: PeerGroupUnreadCountersSummary] = [:]
|
||||
var itemIds: [PeerId] = []
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in apiChats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers[telegramUser.id] = telegramUser
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let peers = AccumulatedPeers(chats: apiChats, users: apiUsers)
|
||||
|
||||
for dialog in apiDialogs {
|
||||
let apiPeer: Api.Peer
|
||||
@ -88,7 +76,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
let apiNotificationSettings: Api.PeerNotifySettings
|
||||
switch dialog {
|
||||
case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, peerNotificationSettings, pts, _, _, ttlPeriod):
|
||||
if let peer = peers[peer.peerId] {
|
||||
if let peer = peers.get(peer.peerId) {
|
||||
var isExluded = false
|
||||
if let group = peer as? TelegramGroup {
|
||||
if group.flags.contains(.deactivated) {
|
||||
@ -154,7 +142,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
|
||||
for message in apiMessages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = peers[peerId], peer.isForum {
|
||||
if let peerId = message.peerId, let peer = peers.get(peerId), peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
@ -179,9 +167,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
|
||||
return ParsedDialogs(
|
||||
itemIds: itemIds,
|
||||
peers: Array(peers.values),
|
||||
peerPresences: peerPresences,
|
||||
|
||||
peers: peers,
|
||||
notificationSettings: notificationSettings,
|
||||
readStates: readStates,
|
||||
mentionTagSummaries: mentionTagSummaries,
|
||||
@ -198,8 +184,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
|
||||
struct FetchedChatList {
|
||||
var chatPeerIds: [PeerId]
|
||||
var peers: [Peer]
|
||||
var peerPresences: [PeerId: Api.User]
|
||||
var peers: AccumulatedPeers
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings]
|
||||
var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout]
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]]
|
||||
@ -306,8 +291,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
|
||||
return combineLatest(folderSignals)
|
||||
|> mapToSignal { folders -> Signal<FetchedChatList?, NoError> in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
var peers = AccumulatedPeers()
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] = [:]
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
@ -317,8 +301,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var topMessageIds: [PeerId: MessageId] = [:]
|
||||
|
||||
peers.append(contentsOf: parsedRemoteChats.peers)
|
||||
peerPresences.merge(parsedRemoteChats.peerPresences, uniquingKeysWith: { _, updated in updated })
|
||||
peers = peers.union(with: parsedRemoteChats.peers)
|
||||
notificationSettings.merge(parsedRemoteChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
ttlPeriods.merge(parsedRemoteChats.ttlPeriods, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(parsedRemoteChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
@ -329,8 +312,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
topMessageIds.merge(parsedRemoteChats.topMessageIds, uniquingKeysWith: { _, updated in updated })
|
||||
|
||||
if let parsedPinnedChats = parsedPinnedChats {
|
||||
peers.append(contentsOf: parsedPinnedChats.peers)
|
||||
peerPresences.merge(parsedPinnedChats.peerPresences, uniquingKeysWith: { _, updated in updated })
|
||||
peers = peers.union(with: parsedPinnedChats.peers)
|
||||
notificationSettings.merge(parsedPinnedChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
ttlPeriods.merge(parsedPinnedChats.ttlPeriods, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(parsedPinnedChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
@ -353,8 +335,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
for peerId in folderChats.itemIds {
|
||||
peerGroupIds[peerId] = groupId
|
||||
}
|
||||
peers.append(contentsOf: folderChats.peers)
|
||||
peerPresences.merge(folderChats.peerPresences, uniquingKeysWith: { _, updated in updated })
|
||||
peers = peers.union(with: folderChats.peers)
|
||||
notificationSettings.merge(folderChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
ttlPeriods.merge(folderChats.ttlPeriods, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(folderChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
@ -389,7 +370,6 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
let result: FetchedChatList? = FetchedChatList(
|
||||
chatPeerIds: parsedRemoteChats.itemIds + (pinnedItemIds ?? []),
|
||||
peers: peers,
|
||||
peerPresences: peerPresences,
|
||||
notificationSettings: notificationSettings,
|
||||
ttlPeriods: ttlPeriods,
|
||||
readStates: readStates,
|
||||
|
@ -4,6 +4,81 @@ import SwiftSignalKit
|
||||
import TelegramApi
|
||||
import MtProtoKit
|
||||
|
||||
struct AccumulatedPeers {
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var users: [PeerId: Api.User] = [:]
|
||||
|
||||
var allIds: Set<PeerId> {
|
||||
var result = Set<PeerId>()
|
||||
for (id, _) in self.peers {
|
||||
result.insert(id)
|
||||
}
|
||||
for (id, _) in self.users {
|
||||
result.insert(id)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
init() {
|
||||
}
|
||||
|
||||
init(transaction: Transaction, chats: [Api.Chat], users: [Api.User]) {
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
self.peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
self.users[user.peerId] = user
|
||||
}
|
||||
}
|
||||
|
||||
init(chats: [Api.Chat], users: [Api.User]) {
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
self.peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
self.users[user.peerId] = user
|
||||
}
|
||||
}
|
||||
|
||||
init(users: [Api.User]) {
|
||||
for user in users {
|
||||
self.users[user.peerId] = user
|
||||
}
|
||||
}
|
||||
|
||||
init(peers: [Peer]) {
|
||||
for peer in peers {
|
||||
self.peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
|
||||
func union(with other: AccumulatedPeers) -> AccumulatedPeers {
|
||||
var result = self
|
||||
|
||||
for (id, peer) in other.peers {
|
||||
result.peers[id] = peer
|
||||
}
|
||||
for (id, user) in other.users {
|
||||
result.users[id] = user
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func get(_ id: PeerId) -> Peer? {
|
||||
if let peer = self.peers[id] {
|
||||
return peer
|
||||
} else if let user = self.users[id] {
|
||||
return TelegramUser(user: user)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func messageFilterForTagMask(_ tagMask: MessageTags) -> Api.MessagesFilter? {
|
||||
if tagMask == .photoOrVideo {
|
||||
@ -100,7 +175,7 @@ func resolveUnknownEmojiFiles<T>(postbox: Postbox, source: FetchMessageHistoryHo
|
||||
}
|
||||
}
|
||||
|
||||
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
|
||||
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, parsedPeers: AccumulatedPeers, storeMessages: [StoreMessage], _ f: @escaping (Transaction, AccumulatedPeers, [StoreMessage]) -> T) -> Signal<T, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||
var storedIds = Set<MessageId>()
|
||||
var referencedReplyIds = ReferencedReplyMessageIds()
|
||||
@ -129,17 +204,17 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
if referencedReplyIds.isEmpty && referencedGeneralIds.isEmpty {
|
||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: peers, result: Void())
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: parsedPeers, result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return postbox.transaction { transaction -> T in
|
||||
return f(transaction, [], [])
|
||||
return f(transaction, parsedPeers, [])
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var signals: [Signal<(Peer, [Api.Message], [Api.Chat], [Api.User]), NoError>] = []
|
||||
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedReplyIds) {
|
||||
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
||||
if let peer = transaction.getPeer(peerId) ?? parsedPeers.get(peerId) {
|
||||
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
signal = source.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
|
||||
@ -170,7 +245,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
}
|
||||
}
|
||||
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedGeneralIds) {
|
||||
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
|
||||
if let peer = transaction.getPeer(peerId) ?? parsedPeers.get(peerId) {
|
||||
var signal: Signal<Api.messages.Messages, MTRpcError>?
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
signal = source.request(Api.functions.messages.getMessages(id: messageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
|
||||
@ -205,42 +280,32 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
||||
|
||||
return fetchMessages
|
||||
|> mapToSignal { results -> Signal<T, NoError> in
|
||||
var additionalPeers: [Peer] = []
|
||||
var additionalMessages: [StoreMessage] = []
|
||||
for (peer, messages, chats, users) in results {
|
||||
if !messages.isEmpty {
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
|
||||
additionalMessages.append(message)
|
||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||
var additionalPeers = AccumulatedPeers()
|
||||
|
||||
var additionalMessages: [StoreMessage] = []
|
||||
for (peer, messages, chats, users) in results {
|
||||
if !messages.isEmpty {
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
|
||||
additionalMessages.append(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
additionalPeers = additionalPeers.union(with: AccumulatedPeers(transaction: transaction, chats: chats, users: users))
|
||||
}
|
||||
|
||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, reactions: [], result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: parsedPeers.union(with: additionalPeers), result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return postbox.transaction { transaction -> T in
|
||||
return f(transaction, additionalPeers, additionalMessages)
|
||||
}
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
additionalPeers.append(peer)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
additionalPeers.append(TelegramUser(user: user))
|
||||
}
|
||||
}
|
||||
|
||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, reactions: [], result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
var additionalPeerMap: [PeerId: Peer] = [:]
|
||||
for (_, peer) in peers {
|
||||
additionalPeerMap[peer.id] = peer
|
||||
}
|
||||
for peer in additionalPeers {
|
||||
additionalPeerMap[peer.id] = peer
|
||||
}
|
||||
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: additionalPeerMap, result: Void())
|
||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||
return postbox.transaction { transaction -> T in
|
||||
return f(transaction, additionalPeers, additionalMessages)
|
||||
}
|
||||
}
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,7 +681,9 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
}
|
||||
return true
|
||||
}, delayIncrement: 0.1, maxDelay: 2.0, maxRetries: 0, onQueue: .concurrentDefaultQueue())
|
||||
|> map(Optional.init)
|
||||
|> map { result -> Api.messages.Messages? in
|
||||
return result
|
||||
}
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
@ -624,160 +691,149 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
||||
guard let result = result else {
|
||||
return .single(nil)
|
||||
}
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
var channelPts: Int32?
|
||||
switch result {
|
||||
case let .messages(messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .channelMessages(_, pts, _, _, apiMessages, apiTopics, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
let _ = apiTopics
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
channelPts = pts
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
chats = []
|
||||
users = []
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
return postbox.transaction { transaction -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
var channelPts: Int32?
|
||||
switch result {
|
||||
case let .messages(messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .messagesSlice(_, _, _, _, messages: apiMessages, chats: apiChats, users: apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
case let .channelMessages(_, pts, _, _, apiMessages, apiTopics, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
let _ = apiTopics
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
channelPts = pts
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
chats = []
|
||||
users = []
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum, namespace: namespace) {
|
||||
if let channelPts = channelPts {
|
||||
var attributes = storeMessage.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
storeMessages.append(storeMessage.withUpdatedAttributes(attributes))
|
||||
} else {
|
||||
storeMessages.append(storeMessage)
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
var storeMessages: [StoreMessage] = []
|
||||
|
||||
for message in messages {
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum, namespace: namespace) {
|
||||
if let channelPts = channelPts {
|
||||
var attributes = storeMessage.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
storeMessages.append(storeMessage.withUpdatedAttributes(attributes))
|
||||
} else {
|
||||
storeMessages.append(storeMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: source, accountPeerId: accountPeerId, peers: Dictionary(peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: storeMessages, { transaction, additionalPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
||||
let _ = transaction.addMessages(storeMessages, location: .Random)
|
||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||
var filledRange: ClosedRange<MessageId.Id>
|
||||
var strictFilledIndices: IndexSet
|
||||
let ids = storeMessages.compactMap { message -> MessageId.Id? in
|
||||
switch message.id {
|
||||
case let .Id(id):
|
||||
switch space {
|
||||
case let .tag(tag):
|
||||
if !message.tags.contains(tag) {
|
||||
return nil
|
||||
} else {
|
||||
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: source, accountPeerId: accountPeerId, parsedPeers: parsedPeers, storeMessages: storeMessages, { transaction, additionalParsedPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
||||
let _ = transaction.addMessages(storeMessages, location: .Random)
|
||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||
var filledRange: ClosedRange<MessageId.Id>
|
||||
var strictFilledIndices: IndexSet
|
||||
let ids = storeMessages.compactMap { message -> MessageId.Id? in
|
||||
switch message.id {
|
||||
case let .Id(id):
|
||||
switch space {
|
||||
case let .tag(tag):
|
||||
if !message.tags.contains(tag) {
|
||||
return nil
|
||||
} else {
|
||||
return id.id
|
||||
}
|
||||
case .everywhere:
|
||||
return id.id
|
||||
}
|
||||
case .everywhere:
|
||||
return id.id
|
||||
case .Partial:
|
||||
return nil
|
||||
}
|
||||
case .Partial:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
let fullIds = storeMessages.compactMap { message -> MessageId? in
|
||||
switch message.id {
|
||||
case let .Id(id):
|
||||
switch space {
|
||||
case let .tag(tag):
|
||||
if !message.tags.contains(tag) {
|
||||
return nil
|
||||
} else {
|
||||
let fullIds = storeMessages.compactMap { message -> MessageId? in
|
||||
switch message.id {
|
||||
case let .Id(id):
|
||||
switch space {
|
||||
case let .tag(tag):
|
||||
if !message.tags.contains(tag) {
|
||||
return nil
|
||||
} else {
|
||||
return id
|
||||
}
|
||||
case .everywhere:
|
||||
return id
|
||||
}
|
||||
case .everywhere:
|
||||
return id
|
||||
case .Partial:
|
||||
return nil
|
||||
}
|
||||
case .Partial:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
||||
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
if ids.count == 0 || implicitelyFillHole {
|
||||
filledRange = minMaxRange
|
||||
strictFilledIndices = IndexSet()
|
||||
} else {
|
||||
let messageRange = ids.min()! ... ids.max()!
|
||||
switch direction {
|
||||
case let .aroundId(aroundId):
|
||||
filledRange = min(aroundId.id, messageRange.lowerBound) ... max(aroundId.id, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(aroundId.id, messageRange.lowerBound)) ... Int(max(aroundId.id, messageRange.upperBound)))
|
||||
if peerInput.requestThreadId != nil {
|
||||
if ids.count <= count / 2 - 1 {
|
||||
filledRange = minMaxRange
|
||||
|
||||
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
||||
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
if ids.count == 0 || implicitelyFillHole {
|
||||
filledRange = minMaxRange
|
||||
strictFilledIndices = IndexSet()
|
||||
} else {
|
||||
let messageRange = ids.min()! ... ids.max()!
|
||||
switch direction {
|
||||
case let .aroundId(aroundId):
|
||||
filledRange = min(aroundId.id, messageRange.lowerBound) ... max(aroundId.id, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(aroundId.id, messageRange.lowerBound)) ... Int(max(aroundId.id, messageRange.upperBound)))
|
||||
if peerInput.requestThreadId != nil {
|
||||
if ids.count <= count / 2 - 1 {
|
||||
filledRange = minMaxRange
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
let minBound = start.id
|
||||
let maxBound = messageRange.upperBound
|
||||
filledRange = min(minBound, maxBound) ... max(minBound, maxBound)
|
||||
|
||||
var maxStrictIndex = max(minBound, maxBound)
|
||||
maxStrictIndex = min(maxStrictIndex, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(minBound, maxBound)) ... Int(maxStrictIndex))
|
||||
} else {
|
||||
let minBound = messageRange.lowerBound
|
||||
let maxBound = start.id
|
||||
filledRange = min(minBound, maxBound) ... max(minBound, maxBound)
|
||||
|
||||
var maxStrictIndex = max(minBound, maxBound)
|
||||
maxStrictIndex = min(maxStrictIndex, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(minBound, maxBound)) ... Int(maxStrictIndex))
|
||||
}
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
let minBound = start.id
|
||||
let maxBound = messageRange.upperBound
|
||||
filledRange = min(minBound, maxBound) ... max(minBound, maxBound)
|
||||
|
||||
var maxStrictIndex = max(minBound, maxBound)
|
||||
maxStrictIndex = min(maxStrictIndex, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(minBound, maxBound)) ... Int(maxStrictIndex))
|
||||
} else {
|
||||
let minBound = messageRange.lowerBound
|
||||
let maxBound = start.id
|
||||
filledRange = min(minBound, maxBound) ... max(minBound, maxBound)
|
||||
|
||||
var maxStrictIndex = max(minBound, maxBound)
|
||||
maxStrictIndex = min(maxStrictIndex, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(minBound, maxBound)) ... Int(maxStrictIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch peerInput {
|
||||
case let .direct(peerId, threadId):
|
||||
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: namespace, space: space, range: filledRange)
|
||||
case .threadFromChannel:
|
||||
break
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers + additionalPeers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
|
||||
|
||||
switch peerInput {
|
||||
case let .direct(peerId, threadId):
|
||||
transaction.removeHole(peerId: peerId, threadId: threadId, namespace: namespace, space: space, range: filledRange)
|
||||
case .threadFromChannel:
|
||||
break
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers.union(with: additionalParsedPeers))
|
||||
|
||||
let result = FetchMessageHistoryHoleResult(
|
||||
removedIndices: IndexSet(integersIn: Int(filledRange.lowerBound) ... Int(filledRange.upperBound)),
|
||||
strictRemovedIndices: strictFilledIndices,
|
||||
actualPeerId: storeMessages.first?.id.peerId,
|
||||
actualThreadId: storeMessages.first?.threadId,
|
||||
ids: fullIds
|
||||
)
|
||||
return result
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
let result = FetchMessageHistoryHoleResult(
|
||||
removedIndices: IndexSet(integersIn: Int(filledRange.lowerBound) ... Int(filledRange.upperBound)),
|
||||
strictRemovedIndices: strictFilledIndices,
|
||||
actualPeerId: storeMessages.first?.id.peerId,
|
||||
actualThreadId: storeMessages.first?.threadId,
|
||||
ids: fullIds
|
||||
)
|
||||
return result
|
||||
})
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -812,10 +868,8 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||
updatePeers(transaction: transaction, peers: fetchedChats.peers + additionalPeers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: fetchedChats.peers.union(with: additionalPeers))
|
||||
|
||||
for (threadMessageId, data) in fetchedChats.threadInfos {
|
||||
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||
@ -825,7 +879,6 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: data.unreadReactionCount, maxId: data.topMessageId)
|
||||
}
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: fetchedChats.peerPresences)
|
||||
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
||||
let _ = transaction.addMessages(fetchedChats.storeMessages, location: .UpperHistoryBlock)
|
||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||
@ -927,27 +980,11 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var topIndex: MessageIndex?
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
var peerMap: [PeerId: Peer] = [:]
|
||||
for peer in peers {
|
||||
peerMap[peer.id] = peer
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for message in messages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = peerMap[peerId], peer.isForum {
|
||||
if let peerId = message.peerId, let peer = parsedPeers.get(peerId), peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
@ -965,10 +1002,7 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
||||
|
||||
transaction.replaceGlobalMessageTagsHole(globalTags: [.Calls, .MissedCalls], index: holeIndex, with: updatedIndex, messages: storeMessages)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
return searchResult
|
||||
|
@ -87,7 +87,7 @@ func managedPeerTimestampAttributeOperations(network: Network, postbox: Postbox)
|
||||
|> then(postbox.transaction { transaction -> Void in
|
||||
if let peer = transaction.getPeer(entry.peerId) {
|
||||
if let user = peer as? TelegramUser {
|
||||
updatePeers(transaction: transaction, peers: [user.withUpdatedEmojiStatus(nil)], update: { _, updated in updated })
|
||||
updatePeersCustom(transaction: transaction, peers: [user.withUpdatedEmojiStatus(nil)], update: { _, updated in updated })
|
||||
}
|
||||
}
|
||||
//failsafe
|
||||
|
@ -5,10 +5,10 @@ import TelegramApi
|
||||
import MtProtoKit
|
||||
|
||||
public func updatePremiumPromoConfigurationOnce(account: Account) -> Signal<Void, NoError> {
|
||||
return updatePremiumPromoConfigurationOnce(postbox: account.postbox, network: account.network)
|
||||
return updatePremiumPromoConfigurationOnce(accountPeerId: account.peerId, postbox: account.postbox, network: account.network)
|
||||
}
|
||||
|
||||
func updatePremiumPromoConfigurationOnce(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
func updatePremiumPromoConfigurationOnce(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
return network.request(Api.functions.help.getPremiumPromo())
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.help.PremiumPromo?, NoError> in
|
||||
@ -20,14 +20,8 @@ func updatePremiumPromoConfigurationOnce(postbox: Postbox, network: Network) ->
|
||||
}
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if case let .premiumPromo(_, _, _, _, _, apiUsers) = result {
|
||||
let users = apiUsers.map { TelegramUser(user: $0) }
|
||||
updatePeers(transaction: transaction, peers: users, update: { current, updated -> Peer in
|
||||
if let updated = updated as? TelegramUser {
|
||||
return TelegramUser.merge(lhs: current as? TelegramUser, rhs: updated)
|
||||
} else {
|
||||
return updated
|
||||
}
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
|
||||
updatePremiumPromoConfiguration(transaction: transaction, { configuration -> PremiumPromoConfiguration in
|
||||
@ -37,9 +31,9 @@ func updatePremiumPromoConfigurationOnce(postbox: Postbox, network: Network) ->
|
||||
}
|
||||
}
|
||||
|
||||
func managedPremiumPromoConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
func managedPremiumPromoConfigurationUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let poll = Signal<Void, NoError> { subscriber in
|
||||
return updatePremiumPromoConfigurationOnce(postbox: postbox, network: network).start(completed: {
|
||||
return updatePremiumPromoConfigurationOnce(accountPeerId: accountPeerId, postbox: postbox, network: network).start(completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public final class PromoChatListItem: AdditionalChatListItem {
|
||||
}
|
||||
}
|
||||
|
||||
func managedPromoInfoUpdates(postbox: Postbox, network: Network, viewTracker: AccountViewTracker) -> Signal<Void, NoError> {
|
||||
func managedPromoInfoUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network, viewTracker: AccountViewTracker) -> Signal<Void, NoError> {
|
||||
return Signal { subscriber in
|
||||
let queue = Queue()
|
||||
let update = network.contextProxyId
|
||||
@ -89,24 +89,9 @@ func managedPromoInfoUpdates(postbox: Postbox, network: Network, viewTracker: Ac
|
||||
case .promoDataEmpty:
|
||||
transaction.replaceAdditionalChatListItems([])
|
||||
case let .promoData(_, _, peer, chats, users, psaType, psaMessage):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let kind: PromoChatListItem.Kind
|
||||
if let psaType = psaType {
|
||||
|
@ -192,7 +192,7 @@ private func initialHandshakeAccept(postbox: Postbox, network: Network, peerId:
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.terminated)
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -266,7 +266,7 @@ private func initialHandshakeAccept(postbox: Postbox, network: Network, peerId:
|
||||
}
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
@ -11,5 +11,7 @@ func managedServiceViews(accountPeerId: PeerId, network: Network, postbox: Postb
|
||||
disposable.add(managedChatListHoles(network: network, postbox: postbox, accountPeerId: accountPeerId).start())
|
||||
disposable.add(managedForumTopicListHoles(network: network, postbox: postbox, accountPeerId: accountPeerId).start())
|
||||
|
||||
disposable.add((_internal_refreshSeenStories(postbox: postbox, network: network) |> then(.complete() |> suspendAwareDelay(5 * 60 * 60, queue: .mainQueue())) |> restart).start())
|
||||
|
||||
return (managedHoles.0, disposable)
|
||||
}
|
||||
|
@ -128,169 +128,153 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
return network.request(Api.functions.messages.getPinnedDialogs(folderId: groupId.rawValue))
|
||||
|> retryRequest
|
||||
|> mapToSignal { dialogs -> Signal<Void, NoError> in
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] = [:]
|
||||
|
||||
var remoteItemIds: [PinnedItemId] = []
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
switch dialogs {
|
||||
case let .peerDialogs(dialogs, messages, chats, users, _):
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] = [:]
|
||||
|
||||
var peerMap: [PeerId: Peer] = [:]
|
||||
for peer in peers {
|
||||
peerMap[peer.id] = peer
|
||||
var remoteItemIds: [PinnedItemId] = []
|
||||
|
||||
let parsedPeers: AccumulatedPeers
|
||||
|
||||
switch dialogs {
|
||||
case let .peerDialogs(dialogs, messages, chats, users, _):
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
loop: for dialog in dialogs {
|
||||
let apiPeer: Api.Peer
|
||||
let apiReadInboxMaxId: Int32
|
||||
let apiReadOutboxMaxId: Int32
|
||||
let apiTopMessage: Int32
|
||||
let apiUnreadCount: Int32
|
||||
let apiMarkedUnread: Bool
|
||||
var apiChannelPts: Int32?
|
||||
let apiTtlPeriod: Int32?
|
||||
let apiNotificationSettings: Api.PeerNotifySettings
|
||||
switch dialog {
|
||||
case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _, peerNotificationSettings, pts, _, _, ttlPeriod):
|
||||
apiPeer = peer
|
||||
apiTopMessage = topMessage
|
||||
apiReadInboxMaxId = readInboxMaxId
|
||||
apiReadOutboxMaxId = readOutboxMaxId
|
||||
apiUnreadCount = unreadCount
|
||||
apiMarkedUnread = (flags & (1 << 3)) != 0
|
||||
apiNotificationSettings = peerNotificationSettings
|
||||
apiChannelPts = pts
|
||||
apiTtlPeriod = ttlPeriod
|
||||
case .dialogFolder:
|
||||
//assertionFailure()
|
||||
continue loop
|
||||
}
|
||||
|
||||
loop: for dialog in dialogs {
|
||||
let apiPeer: Api.Peer
|
||||
let apiReadInboxMaxId: Int32
|
||||
let apiReadOutboxMaxId: Int32
|
||||
let apiTopMessage: Int32
|
||||
let apiUnreadCount: Int32
|
||||
let apiMarkedUnread: Bool
|
||||
var apiChannelPts: Int32?
|
||||
let apiTtlPeriod: Int32?
|
||||
let apiNotificationSettings: Api.PeerNotifySettings
|
||||
switch dialog {
|
||||
case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _, peerNotificationSettings, pts, _, _, ttlPeriod):
|
||||
apiPeer = peer
|
||||
apiTopMessage = topMessage
|
||||
apiReadInboxMaxId = readInboxMaxId
|
||||
apiReadOutboxMaxId = readOutboxMaxId
|
||||
apiUnreadCount = unreadCount
|
||||
apiMarkedUnread = (flags & (1 << 3)) != 0
|
||||
apiNotificationSettings = peerNotificationSettings
|
||||
apiChannelPts = pts
|
||||
apiTtlPeriod = ttlPeriod
|
||||
case .dialogFolder:
|
||||
//assertionFailure()
|
||||
continue loop
|
||||
}
|
||||
|
||||
let peerId: PeerId = apiPeer.peerId
|
||||
|
||||
remoteItemIds.append(.peer(peerId))
|
||||
|
||||
if readStates[peerId] == nil {
|
||||
readStates[peerId] = [:]
|
||||
}
|
||||
readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount, markedUnread: apiMarkedUnread)
|
||||
|
||||
if let apiChannelPts = apiChannelPts {
|
||||
channelStates[peerId] = apiChannelPts
|
||||
}
|
||||
|
||||
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
|
||||
|
||||
ttlPeriods[peerId] = .known(apiTtlPeriod.flatMap(CachedPeerAutoremoveTimeout.Value.init(peerValue:)))
|
||||
let peerId: PeerId = apiPeer.peerId
|
||||
|
||||
remoteItemIds.append(.peer(peerId))
|
||||
|
||||
if readStates[peerId] == nil {
|
||||
readStates[peerId] = [:]
|
||||
}
|
||||
readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount, markedUnread: apiMarkedUnread)
|
||||
|
||||
if let apiChannelPts = apiChannelPts {
|
||||
channelStates[peerId] = apiChannelPts
|
||||
}
|
||||
|
||||
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
|
||||
|
||||
ttlPeriods[peerId] = .known(apiTtlPeriod.flatMap(CachedPeerAutoremoveTimeout.Value.init(peerValue:)))
|
||||
}
|
||||
|
||||
for message in messages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = peerMap[peerId], peer.isForum {
|
||||
if let peerId = message.peerId, let peer = parsedPeers.get(peerId), peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
storeMessages.append(storeMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var resultingItemIds: [PinnedItemId]
|
||||
if initialRemoteItemIds == localItemIds {
|
||||
resultingItemIds = remoteItemIds
|
||||
} else {
|
||||
let locallyRemovedFromRemoteItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(localItemIdsWithoutSecretChats))
|
||||
let remotelyRemovedItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(remoteItemIds))
|
||||
|
||||
resultingItemIds = localItemIds.filter { !remotelyRemovedItemIds.contains($0) }
|
||||
resultingItemIds.append(contentsOf: remoteItemIds.filter { !locallyRemovedFromRemoteItemIds.contains($0) && !resultingItemIds.contains($0) })
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
transaction.setPinnedItemIds(groupId: groupId, itemIds: resultingItemIds)
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
transaction.updateCurrentPeerNotificationSettings(notificationSettings)
|
||||
|
||||
for (peerId, autoremoveValue) in ttlPeriods {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
let current = (current as? CachedUserData) ?? CachedUserData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let current = (current as? CachedChannelData) ?? CachedChannelData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
let current = (current as? CachedGroupData) ?? CachedGroupData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var allPeersWithMessages = Set<PeerId>()
|
||||
for message in storeMessages {
|
||||
if !allPeersWithMessages.contains(message.id.peerId) {
|
||||
allPeersWithMessages.insert(message.id.peerId)
|
||||
}
|
||||
}
|
||||
let _ = transaction.addMessages(storeMessages, location: .UpperHistoryBlock)
|
||||
|
||||
transaction.resetIncomingReadStates(readStates)
|
||||
|
||||
for (peerId, pts) in channelStates {
|
||||
if let _ = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
// skip changing state
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
if remoteItemIds == resultingItemIds {
|
||||
return .complete()
|
||||
var resultingItemIds: [PinnedItemId]
|
||||
if initialRemoteItemIds == localItemIds {
|
||||
resultingItemIds = remoteItemIds
|
||||
} else {
|
||||
var inputDialogPeers: [Api.InputDialogPeer] = []
|
||||
for itemId in resultingItemIds {
|
||||
switch itemId {
|
||||
case let .peer(peerId):
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
inputDialogPeers.append(Api.InputDialogPeer.inputDialogPeer(peer: inputPeer))
|
||||
}
|
||||
let locallyRemovedFromRemoteItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(localItemIdsWithoutSecretChats))
|
||||
let remotelyRemovedItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(remoteItemIds))
|
||||
|
||||
resultingItemIds = localItemIds.filter { !remotelyRemovedItemIds.contains($0) }
|
||||
resultingItemIds.append(contentsOf: remoteItemIds.filter { !locallyRemovedFromRemoteItemIds.contains($0) && !resultingItemIds.contains($0) })
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
transaction.setPinnedItemIds(groupId: groupId, itemIds: resultingItemIds)
|
||||
|
||||
transaction.updateCurrentPeerNotificationSettings(notificationSettings)
|
||||
|
||||
for (peerId, autoremoveValue) in ttlPeriods {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
let current = (current as? CachedUserData) ?? CachedUserData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let current = (current as? CachedChannelData) ?? CachedChannelData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
let current = (current as? CachedGroupData) ?? CachedGroupData()
|
||||
return current.withUpdatedAutoremoveTimeout(autoremoveValue)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var allPeersWithMessages = Set<PeerId>()
|
||||
for message in storeMessages {
|
||||
if !allPeersWithMessages.contains(message.id.peerId) {
|
||||
allPeersWithMessages.insert(message.id.peerId)
|
||||
}
|
||||
}
|
||||
let _ = transaction.addMessages(storeMessages, location: .UpperHistoryBlock)
|
||||
|
||||
transaction.resetIncomingReadStates(readStates)
|
||||
|
||||
for (peerId, pts) in channelStates {
|
||||
if let _ = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
// skip changing state
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
return network.request(Api.functions.messages.reorderPinnedDialogs(flags: 1 << 0, folderId: groupId.rawValue, order: inputDialogPeers))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(Api.Bool.boolFalse)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if remoteItemIds == resultingItemIds {
|
||||
return .complete()
|
||||
} else {
|
||||
var inputDialogPeers: [Api.InputDialogPeer] = []
|
||||
for itemId in resultingItemIds {
|
||||
switch itemId {
|
||||
case let .peer(peerId):
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
inputDialogPeers.append(Api.InputDialogPeer.inputDialogPeer(peer: inputPeer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return network.request(Api.functions.messages.reorderPinnedDialogs(flags: 1 << 0, folderId: groupId.rawValue, order: inputDialogPeers))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(Api.Bool.boolFalse)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
@ -470,6 +470,7 @@ public final class EngineMessageReactionListContext {
|
||||
self.isLoadingMore = true
|
||||
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let message = self.message
|
||||
let reaction = self.reaction
|
||||
let currentOffset = self.state.nextOffset
|
||||
@ -500,24 +501,9 @@ public final class EngineMessageReactionListContext {
|
||||
return account.postbox.transaction { transaction -> InternalState in
|
||||
switch result {
|
||||
case let .messageReactionsList(_, count, reactions, chats, users, nextOffset):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var items: [EngineMessageReactionListContext.Item] = []
|
||||
for reaction in reactions {
|
||||
|
@ -384,7 +384,7 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption
|
||||
updatedPeer = updatedPeer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)
|
||||
}
|
||||
if !peer.isEqual(updatedPeer) {
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
||||
guard let fetchedChats = fetchedChats else {
|
||||
return .never()
|
||||
}
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, parsedPeers: fetchedChats.peers, storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||
for peerId in transaction.chatListGetAllPeerIds() {
|
||||
if peerId.namespace != Namespaces.Peer.SecretChat {
|
||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||
@ -40,9 +40,7 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
||||
transaction.removeAllChatListEntries(groupId: .root, exceptPeerNamespace: Namespaces.Peer.SecretChat)
|
||||
transaction.removeAllChatListEntries(groupId: .group(1), exceptPeerNamespace: Namespaces.Peer.SecretChat)
|
||||
|
||||
updatePeers(transaction: transaction, peers: fetchedChats.peers + additionalPeers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: fetchedChats.peers.union(with: additionalPeers))
|
||||
|
||||
for (threadMessageId, data) in fetchedChats.threadInfos {
|
||||
if let entry = StoredMessageHistoryThreadInfo(data.data) {
|
||||
@ -52,7 +50,6 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
||||
transaction.replaceMessageTagSummary(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: data.unreadReactionCount, maxId: data.topMessageId)
|
||||
}
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: fetchedChats.peerPresences)
|
||||
transaction.updateCurrentPeerNotificationSettings(fetchedChats.notificationSettings)
|
||||
let _ = transaction.addMessages(fetchedChats.storeMessages, location: .UpperHistoryBlock)
|
||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||
|
@ -100,6 +100,7 @@ public enum ChangeAccountPhoneNumberError {
|
||||
}
|
||||
|
||||
func _internal_requestChangeAccountPhoneNumber(account: Account, phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> Signal<Void, ChangeAccountPhoneNumberError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.account.changePhone(phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, phoneCode: phoneCode), automaticFloodWait: false)
|
||||
|> mapError { error -> ChangeAccountPhoneNumberError in
|
||||
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
|
||||
@ -114,10 +115,7 @@ func _internal_requestChangeAccountPhoneNumber(account: Account, phoneNumber: St
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, ChangeAccountPhoneNumberError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
let user = TelegramUser(user: result)
|
||||
updatePeers(transaction: transaction, peers: [user], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(transaction: transaction, chats: [], users: [result]))
|
||||
} |> mapError { _ -> ChangeAccountPhoneNumberError in }
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramUser {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmojiStatus(file.flatMap({ PeerEmojiStatus(fileId: $0.fileId.id, expirationDate: expirationDate) }))], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmojiStatus(file.flatMap({ PeerEmojiStatus(fileId: $0.fileId.id, expirationDate: expirationDate) }))], update: { _, updated in
|
||||
updated
|
||||
})
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import MtProtoKit
|
||||
|
||||
|
||||
func _internal_updateAccountPeerName(account: Account, firstName: String, lastName: String) -> Signal<Void, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.account.updateProfile(flags: (1 << 0) | (1 << 1), firstName: firstName, lastName: lastName, about: nil))
|
||||
|> map { result -> Api.User? in
|
||||
return result
|
||||
@ -16,9 +17,7 @@ func _internal_updateAccountPeerName(account: Account, firstName: String, lastNa
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let result = result {
|
||||
if let peer = TelegramUser.merge(transaction.getPeer(result.peerId) as? TelegramUser, rhs: result) {
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { $1 })
|
||||
}
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(transaction: transaction, chats: [], users: [result]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ public enum GetCurrentGroupCallError {
|
||||
}
|
||||
|
||||
func _internal_getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), limit: 4))
|
||||
|> mapError { _ -> GetCurrentGroupCallError in
|
||||
return .generic
|
||||
@ -96,20 +97,7 @@ func _internal_getCurrentGroupCall(account: Account, callId: Int64, accessHash:
|
||||
return nil
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
if let peerId = peerId {
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in
|
||||
if let cachedData = current as? CachedChannelData {
|
||||
@ -122,10 +110,7 @@ func _internal_getCurrentGroupCall(account: Account, callId: Int64, accessHash:
|
||||
})
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
||||
return GroupCallSummary(
|
||||
@ -340,6 +325,8 @@ public enum GetGroupCallParticipantsError {
|
||||
}
|
||||
|
||||
func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal<GroupCallParticipantsContext.State, GetGroupCallParticipantsError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let sortAscendingValue: Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int, Bool), GetGroupCallParticipantsError>
|
||||
|
||||
sortAscendingValue = _internal_getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash)
|
||||
@ -380,25 +367,8 @@ func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessH
|
||||
nextParticipantsFetchOffset = nil
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
||||
}
|
||||
@ -587,18 +557,7 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?,
|
||||
|
||||
state.sortAscending = parsedCall.sortAscending
|
||||
|
||||
let apiUsers: [Api.User] = []
|
||||
|
||||
state.adminIds = Set(peerAdminIds)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
let connectionMode: JoinGroupCallResult.ConnectionMode
|
||||
if let clientParamsData = parsedClientParams.data(using: .utf8), let dict = (try? JSONSerialization.jsonObject(with: clientParamsData, options: [])) as? [String: Any] {
|
||||
@ -681,11 +640,6 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?,
|
||||
|
||||
state.participants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: state.sortAscending) })
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
|
||||
return JoinGroupCallResult(
|
||||
callInfo: parsedCall,
|
||||
state: state,
|
||||
@ -805,7 +759,7 @@ func _internal_stopGroupCall(account: Account, peerId: PeerId, callId: Int64, ac
|
||||
flags.remove(.hasVoiceChat)
|
||||
flags.remove(.hasActiveVoiceChat)
|
||||
peer = peer.withUpdatedFlags(flags)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -814,7 +768,7 @@ func _internal_stopGroupCall(account: Account, peerId: PeerId, callId: Int64, ac
|
||||
flags.remove(.hasVoiceChat)
|
||||
flags.remove(.hasActiveVoiceChat)
|
||||
peer = peer.updateFlags(flags: flags, version: peer.version)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -2275,10 +2229,11 @@ func _internal_editGroupCallTitle(account: Account, callId: Int64, accessHash: I
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_groupCallDisplayAsAvailablePeers(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[FoundPeer], NoError> {
|
||||
func _internal_groupCallDisplayAsAvailablePeers(accountPeerId: PeerId, network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[FoundPeer], NoError> {
|
||||
return postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
} |> mapToSignal { inputPeer in
|
||||
}
|
||||
|> mapToSignal { inputPeer in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .complete()
|
||||
}
|
||||
@ -2287,34 +2242,39 @@ func _internal_groupCallDisplayAsAvailablePeers(network: Network, postbox: Postb
|
||||
|> `catch` { _ -> Signal<Api.phone.JoinAsPeers?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result in
|
||||
|> mapToSignal { result -> Signal<[FoundPeer], NoError> in
|
||||
guard let result = result else {
|
||||
return .single([])
|
||||
}
|
||||
switch result {
|
||||
case let .joinAsPeers(_, chats, _):
|
||||
var subscribers: [PeerId: Int32] = [:]
|
||||
let peers = chats.compactMap(parseTelegramGroupOrChannel)
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
switch chat {
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
case let .joinAsPeers(_, chats, users):
|
||||
return postbox.transaction { transaction -> [FoundPeer] in
|
||||
var subscribers: [PeerId: Int32] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
switch chat {
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
}
|
||||
case let .chat(_, _, _, _, participantsCount, _, _, _, _, _):
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
default:
|
||||
break
|
||||
}
|
||||
case let .chat(_, _, _, _, participantsCount, _, _, _, _, _):
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return postbox.transaction { transaction -> [Peer] in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return peers
|
||||
} |> map { peers -> [FoundPeer] in
|
||||
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let peer = transaction.getPeer(chat.peerId) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
return peers.map { FoundPeer(peer: $0, subscribers: subscribers[$0.id]) }
|
||||
}
|
||||
}
|
||||
@ -2382,7 +2342,7 @@ func _internal_cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId:
|
||||
if let (cachedPeers, timestamp) = cachedPeersAndTimestamp, currentTimestamp - timestamp < 60 * 3 && !cachedPeers.isEmpty {
|
||||
return .single(cachedPeers)
|
||||
} else {
|
||||
return _internal_groupCallDisplayAsAvailablePeers(network: account.network, postbox: account.postbox, peerId: peerId)
|
||||
return _internal_groupCallDisplayAsAvailablePeers(accountPeerId: account.peerId, network: account.network, postbox: account.postbox, peerId: peerId)
|
||||
|> mapToSignal { peers -> Signal<[FoundPeer], NoError> in
|
||||
return account.postbox.transaction { transaction -> [FoundPeer] in
|
||||
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
|
@ -12,30 +12,21 @@ private func md5(_ data: Data) -> Data {
|
||||
}
|
||||
}
|
||||
|
||||
private func updatedRemoteContactPeers(network: Network, hash: Int64) -> Signal<([Peer], [PeerId: PeerPresence], Int32)?, NoError> {
|
||||
private func updatedRemoteContactPeers(network: Network, hash: Int64) -> Signal<(AccumulatedPeers, Int32)?, NoError> {
|
||||
return network.request(Api.functions.contacts.getContacts(hash: hash), automaticFloodWait: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.contacts.Contacts?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> ([Peer], [PeerId: PeerPresence], Int32)? in
|
||||
|> map { result -> (AccumulatedPeers, Int32)? in
|
||||
guard let result = result else {
|
||||
return nil
|
||||
}
|
||||
switch result {
|
||||
case .contactsNotModified:
|
||||
return nil
|
||||
case let .contacts(_, savedCount, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
peerPresences[telegramUser.id] = presence
|
||||
}
|
||||
}
|
||||
return (peers, peerPresences, savedCount)
|
||||
case .contactsNotModified:
|
||||
return nil
|
||||
case let .contacts(_, savedCount, users):
|
||||
return (AccumulatedPeers(users: users), savedCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,29 +51,28 @@ func syncContactsOnce(network: Network, postbox: Postbox, accountPeerId: PeerId)
|
||||
}
|
||||
|
||||
let updatedPeers = initialContactPeerIdsHash
|
||||
|> mapToSignal { hash -> Signal<([Peer], [PeerId: PeerPresence], Int32)?, NoError> in
|
||||
|> mapToSignal { hash -> Signal<(AccumulatedPeers, Int32)?, NoError> in
|
||||
return updatedRemoteContactPeers(network: network, hash: hash)
|
||||
}
|
||||
|
||||
let appliedUpdatedPeers = updatedPeers
|
||||
|> mapToSignal { peersAndPresences -> Signal<Never, NoError> in
|
||||
if let (peers, peerPresences, totalCount) = peersAndPresences {
|
||||
if let (peers, totalCount) = peersAndPresences {
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
let previousIds = transaction.getContactPeerIds()
|
||||
let wasEmpty = previousIds.isEmpty
|
||||
|
||||
transaction.replaceRemoteContactCount(totalCount)
|
||||
|
||||
updatePeerPresencesClean(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
if wasEmpty {
|
||||
let users = Array(peers.users.values)
|
||||
var insertSignal: Signal<Void, NoError> = .complete()
|
||||
for s in stride(from: 0, to: peers.count, by: 500) {
|
||||
let partPeers = Array(peers[s ..< min(s + 500, peers.count)])
|
||||
for s in stride(from: 0, to: users.count, by: 500) {
|
||||
let partUsers = Array(users[s ..< min(s + 500, users.count)])
|
||||
let partSignal = postbox.transaction { transaction -> Void in
|
||||
updatePeers(transaction: transaction, peers: partPeers, update: { return $1 })
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: partUsers))
|
||||
var updatedIds = transaction.getContactPeerIds()
|
||||
updatedIds.formUnion(partPeers.map { $0.id })
|
||||
updatedIds.formUnion(partUsers.map { $0.peerId })
|
||||
transaction.replaceContactPeerIds(updatedIds)
|
||||
}
|
||||
|> delay(0.1, queue: Queue.concurrentDefaultQueue())
|
||||
@ -91,7 +81,7 @@ func syncContactsOnce(network: Network, postbox: Postbox, accountPeerId: PeerId)
|
||||
|
||||
return insertSignal
|
||||
} else {
|
||||
transaction.replaceContactPeerIds(Set(peers.map { $0.id }))
|
||||
transaction.replaceContactPeerIds(Set(peers.users.keys))
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import SwiftSignalKit
|
||||
|
||||
|
||||
func _internal_importContact(account: Account, firstName: String, lastName: String, phoneNumber: String) -> Signal<PeerId?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let input = Api.InputContact.inputPhoneContact(clientId: 1, phone: phoneNumber, firstName: firstName, lastName: lastName)
|
||||
|
||||
return account.network.request(Api.functions.contacts.importContacts(contacts: [input]))
|
||||
@ -17,11 +19,10 @@ func _internal_importContact(account: Account, firstName: String, lastName: Stri
|
||||
switch result {
|
||||
case let .importedContacts(_, _, _, users):
|
||||
if let first = users.first {
|
||||
let user = TelegramUser(user: first)
|
||||
let peerId = user.id
|
||||
updatePeers(transaction: transaction, peers: [user], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
let peerId = first.peerId
|
||||
|
||||
var peerIds = transaction.getContactPeerIds()
|
||||
if !peerIds.contains(peerId) {
|
||||
peerIds.insert(peerId)
|
||||
@ -41,6 +42,8 @@ public enum AddContactError {
|
||||
}
|
||||
|
||||
func _internal_addContactInteractively(account: Account, peerId: PeerId, firstName: String, lastName: String, phoneNumber: String, addToPrivacyExceptions: Bool) -> Signal<Never, AddContactError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.postbox.transaction { transaction -> (Api.InputUser, String)? in
|
||||
if let user = transaction.getPeer(peerId) as? TelegramUser, let inputUser = apiInputUser(user) {
|
||||
return (inputUser, user.phone == nil ? phoneNumber : "")
|
||||
@ -63,22 +66,16 @@ func _internal_addContactInteractively(account: Account, peerId: PeerId, firstNa
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, AddContactError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peers = AccumulatedPeers()
|
||||
switch result {
|
||||
case let .updates(_, users, _, _, _):
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
case let .updatesCombined(_, users, _, _, _, _):
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
default:
|
||||
break
|
||||
case let .updates(_, users, _, _, _):
|
||||
peers = AccumulatedPeers(users: users)
|
||||
case let .updatesCombined(_, users, _, _, _, _):
|
||||
peers = AccumulatedPeers(users: users)
|
||||
default:
|
||||
break
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: peers)
|
||||
var peerIds = transaction.getContactPeerIds()
|
||||
if !peerIds.contains(peerId) {
|
||||
peerIds.insert(peerId)
|
||||
|
@ -442,6 +442,8 @@ private class AdMessagesHistoryContextImpl {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
self.stateValue = State(interPostInterval: nil, messages: [])
|
||||
|
||||
@ -478,25 +480,8 @@ private class AdMessagesHistoryContextImpl {
|
||||
return account.postbox.transaction { transaction -> (interPostInterval: Int32?, messages: [Message]) in
|
||||
switch result {
|
||||
case let .sponsoredMessages(_, postsBetween, messages, chats, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var parsedMessages: [CachedMessage] = []
|
||||
|
||||
|
@ -269,7 +269,7 @@ private func removeCachedAttachMenuBot(postbox: Postbox, botId: PeerId) -> Signa
|
||||
}
|
||||
}
|
||||
|
||||
func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network, force: Bool = false) -> Signal<Void, NoError> {
|
||||
func managedSynchronizeAttachMenuBots(accountPeerId: PeerId, postbox: Postbox, network: Network, force: Bool = false) -> Signal<Void, NoError> {
|
||||
let poll = Signal<Void, NoError> { subscriber in
|
||||
let signal: Signal<Void, NoError> = cachedAttachMenuBots(postbox: postbox)
|
||||
|> mapToSignal { current in
|
||||
@ -285,14 +285,7 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network, force:
|
||||
return postbox.transaction { transaction -> Void in
|
||||
switch result {
|
||||
case let .attachMenuBots(hash, bots, users):
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
var resultBots: [AttachMenuBots.Bot] = []
|
||||
for bot in bots {
|
||||
@ -368,7 +361,7 @@ public enum AddBotToAttachMenuError {
|
||||
}
|
||||
|
||||
|
||||
func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: PeerId, allowWrite: Bool) -> Signal<Bool, AddBotToAttachMenuError> {
|
||||
func _internal_addBotToAttachMenu(accountPeerId: PeerId, postbox: Postbox, network: Network, botId: PeerId, allowWrite: Bool) -> Signal<Bool, AddBotToAttachMenuError> {
|
||||
return postbox.transaction { transaction -> Signal<Bool, AddBotToAttachMenuError> in
|
||||
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
|
||||
return .complete()
|
||||
@ -391,7 +384,7 @@ func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: Pee
|
||||
}
|
||||
|> mapToSignal { value -> Signal<Bool, AddBotToAttachMenuError> in
|
||||
if value {
|
||||
return managedSynchronizeAttachMenuBots(postbox: postbox, network: network, force: true)
|
||||
return managedSynchronizeAttachMenuBots(accountPeerId: accountPeerId, postbox: postbox, network: network, force: true)
|
||||
|> castError(AddBotToAttachMenuError.self)
|
||||
|> take(1)
|
||||
|> map { _ -> Bool in
|
||||
@ -406,7 +399,7 @@ func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: Pee
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func _internal_removeBotFromAttachMenu(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
|
||||
func _internal_removeBotFromAttachMenu(accountPeerId: PeerId, postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Bool, NoError> in
|
||||
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
|
||||
return .complete()
|
||||
@ -424,7 +417,7 @@ func _internal_removeBotFromAttachMenu(postbox: Postbox, network: Network, botId
|
||||
return .single(false)
|
||||
}
|
||||
|> afterCompleted {
|
||||
let _ = (managedSynchronizeAttachMenuBots(postbox: postbox, network: network, force: true)
|
||||
let _ = (managedSynchronizeAttachMenuBots(accountPeerId: accountPeerId, postbox: postbox, network: network, force: true)
|
||||
|> take(1)).start(completed: {
|
||||
let _ = removeCachedAttachMenuBot(postbox: postbox, botId: botId)
|
||||
})
|
||||
@ -468,7 +461,7 @@ public enum GetAttachMenuBotError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_getAttachMenuBot(postbox: Postbox, network: Network, botId: PeerId, cached: Bool) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
|
||||
func _internal_getAttachMenuBot(accountPeerId: PeerId, postbox: Postbox, network: Network, botId: PeerId, cached: Bool) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
|
||||
return postbox.transaction { transaction -> Signal<AttachMenuBot, GetAttachMenuBotError> in
|
||||
if cached, let cachedBots = cachedAttachMenuBots(transaction: transaction)?.bots {
|
||||
if let bot = cachedBots.first(where: { $0.peerId == botId }), let peer = transaction.getPeer(bot.peerId) {
|
||||
@ -487,19 +480,14 @@ func _internal_getAttachMenuBot(postbox: Postbox, network: Network, botId: PeerI
|
||||
return postbox.transaction { transaction -> Signal<AttachMenuBot, GetAttachMenuBotError> in
|
||||
switch result {
|
||||
case let .attachMenuBotsBot(bot, users):
|
||||
var peers: [Peer] = []
|
||||
var peer: Peer?
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
|
||||
if telegramUser.id == botId {
|
||||
peer = telegramUser
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
guard let peer = peer else {
|
||||
return .fail(.generic)
|
||||
|
@ -7,6 +7,7 @@ public final class EngineChatList: Equatable {
|
||||
}
|
||||
|
||||
public typealias MessageTagSummaryInfo = ChatListMessageTagSummaryInfo
|
||||
public typealias StoryStats = PeerStoryStats
|
||||
|
||||
public enum PinnedItem {
|
||||
public typealias Id = PinnedItemId
|
||||
@ -127,6 +128,7 @@ public final class EngineChatList: Equatable {
|
||||
public let hasFailed: Bool
|
||||
public let isContact: Bool
|
||||
public let autoremoveTimeout: Int32?
|
||||
public let storyStats: StoryStats?
|
||||
|
||||
public init(
|
||||
id: Id,
|
||||
@ -144,7 +146,8 @@ public final class EngineChatList: Equatable {
|
||||
topForumTopicItems: [EngineChatList.ForumTopicData],
|
||||
hasFailed: Bool,
|
||||
isContact: Bool,
|
||||
autoremoveTimeout: Int32?
|
||||
autoremoveTimeout: Int32?,
|
||||
storyStats: StoryStats?
|
||||
) {
|
||||
self.id = id
|
||||
self.index = index
|
||||
@ -162,6 +165,7 @@ public final class EngineChatList: Equatable {
|
||||
self.hasFailed = hasFailed
|
||||
self.isContact = isContact
|
||||
self.autoremoveTimeout = autoremoveTimeout
|
||||
self.storyStats = storyStats
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
@ -213,6 +217,9 @@ public final class EngineChatList: Equatable {
|
||||
if lhs.autoremoveTimeout != rhs.autoremoveTimeout {
|
||||
return false
|
||||
}
|
||||
if lhs.storyStats != rhs.storyStats {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -414,7 +421,21 @@ public extension EngineChatList.RelativePosition {
|
||||
extension EngineChatList.Item {
|
||||
convenience init?(_ entry: ChatListEntry) {
|
||||
switch entry {
|
||||
case let .MessageEntry(index, messages, readState, isRemovedFromTotalUnreadCount, embeddedState, renderedPeer, presence, tagSummaryInfo, forumTopicData, topForumTopics, hasFailed, isContact, autoremoveTimeout):
|
||||
case let .MessageEntry(entryData):
|
||||
let index = entryData.index
|
||||
let messages = entryData.messages
|
||||
let readState = entryData.readState
|
||||
let isRemovedFromTotalUnreadCount = entryData.isRemovedFromTotalUnreadCount
|
||||
let embeddedState = entryData.embeddedInterfaceState
|
||||
let renderedPeer = entryData.renderedPeer
|
||||
let presence = entryData.presence
|
||||
let tagSummaryInfo = entryData.summaryInfo
|
||||
let forumTopicData = entryData.forumTopicData
|
||||
let topForumTopics = entryData.topForumTopics
|
||||
let hasFailed = entryData.hasFailed
|
||||
let isContact = entryData.isContact
|
||||
let autoremoveTimeout = entryData.autoremoveTimeout
|
||||
|
||||
var draft: EngineChatList.Draft?
|
||||
if let embeddedState = embeddedState, let _ = embeddedState.overrideChatTimestamp {
|
||||
if let opaqueState = _internal_decodeStoredChatInterfaceState(state: embeddedState) {
|
||||
@ -482,7 +503,8 @@ extension EngineChatList.Item {
|
||||
topForumTopicItems: topForumTopicItems,
|
||||
hasFailed: hasFailed,
|
||||
isContact: isContact,
|
||||
autoremoveTimeout: autoremoveTimeout
|
||||
autoremoveTimeout: autoremoveTimeout,
|
||||
storyStats: entryData.storyStats
|
||||
)
|
||||
case .HoleEntry:
|
||||
return nil
|
||||
|
@ -16,18 +16,8 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network,
|
||||
var keys = Set<Key>()
|
||||
switch updates {
|
||||
case let .updates(updates, users, chats, _, _):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for update in updates {
|
||||
switch update {
|
||||
case let .updateDraftMessage(_, peer, topMsgId, _):
|
||||
@ -40,11 +30,8 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network,
|
||||
break
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
var signals: [Signal<Void, NoError>] = []
|
||||
for key in keys {
|
||||
_internal_updateChatInputState(transaction: transaction, peerId: key.peerId, threadId: key.threadId, inputState: nil)
|
||||
|
@ -92,23 +92,8 @@ func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Po
|
||||
_ = transaction.addMessages(storeMessages, location: .Random)
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
var loadedMessages:[Message] = []
|
||||
for messageId in missingMessageIds {
|
||||
|
@ -250,6 +250,7 @@ private final class PollResultsOptionContext {
|
||||
let messageId = self.messageId
|
||||
let opaqueIdentifier = self.opaqueIdentifier
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let nextOffset = self.nextOffset
|
||||
let populateCache = self.populateCache
|
||||
self.disposable.set((self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
@ -273,18 +274,8 @@ private final class PollResultsOptionContext {
|
||||
}
|
||||
switch result {
|
||||
case let .votesList(_, count, votes, chats, users, nextOffset):
|
||||
var peers: [Peer] = []
|
||||
for apiChat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: apiChat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
for apiUser in users {
|
||||
peers.append(TelegramUser(user: apiUser))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
var resultPeers: [RenderedPeer] = []
|
||||
for vote in votes {
|
||||
let peerId: PeerId
|
||||
|
@ -138,6 +138,8 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
})
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let updateInitialState: Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> = account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(data.messageId.peerId)
|
||||
}
|
||||
@ -176,27 +178,11 @@ private class ReplyThreadHistoryContextImpl {
|
||||
}
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
let _ = transaction.addMessages(parsedMessages, location: .Random)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let resolvedMaxMessage: MessageId?
|
||||
if let maxId = maxId {
|
||||
@ -608,6 +594,8 @@ public enum FetchChannelReplyThreadMessageError {
|
||||
}
|
||||
|
||||
func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: MessageId, atMessageId: MessageId?) -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(messageId.peerId)
|
||||
}
|
||||
@ -653,27 +641,11 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
||||
}
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
let _ = transaction.addMessages(parsedMessages, location: .Random)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let resolvedMaxMessage: MessageId?
|
||||
if let maxId = maxId {
|
||||
|
@ -545,7 +545,7 @@ func _internal_downloadMessage(postbox: Postbox, network: Network, messageId: Me
|
||||
}
|
||||
}
|
||||
|
||||
func fetchRemoteMessage(postbox: Postbox, source: FetchMessageHistoryHoleSource, message: MessageReference) -> Signal<Message?, NoError> {
|
||||
func fetchRemoteMessage(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, message: MessageReference) -> Signal<Message?, NoError> {
|
||||
guard case let .message(peer, _, id, _, _, _) = message.content else {
|
||||
return .single(nil)
|
||||
}
|
||||
@ -597,28 +597,13 @@ func fetchRemoteMessage(postbox: Postbox, source: FetchMessageHistoryHoleSource,
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Message? in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers[user.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = mergeGroupOrChannel(lhs: transaction.getPeer(chat.peerId), rhs: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var renderedMessages: [Message] = []
|
||||
for message in messages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = transaction.getPeer(peerId), peer.isForum {
|
||||
if let peerId = message.peerId, let peer = transaction.getPeer(peerId) ?? parsedPeers.get(peerId), peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peerIsForum, namespace: id.namespace), case let .Id(updatedId) = message.id {
|
||||
@ -633,6 +618,12 @@ func fetchRemoteMessage(postbox: Postbox, source: FetchMessageHistoryHoleSource,
|
||||
}
|
||||
}
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for id in parsedPeers.allIds {
|
||||
if let peer = transaction.getPeer(id) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
if !addedExisting, let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
|
||||
renderedMessages.append(renderedMessage)
|
||||
}
|
||||
@ -756,7 +747,7 @@ public enum UpdatedRemotePeerError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerReference) -> Signal<Peer, UpdatedRemotePeerError> {
|
||||
func _internal_updatedRemotePeer(accountPeerId: PeerId, postbox: Postbox, network: Network, peer: PeerReference) -> Signal<Peer, UpdatedRemotePeerError> {
|
||||
if let inputUser = peer.inputUser {
|
||||
return network.request(Api.functions.users.getUsers(id: [inputUser]))
|
||||
|> mapError { _ -> UpdatedRemotePeerError in
|
||||
@ -767,12 +758,10 @@ func _internal_updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerR
|
||||
return .fail(.generic)
|
||||
}
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
guard let peer = TelegramUser.merge(transaction.getPeer(apiUser.peerId) as? TelegramUser, rhs: apiUser) else {
|
||||
return nil
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(users: [apiUser])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let peer = transaction.getPeer(apiUser.peerId)
|
||||
return peer
|
||||
}
|
||||
|> castError(UpdatedRemotePeerError.self)
|
||||
@ -790,25 +779,30 @@ func _internal_updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerR
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Peer, UpdatedRemotePeerError> in
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
return postbox.transaction { transaction -> Signal<Peer, UpdatedRemotePeerError> in
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
case let .chats(c):
|
||||
chats = c
|
||||
case let .chatsSlice(_, c):
|
||||
chats = c
|
||||
}
|
||||
if let updatedPeer = chats.first.flatMap(parseTelegramGroupOrChannel), updatedPeer.id == peer.id {
|
||||
return postbox.transaction { transaction -> Peer in
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return updatedPeer
|
||||
}
|
||||
|> mapError { _ -> UpdatedRemotePeerError in
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
|
||||
if let firstId = chats.first?.peerId, let updatedPeer = parsedPeers.get(firstId), updatedPeer.id == peer.id {
|
||||
return postbox.transaction { transaction -> Peer in
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
return updatedPeer
|
||||
}
|
||||
|> mapError { _ -> UpdatedRemotePeerError in
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|> castError(UpdatedRemotePeerError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
} else if let inputChannel = peer.inputChannel {
|
||||
return network.request(Api.functions.channels.getChannels(id: [inputChannel]))
|
||||
@ -816,25 +810,30 @@ func _internal_updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerR
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Peer, UpdatedRemotePeerError> in
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
return postbox.transaction { transaction -> Signal<Peer, UpdatedRemotePeerError> in
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
case let .chats(c):
|
||||
chats = c
|
||||
case let .chatsSlice(_, c):
|
||||
chats = c
|
||||
}
|
||||
if let updatedPeer = chats.first.flatMap(parseTelegramGroupOrChannel), updatedPeer.id == peer.id {
|
||||
return postbox.transaction { transaction -> Peer in
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return updatedPeer
|
||||
}
|
||||
|> mapError { _ -> UpdatedRemotePeerError in
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
|
||||
if let firstId = chats.first?.peerId, let updatedPeer = parsedPeers.get(firstId), updatedPeer.id == peer.id {
|
||||
return postbox.transaction { transaction -> Peer in
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
return updatedPeer
|
||||
}
|
||||
|> mapError { _ -> UpdatedRemotePeerError in
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|> castError(UpdatedRemotePeerError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
|
@ -77,7 +77,7 @@ func _internal_cachedPeerSendAsAvailablePeers(account: Account, peerId: PeerId)
|
||||
initialSignal = .complete()
|
||||
}
|
||||
return initialSignal
|
||||
|> then(_internal_peerSendAsAvailablePeers(network: account.network, postbox: account.postbox, peerId: peerId)
|
||||
|> then(_internal_peerSendAsAvailablePeers(accountPeerId: account.peerId, network: account.network, postbox: account.postbox, peerId: peerId)
|
||||
|> mapToSignal { peers -> Signal<[SendAsPeer], NoError> in
|
||||
return account.postbox.transaction { transaction -> [SendAsPeer] in
|
||||
let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
@ -97,7 +97,7 @@ func _internal_cachedPeerSendAsAvailablePeers(account: Account, peerId: PeerId)
|
||||
}
|
||||
|
||||
|
||||
func _internal_peerSendAsAvailablePeers(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[SendAsPeer], NoError> {
|
||||
func _internal_peerSendAsAvailablePeers(accountPeerId: PeerId, network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[SendAsPeer], NoError> {
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
@ -119,40 +119,44 @@ func _internal_peerSendAsAvailablePeers(network: Network, postbox: Postbox, peer
|
||||
|> `catch` { _ -> Signal<Api.channels.SendAsPeers?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result in
|
||||
|> mapToSignal { result -> Signal<[SendAsPeer], NoError> in
|
||||
guard let result = result else {
|
||||
return .single([])
|
||||
}
|
||||
switch result {
|
||||
case let .sendAsPeers(sendAsPeers, chats, _):
|
||||
var subscribers: [PeerId: Int32] = [:]
|
||||
let peers = chats.compactMap(parseTelegramGroupOrChannel)
|
||||
var premiumRequiredPeerIds = Set<PeerId>()
|
||||
for sendAsPeer in sendAsPeers {
|
||||
if case let .sendAsPeer(flags, peer) = sendAsPeer, (flags & (1 << 0)) != 0 {
|
||||
premiumRequiredPeerIds.insert(peer.peerId)
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
switch chat {
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
}
|
||||
case let .chat(_, _, _, _, participantsCount, _, _, _, _, _):
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
default:
|
||||
break
|
||||
return postbox.transaction { transaction -> [SendAsPeer] in
|
||||
var subscribers: [PeerId: Int32] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
|
||||
var premiumRequiredPeerIds = Set<PeerId>()
|
||||
for sendAsPeer in sendAsPeers {
|
||||
if case let .sendAsPeer(flags, peer) = sendAsPeer, (flags & (1 << 0)) != 0 {
|
||||
premiumRequiredPeerIds.insert(peer.peerId)
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parsedPeers.get(chat.peerId) {
|
||||
switch chat {
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
}
|
||||
case let .chat(_, _, _, _, participantsCount, _, _, _, _, _):
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId,peers: parsedPeers)
|
||||
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let peer = transaction.getPeer(chat.peerId) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
return postbox.transaction { transaction -> [Peer] in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return peers
|
||||
} |> map { peers -> [SendAsPeer] in
|
||||
return peers.map { SendAsPeer(peer: $0, subscribers: subscribers[$0.id], isPremiumRequired: premiumRequiredPeerIds.contains($0.id)) }
|
||||
}
|
||||
}
|
||||
|
@ -801,6 +801,7 @@ public final class SparseMessageCalendar {
|
||||
}
|
||||
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let peerId = self.peerId
|
||||
let messageTag = self.messageTag
|
||||
self.disposable.set((self.account.postbox.transaction { transaction -> Peer? in
|
||||
@ -830,19 +831,8 @@ public final class SparseMessageCalendar {
|
||||
switch result {
|
||||
case let .searchResultsCalendar(_, _, minDate, minMsgId, _, periods, messages, chats, users):
|
||||
var parsedMessages: [StoreMessage] = []
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for message in messages {
|
||||
if let parsedMessage = StoreMessage(apiMessage: message, peerIsForum: peer.isForum) {
|
||||
@ -850,8 +840,7 @@ public final class SparseMessageCalendar {
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
let _ = transaction.addMessages(parsedMessages, location: .Random)
|
||||
|
||||
var minMessageId: Int32?
|
||||
|
@ -410,8 +410,8 @@ public enum Stories {
|
||||
}
|
||||
|
||||
public final class PeerState: Equatable, Codable {
|
||||
private enum CodingKeys: CodingKey {
|
||||
case maxReadId
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case maxReadId = "rid"
|
||||
}
|
||||
|
||||
public let maxReadId: Int32
|
||||
@ -576,6 +576,12 @@ public final class EngineStorySubscriptions: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Stories.PeerState {
|
||||
var postboxRepresentation: StoredStoryPeerState {
|
||||
return StoredStoryPeerState(entry: CodableEntry(self)!, maxSeenId: self.maxReadId)
|
||||
}
|
||||
}
|
||||
|
||||
public enum StoryUploadResult {
|
||||
case progress(Float)
|
||||
case completed(Int32?)
|
||||
@ -1121,7 +1127,7 @@ func _internal_markStoryAsSeen(account: Account, peerId: PeerId, id: Int32, asPi
|
||||
return .complete()
|
||||
}
|
||||
|
||||
#if DEBUG && false
|
||||
#if DEBUG && true
|
||||
if "".isEmpty {
|
||||
return .complete()
|
||||
}
|
||||
@ -1135,10 +1141,10 @@ func _internal_markStoryAsSeen(account: Account, peerId: PeerId, id: Int32, asPi
|
||||
}
|
||||
} else {
|
||||
return account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
if let peerStoryState = transaction.getPeerStoryState(peerId: peerId)?.get(Stories.PeerState.self) {
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
if let peerStoryState = transaction.getPeerStoryState(peerId: peerId)?.entry.get(Stories.PeerState.self) {
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: max(peerStoryState.maxReadId, id)
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
}
|
||||
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
@ -1352,19 +1358,7 @@ func _internal_getStoriesById(accountPeerId: PeerId, postbox: Postbox, network:
|
||||
return postbox.transaction { transaction -> [Stories.StoredItem] in
|
||||
switch result {
|
||||
case let .stories(_, stories, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
return stories.compactMap { apiStoryItem -> Stories.StoredItem? in
|
||||
return Stories.StoredItem(apiStoryItem: apiStoryItem, peerId: peer.id, transaction: transaction)
|
||||
@ -1395,19 +1389,7 @@ func _internal_getStoriesById(accountPeerId: PeerId, postbox: Postbox, source: F
|
||||
return postbox.transaction { transaction -> [Stories.StoredItem] in
|
||||
switch result {
|
||||
case let .stories(_, stories, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
return stories.compactMap { apiStoryItem -> Stories.StoredItem? in
|
||||
return Stories.StoredItem(apiStoryItem: apiStoryItem, peerId: peerId, transaction: transaction)
|
||||
@ -1439,6 +1421,7 @@ public final class StoryViewList {
|
||||
}
|
||||
|
||||
func _internal_getStoryViewList(account: Account, id: Int32, offsetTimestamp: Int32?, offsetPeerId: PeerId?, limit: Int) -> Signal<StoryViewList?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.stories.getStoryViewsList(id: id, offsetDate: offsetTimestamp ?? 0, offsetId: offsetPeerId?.id._internalGetInt64Value() ?? 0, limit: Int32(limit)))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.stories.StoryViewsList?, NoError> in
|
||||
@ -1451,19 +1434,7 @@ func _internal_getStoryViewList(account: Account, id: Int32, offsetTimestamp: In
|
||||
return account.postbox.transaction { transaction -> StoryViewList? in
|
||||
switch result {
|
||||
case let .storyViewsList(count, views, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
var items: [StoryViewList.Item] = []
|
||||
for view in views {
|
||||
@ -1482,6 +1453,7 @@ func _internal_getStoryViewList(account: Account, id: Int32, offsetTimestamp: In
|
||||
}
|
||||
|
||||
func _internal_getStoryViews(account: Account, ids: [Int32]) -> Signal<[Int32: Stories.Item.Views], NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.stories.getStoriesViews(id: ids))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.stories.StoryViews?, NoError> in
|
||||
@ -1495,19 +1467,7 @@ func _internal_getStoryViews(account: Account, ids: [Int32]) -> Signal<[Int32: S
|
||||
var parsedViews: [Int32: Stories.Item.Views] = [:]
|
||||
switch result {
|
||||
case let .storyViews(views, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
for i in 0 ..< views.count {
|
||||
if i < ids.count {
|
||||
@ -1621,6 +1581,7 @@ public final class EngineStoryViewListContext {
|
||||
self.isLoadingMore = true
|
||||
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let storyId = self.storyId
|
||||
let currentOffset = self.state.nextOffset
|
||||
let limit = self.state.items.isEmpty ? 50 : 100
|
||||
@ -1636,19 +1597,7 @@ public final class EngineStoryViewListContext {
|
||||
return account.postbox.transaction { transaction -> InternalState in
|
||||
switch result {
|
||||
case let .storyViewsList(count, views, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
var items: [Item] = []
|
||||
var nextOffset: NextOffset?
|
||||
@ -1803,7 +1752,7 @@ func _internal_updatePeerStoriesHidden(account: Account, id: PeerId, isHidden: B
|
||||
guard let user = peer as? TelegramUser else {
|
||||
return nil
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: [user.withUpdatedStoriesHidden(isHidden)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [user.withUpdatedStoriesHidden(isHidden)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return apiInputUser(peer)
|
||||
@ -1879,3 +1828,36 @@ func _internal_refreshStories(account: Account, peerId: PeerId, ids: [Int32]) ->
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_refreshSeenStories(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
|
||||
return network.request(Api.functions.stories.getAllReadUserStories())
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<Never, NoError> in
|
||||
guard let updates = updates else {
|
||||
return .complete()
|
||||
}
|
||||
return postbox.transaction { transaction -> Void in
|
||||
for update in updates.allUpdates {
|
||||
switch update {
|
||||
case let .updateReadStories(userId, maxId):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
|
||||
var update = false
|
||||
if let value = transaction.getPeerStoryState(peerId: peerId) {
|
||||
update = value.maxSeenId < maxId
|
||||
} else {
|
||||
update = true
|
||||
}
|
||||
if update {
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(maxReadId: maxId).postboxRepresentation)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
|
@ -317,14 +317,7 @@ public final class StorySubscriptionsContext {
|
||||
case let .allStories(flags, _, state, userStories, users):
|
||||
//TODO:count
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
|
||||
let hasMore: Bool = (flags & (1 << 0)) != 0
|
||||
|
||||
@ -354,9 +347,9 @@ public final class StorySubscriptionsContext {
|
||||
peerEntries.append(peerId)
|
||||
|
||||
transaction.setStoryItems(peerId: peerId, items: updatedPeerEntries)
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: maxReadId ?? 0
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,10 +372,7 @@ public final class StorySubscriptionsContext {
|
||||
hasMore: hasMore
|
||||
)), peerIds: peerEntries)
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|> deliverOn(self.queue)).start(completed: { [weak self] in
|
||||
@ -549,6 +539,7 @@ public final class PeerStoryListContext {
|
||||
|
||||
let peerId = self.peerId
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let isArchived = self.isArchived
|
||||
self.requestDisposable = (self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
@ -565,7 +556,9 @@ public final class PeerStoryListContext {
|
||||
signal = account.network.request(Api.functions.stories.getPinnedStories(userId: inputUser, offsetId: Int32(loadMoreToken), limit: 100))
|
||||
}
|
||||
return signal
|
||||
|> map(Optional.init)
|
||||
|> map { result -> Api.stories.Stories? in
|
||||
return result
|
||||
}
|
||||
|> `catch` { _ -> Signal<Api.stories.Stories?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
@ -582,19 +575,7 @@ public final class PeerStoryListContext {
|
||||
case let .stories(count, stories, users):
|
||||
totalCount = Int(count)
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
for story in stories {
|
||||
if let storedItem = Stories.StoredItem(apiStoryItem: story, peerId: peerId, transaction: transaction) {
|
||||
@ -897,16 +878,21 @@ public final class PeerExpiringStoryListContext {
|
||||
return self.statePromise.get()
|
||||
}
|
||||
|
||||
private let polledOnce = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
|
||||
init(queue: Queue, account: Account, peerId: EnginePeer.Id) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
|
||||
self.listDisposable = (account.postbox.combinedView(keys: [
|
||||
PostboxViewKey.storiesState(key: .peer(peerId)),
|
||||
PostboxViewKey.storyItems(peerId: peerId)
|
||||
])
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] views in
|
||||
self.listDisposable = (combineLatest(queue: self.queue,
|
||||
account.postbox.combinedView(keys: [
|
||||
PostboxViewKey.storiesState(key: .peer(peerId)),
|
||||
PostboxViewKey.storyItems(peerId: peerId)
|
||||
]),
|
||||
self.polledOnce.get()
|
||||
)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] views, polledOnce in
|
||||
guard let `self` = self else {
|
||||
return
|
||||
}
|
||||
@ -961,7 +947,8 @@ public final class PeerExpiringStoryListContext {
|
||||
return State(
|
||||
items: items,
|
||||
isCached: false,
|
||||
maxReadId: state?.maxReadId ?? 0
|
||||
maxReadId: state?.maxReadId ?? 0,
|
||||
isLoading: items.isEmpty && !polledOnce
|
||||
)
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] state in
|
||||
@ -987,6 +974,7 @@ public final class PeerExpiringStoryListContext {
|
||||
self.pollDisposable?.dispose()
|
||||
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let peerId = self.peerId
|
||||
self.pollDisposable = (self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
@ -1006,14 +994,7 @@ public final class PeerExpiringStoryListContext {
|
||||
updatedPeerEntries.removeAll()
|
||||
|
||||
if let result = result, case let .userStories(stories, users) = result {
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
|
||||
switch stories {
|
||||
case let .userStories(_, userId, maxReadId, stories):
|
||||
@ -1033,15 +1014,12 @@ public final class PeerExpiringStoryListContext {
|
||||
}
|
||||
}
|
||||
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: maxReadId ?? 0
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
|
||||
transaction.setStoryItems(peerId: peerId, items: updatedPeerEntries)
|
||||
@ -1052,6 +1030,9 @@ public final class PeerExpiringStoryListContext {
|
||||
guard let `self` = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.polledOnce.set(true)
|
||||
|
||||
self.pollDisposable = (Signal<Never, NoError>.complete() |> suspendAwareDelay(60.0, queue: self.queue) |> deliverOn(self.queue)).start(completed: { [weak self] in
|
||||
guard let `self` = self else {
|
||||
return
|
||||
@ -1098,6 +1079,7 @@ public final class PeerExpiringStoryListContext {
|
||||
public let items: [Item]
|
||||
public let isCached: Bool
|
||||
public let maxReadId: Int32
|
||||
public let isLoading: Bool
|
||||
|
||||
public var hasUnseen: Bool {
|
||||
return self.items.contains(where: { $0.id > self.maxReadId })
|
||||
@ -1117,10 +1099,11 @@ public final class PeerExpiringStoryListContext {
|
||||
return self.items.contains(where: { $0.id > self.maxReadId && $0.isCloseFriends })
|
||||
}
|
||||
|
||||
public init(items: [Item], isCached: Bool, maxReadId: Int32) {
|
||||
public init(items: [Item], isCached: Bool, maxReadId: Int32, isLoading: Bool) {
|
||||
self.items = items
|
||||
self.isCached = isCached
|
||||
self.maxReadId = maxReadId
|
||||
self.isLoading = isLoading
|
||||
}
|
||||
|
||||
public static func ==(lhs: State, rhs: State) -> Bool {
|
||||
@ -1133,6 +1116,9 @@ public final class PeerExpiringStoryListContext {
|
||||
if lhs.maxReadId != rhs.maxReadId {
|
||||
return false
|
||||
}
|
||||
if lhs.isLoading != rhs.isLoading {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1174,14 +1160,7 @@ public func _internal_pollPeerStories(postbox: Postbox, network: Network, accoun
|
||||
updatedPeerEntries.removeAll()
|
||||
|
||||
if let result = result, case let .userStories(stories, users) = result {
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
|
||||
switch stories {
|
||||
case let .userStories(_, userId, maxReadId, stories):
|
||||
@ -1201,15 +1180,12 @@ public func _internal_pollPeerStories(postbox: Postbox, network: Network, accoun
|
||||
}
|
||||
}
|
||||
|
||||
transaction.setPeerStoryState(peerId: peerId, state: CodableEntry(Stories.PeerState(
|
||||
transaction.setPeerStoryState(peerId: peerId, state: Stories.PeerState(
|
||||
maxReadId: maxReadId ?? 0
|
||||
)))
|
||||
).postboxRepresentation)
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
|
||||
transaction.setStoryItems(peerId: peerId, items: updatedPeerEntries)
|
||||
|
@ -498,15 +498,15 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func addBotToAttachMenu(botId: PeerId, allowWrite: Bool) -> Signal<Bool, AddBotToAttachMenuError> {
|
||||
return _internal_addBotToAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId, allowWrite: allowWrite)
|
||||
return _internal_addBotToAttachMenu(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId, allowWrite: allowWrite)
|
||||
}
|
||||
|
||||
public func removeBotFromAttachMenu(botId: PeerId) -> Signal<Bool, NoError> {
|
||||
return _internal_removeBotFromAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId)
|
||||
return _internal_removeBotFromAttachMenu(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId)
|
||||
}
|
||||
|
||||
public func getAttachMenuBot(botId: PeerId, cached: Bool = false) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
|
||||
return _internal_getAttachMenuBot(postbox: self.account.postbox, network: self.account.network, botId: botId, cached: cached)
|
||||
return _internal_getAttachMenuBot(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId, cached: cached)
|
||||
}
|
||||
|
||||
public func attachMenuBots() -> Signal<[AttachMenuBot], NoError> {
|
||||
|
@ -247,7 +247,7 @@ func _internal_fetchBotPaymentInvoice(postbox: Postbox, network: Network, source
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: BotPaymentInvoiceSource, themeParams: [String: Any]?) -> Signal<BotPaymentForm, BotPaymentFormRequestError> {
|
||||
func _internal_fetchBotPaymentForm(accountPeerId: PeerId, postbox: Postbox, network: Network, source: BotPaymentInvoiceSource, themeParams: [String: Any]?) -> Signal<BotPaymentForm, BotPaymentFormRequestError> {
|
||||
return postbox.transaction { transaction -> Api.InputInvoice? in
|
||||
switch source {
|
||||
case let .message(messageId):
|
||||
@ -286,14 +286,8 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B
|
||||
let _ = description
|
||||
let _ = photo
|
||||
|
||||
var peers: [Peer] = []
|
||||
for user in apiUsers {
|
||||
let parsed = TelegramUser(user: user)
|
||||
peers.append(parsed)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
var parsedNativeProvider: BotPaymentNativeProvider?
|
||||
@ -577,6 +571,7 @@ public enum RequestBotPaymentReceiptError {
|
||||
}
|
||||
|
||||
func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId) -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
@ -594,11 +589,8 @@ func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId)
|
||||
return account.postbox.transaction { transaction -> BotPaymentReceipt in
|
||||
switch result {
|
||||
case let .paymentReceipt(_, _, botId, _, title, description, photo, invoice, info, shipping, tipAmount, currency, totalAmount, credentialsTitle, users):
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in return updated })
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
let parsedInfo = info.flatMap(BotPaymentRequestedInfo.init)
|
||||
|
@ -19,7 +19,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func fetchBotPaymentForm(source: BotPaymentInvoiceSource, themeParams: [String: Any]?) -> Signal<BotPaymentForm, BotPaymentFormRequestError> {
|
||||
return _internal_fetchBotPaymentForm(postbox: self.account.postbox, network: self.account.network, source: source, themeParams: themeParams)
|
||||
return _internal_fetchBotPaymentForm(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, source: source, themeParams: themeParams)
|
||||
}
|
||||
|
||||
public func validateBotPaymentForm(saveInfo: Bool, source: BotPaymentInvoiceSource, formInfo: BotPaymentRequestedInfo) -> Signal<BotPaymentValidatedFormInfo, ValidateBotPaymentFormError> {
|
||||
|
@ -136,6 +136,7 @@ public enum UpdateAddressNameError {
|
||||
}
|
||||
|
||||
func _internal_updateAddressName(account: Account, domain: AddressNameDomain, name: String?) -> Signal<Void, UpdateAddressNameError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<Void, UpdateAddressNameError> in
|
||||
switch domain {
|
||||
case .account:
|
||||
@ -145,10 +146,7 @@ func _internal_updateAddressName(account: Account, domain: AddressNameDomain, na
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, UpdateAddressNameError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
let user = TelegramUser(user: result)
|
||||
updatePeers(transaction: transaction, peers: [user], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: [result]))
|
||||
} |> mapError { _ -> UpdateAddressNameError in }
|
||||
}
|
||||
case let .peer(peerId):
|
||||
@ -165,8 +163,8 @@ func _internal_updateAddressName(account: Account, domain: AddressNameDomain, na
|
||||
if name != nil, let defaultBannedRights = updatedPeer.defaultBannedRights {
|
||||
updatedPeer = updatedPeer.withUpdatedDefaultBannedRights(TelegramChatBannedRights(flags: defaultBannedRights.flags.union([.banPinMessages, .banChangeInfo]), untilDate: Int32.max))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updated
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -211,7 +209,7 @@ func _internal_deactivateAllAddressNames(account: Account, peerId: EnginePeer.Id
|
||||
updatedNames.append(TelegramPeerUsername(flags: updatedFlags, username: username.username))
|
||||
}
|
||||
let updatedUser = peer.withUpdatedAddressNames(updatedNames)
|
||||
updatePeers(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -289,7 +287,7 @@ func _internal_toggleAddressNameActive(account: Account, domain: AddressNameDoma
|
||||
updatedNames.insert(updatedName, at: updatedIndex)
|
||||
}
|
||||
let updatedUser = peer.withUpdatedUsernames(updatedNames)
|
||||
updatePeers(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -347,7 +345,7 @@ func _internal_toggleAddressNameActive(account: Account, domain: AddressNameDoma
|
||||
updatedNames.insert(updatedName, at: updatedIndex)
|
||||
}
|
||||
let updatedPeer = peer.withUpdatedAddressNames(updatedNames)
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -408,7 +406,7 @@ func _internal_toggleAddressNameActive(account: Account, domain: AddressNameDoma
|
||||
updatedNames.insert(updatedName, at: updatedIndex)
|
||||
}
|
||||
let updatedPeer = peer.withUpdatedAddressNames(updatedNames)
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -439,7 +437,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain,
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if case .boolTrue = result, let peer = transaction.getPeer(account.peerId) as? TelegramUser {
|
||||
let updatedUser = peer.withUpdatedUsernames(names)
|
||||
updatePeers(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedUser], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -455,7 +453,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain,
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if case .boolTrue = result, let peer = transaction.getPeer(peerId) as? TelegramChannel {
|
||||
let updatedPeer = peer.withUpdatedAddressNames(names)
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -474,7 +472,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain,
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if case .boolTrue = result, let peer = transaction.getPeer(peerId) as? TelegramChannel {
|
||||
let updatedPeer = peer.withUpdatedAddressNames(names)
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -521,28 +519,28 @@ func _internal_adminedPublicChannels(account: Account, scope: AdminedPublicChann
|
||||
flags |= (1 << 2)
|
||||
}
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.network.request(Api.functions.channels.getAdminedPublicChannels(flags: flags))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<[Peer], NoError> in
|
||||
var peers: [Peer] = []
|
||||
switch result {
|
||||
case let .chats(apiChats):
|
||||
for chat in apiChats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
case let .chatsSlice(_, apiChats):
|
||||
for chat in apiChats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
}
|
||||
return account.postbox.transaction { transaction -> [Peer] in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
let chats: [Api.Chat]
|
||||
let parsedPeers: AccumulatedPeers
|
||||
switch result {
|
||||
case let .chats(apiChats):
|
||||
chats = apiChats
|
||||
case let .chatsSlice(_, apiChats):
|
||||
chats = apiChats
|
||||
}
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let peer = transaction.getPeer(chat.peerId) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
return peers
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ public final class ChannelAdminEventLogContext {
|
||||
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let accountPeerId: PeerId
|
||||
private let peerId: PeerId
|
||||
|
||||
private var filter: ChannelAdminEventLogFilter = ChannelAdminEventLogFilter()
|
||||
@ -98,10 +99,11 @@ public final class ChannelAdminEventLogContext {
|
||||
|
||||
private let loadMoreDisposable = MetaDisposable()
|
||||
|
||||
init(postbox: Postbox, network: Network, peerId: PeerId) {
|
||||
init(postbox: Postbox, network: Network, peerId: PeerId, accountPeerId: PeerId) {
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.peerId = peerId
|
||||
self.accountPeerId = accountPeerId
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -166,7 +168,7 @@ public final class ChannelAdminEventLogContext {
|
||||
}
|
||||
|
||||
self.loadingMoreEarlier = true
|
||||
self.loadMoreDisposable.set((channelAdminLogEvents(postbox: self.postbox, network: self.network, peerId: self.peerId, maxId: maxId, minId: AdminLogEventId.min, limit: 100, query: self.filter.query, filter: self.filter.events, admins: self.filter.adminPeerIds)
|
||||
self.loadMoreDisposable.set((channelAdminLogEvents(accountPeerId: self.accountPeerId, postbox: self.postbox, network: self.network, peerId: self.peerId, maxId: maxId, minId: AdminLogEventId.min, limit: 100, query: self.filter.query, filter: self.filter.events, admins: self.filter.adminPeerIds)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
var events = result.events.sorted()
|
||||
|
@ -139,7 +139,7 @@ private func boolFromApiValue(_ value: Api.Bool) -> Bool {
|
||||
}
|
||||
}
|
||||
|
||||
func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
|
||||
func channelAdminLogEvents(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
|
||||
return postbox.transaction { transaction -> (Peer?, [Peer]?) in
|
||||
return (transaction.getPeer(peerId), admins?.compactMap { transaction.getPeer($0) })
|
||||
}
|
||||
@ -157,213 +157,214 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
|
||||
if let _ = inputAdmins {
|
||||
flags += Int32(1 << 1)
|
||||
}
|
||||
return network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query ?? "", eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> mapToSignal { result in
|
||||
|
||||
return network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query ?? "", eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit))
|
||||
|> mapToSignal { result in
|
||||
switch result {
|
||||
case let .adminLogResults(apiEvents, apiChats, apiUsers):
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for apiChat in apiChats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: apiChat) {
|
||||
return postbox.transaction { transaction -> AdminLogEventsResult in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for apiChat in apiChats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: apiChat) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
for apiUser in apiUsers {
|
||||
let peer = TelegramUser(user: apiUser)
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
for apiUser in apiUsers {
|
||||
let peer = TelegramUser(user: apiUser)
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
|
||||
var events: [AdminLogEvent] = []
|
||||
|
||||
for event in apiEvents {
|
||||
switch event {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: apiChats, users: apiUsers)
|
||||
|
||||
var events: [AdminLogEvent] = []
|
||||
|
||||
for event in apiEvents {
|
||||
switch event {
|
||||
case let .channelAdminLogEvent(id, date, userId, apiAction):
|
||||
var action: AdminLogEventAction?
|
||||
switch apiAction {
|
||||
case let .channelAdminLogEventActionChangeTitle(prev, new):
|
||||
action = .changeTitle(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeAbout(prev, new):
|
||||
action = .changeAbout(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeUsername(prev, new):
|
||||
action = .changeUsername(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangePhoto(prev, new):
|
||||
let previousImage = telegramMediaImageFromApiPhoto(prev)
|
||||
let newImage = telegramMediaImageFromApiPhoto(new)
|
||||
action = .changePhoto(prev: (previousImage?.representations ?? [], previousImage?.videoRepresentations ?? []) , new: (newImage?.representations ?? [], newImage?.videoRepresentations ?? []))
|
||||
case let .channelAdminLogEventActionToggleInvites(new):
|
||||
action = .toggleInvites(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionToggleSignatures(new):
|
||||
action = .toggleSignatures(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionUpdatePinned(new):
|
||||
switch new {
|
||||
case .messageEmpty:
|
||||
action = .updatePinned(nil)
|
||||
default:
|
||||
if let message = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .updatePinned(rendered)
|
||||
}
|
||||
}
|
||||
case let .channelAdminLogEventActionEditMessage(prev, new):
|
||||
if let prev = StoreMessage(apiMessage: prev, peerIsForum: peer.isForum), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
|
||||
action = .editMessage(prev: prevRendered, new: newRendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .deleteMessage(rendered)
|
||||
}
|
||||
case .channelAdminLogEventActionParticipantJoin:
|
||||
action = .participantJoin
|
||||
case .channelAdminLogEventActionParticipantLeave:
|
||||
action = .participantLeave
|
||||
case let .channelAdminLogEventActionParticipantInvite(participant):
|
||||
let participant = ChannelParticipant(apiParticipant: participant)
|
||||
|
||||
if let peer = peers[participant.peerId] {
|
||||
action = .participantInvite(RenderedChannelParticipant(participant: participant, peer: peer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleBan(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleBan(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleAdmin(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleAdmin(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeStickerSet(prevStickerset, newStickerset):
|
||||
action = .changeStickerPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset))
|
||||
case let .channelAdminLogEventActionTogglePreHistoryHidden(value):
|
||||
action = .togglePreHistoryHidden(value == .boolTrue)
|
||||
case let .channelAdminLogEventActionDefaultBannedRights(prevBannedRights, newBannedRights):
|
||||
action = .updateDefaultBannedRights(prev: TelegramChatBannedRights(apiBannedRights: prevBannedRights), new: TelegramChatBannedRights(apiBannedRights: newBannedRights))
|
||||
case let .channelAdminLogEventActionStopPoll(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .pollStopped(rendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeLinkedChat(prevValue, newValue):
|
||||
action = .linkedPeerUpdated(previous: prevValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(prevValue))], updated: newValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(newValue))])
|
||||
case let .channelAdminLogEventActionChangeLocation(prevValue, newValue):
|
||||
action = .changeGeoLocation(previous: PeerGeoLocation(apiLocation: prevValue), updated: PeerGeoLocation(apiLocation: newValue))
|
||||
case let .channelAdminLogEventActionToggleSlowMode(prevValue, newValue):
|
||||
action = .updateSlowmode(previous: prevValue == 0 ? nil : prevValue, updated: newValue == 0 ? nil : newValue)
|
||||
case .channelAdminLogEventActionStartGroupCall:
|
||||
action = .startGroupCall
|
||||
case .channelAdminLogEventActionDiscardGroupCall:
|
||||
action = .endGroupCall
|
||||
case let .channelAdminLogEventActionParticipantMute(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantMuteStatus(peerId: parsedParticipant.peerId, isMuted: true)
|
||||
case let .channelAdminLogEventActionParticipantUnmute(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantMuteStatus(peerId: parsedParticipant.peerId, isMuted: false)
|
||||
case let .channelAdminLogEventActionToggleGroupCallSetting(joinMuted):
|
||||
action = .updateGroupCallSettings(joinMuted: joinMuted == .boolTrue)
|
||||
case let .channelAdminLogEventActionExportedInviteDelete(invite):
|
||||
action = .deleteExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
||||
case let .channelAdminLogEventActionExportedInviteRevoke(invite):
|
||||
action = .revokeExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
||||
case let .channelAdminLogEventActionExportedInviteEdit(prevInvite, newInvite):
|
||||
action = .editExportedInvitation(previous: ExportedInvitation(apiExportedInvite: prevInvite), updated: ExportedInvitation(apiExportedInvite: newInvite))
|
||||
case let .channelAdminLogEventActionParticipantJoinByInvite(flags, invite):
|
||||
action = .participantJoinedViaInvite(invitation: ExportedInvitation(apiExportedInvite: invite), joinedViaFolderLink: (flags & (1 << 0)) != 0)
|
||||
case let .channelAdminLogEventActionParticipantVolume(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantVolume(peerId: parsedParticipant.peerId, volume: parsedParticipant.volume ?? 10000)
|
||||
case let .channelAdminLogEventActionChangeHistoryTTL(prevValue, newValue):
|
||||
action = .changeHistoryTTL(previousValue: prevValue, updatedValue: newValue)
|
||||
case let .channelAdminLogEventActionParticipantJoinByRequest(invite, approvedBy):
|
||||
action = .participantJoinByRequest(invitation: ExportedInvitation(apiExportedInvite: invite), approvedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(approvedBy)))
|
||||
case let .channelAdminLogEventActionToggleNoForwards(new):
|
||||
action = .toggleCopyProtection(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionSendMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .sendMessage(rendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue):
|
||||
action = .changeAvailableReactions(previousValue: PeerAllowedReactions(apiReactions: prevValue), updatedValue: PeerAllowedReactions(apiReactions: newValue))
|
||||
case let .channelAdminLogEventActionChangeUsernames(prevValue, newValue):
|
||||
action = .changeUsernames(prev: prevValue, new: newValue)
|
||||
case let .channelAdminLogEventActionCreateTopic(topic):
|
||||
switch topic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
action = .createTopic(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor))
|
||||
case .forumTopicDeleted:
|
||||
action = .createTopic(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0))
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteTopic(topic):
|
||||
switch topic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
action = .deleteTopic(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor))
|
||||
case .forumTopicDeleted:
|
||||
action = .deleteTopic(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0))
|
||||
}
|
||||
case let .channelAdminLogEventActionEditTopic(prevTopic, newTopic):
|
||||
let prevInfo: AdminLogEventAction.ForumTopicInfo
|
||||
switch prevTopic {
|
||||
case let .forumTopic(flags, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
prevInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor), isClosed: (flags & (1 << 2)) != 0, isHidden: (flags & (1 << 6)) != 0)
|
||||
case .forumTopicDeleted:
|
||||
prevInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0), isClosed: false, isHidden: false)
|
||||
case let .channelAdminLogEventActionChangeTitle(prev, new):
|
||||
action = .changeTitle(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeAbout(prev, new):
|
||||
action = .changeAbout(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeUsername(prev, new):
|
||||
action = .changeUsername(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangePhoto(prev, new):
|
||||
let previousImage = telegramMediaImageFromApiPhoto(prev)
|
||||
let newImage = telegramMediaImageFromApiPhoto(new)
|
||||
action = .changePhoto(prev: (previousImage?.representations ?? [], previousImage?.videoRepresentations ?? []) , new: (newImage?.representations ?? [], newImage?.videoRepresentations ?? []))
|
||||
case let .channelAdminLogEventActionToggleInvites(new):
|
||||
action = .toggleInvites(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionToggleSignatures(new):
|
||||
action = .toggleSignatures(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionUpdatePinned(new):
|
||||
switch new {
|
||||
case .messageEmpty:
|
||||
action = .updatePinned(nil)
|
||||
default:
|
||||
if let message = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .updatePinned(rendered)
|
||||
}
|
||||
}
|
||||
case let .channelAdminLogEventActionEditMessage(prev, new):
|
||||
if let prev = StoreMessage(apiMessage: prev, peerIsForum: peer.isForum), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new, peerIsForum: peer.isForum), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
|
||||
action = .editMessage(prev: prevRendered, new: newRendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .deleteMessage(rendered)
|
||||
}
|
||||
case .channelAdminLogEventActionParticipantJoin:
|
||||
action = .participantJoin
|
||||
case .channelAdminLogEventActionParticipantLeave:
|
||||
action = .participantLeave
|
||||
case let .channelAdminLogEventActionParticipantInvite(participant):
|
||||
let participant = ChannelParticipant(apiParticipant: participant)
|
||||
|
||||
let newInfo: AdminLogEventAction.ForumTopicInfo
|
||||
switch newTopic {
|
||||
case let .forumTopic(flags, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
newInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor), isClosed: (flags & (1 << 2)) != 0, isHidden: (flags & (1 << 6)) != 0)
|
||||
case .forumTopicDeleted:
|
||||
newInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0), isClosed: false, isHidden: false)
|
||||
}
|
||||
if let peer = peers[participant.peerId] {
|
||||
action = .participantInvite(RenderedChannelParticipant(participant: participant, peer: peer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleBan(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
action = .editTopic(prevInfo: prevInfo, newInfo: newInfo)
|
||||
case let .channelAdminLogEventActionPinTopic(_, prevTopic, newTopic):
|
||||
let prevInfo: EngineMessageHistoryThread.Info?
|
||||
switch prevTopic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
prevInfo = EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor)
|
||||
case .forumTopicDeleted:
|
||||
prevInfo = EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0)
|
||||
case .none:
|
||||
prevInfo = nil
|
||||
}
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleBan(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleAdmin(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
let newInfo: EngineMessageHistoryThread.Info?
|
||||
switch newTopic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
newInfo = EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor)
|
||||
case .forumTopicDeleted:
|
||||
newInfo = EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0)
|
||||
case .none:
|
||||
newInfo = nil
|
||||
}
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleAdmin(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeStickerSet(prevStickerset, newStickerset):
|
||||
action = .changeStickerPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset))
|
||||
case let .channelAdminLogEventActionTogglePreHistoryHidden(value):
|
||||
action = .togglePreHistoryHidden(value == .boolTrue)
|
||||
case let .channelAdminLogEventActionDefaultBannedRights(prevBannedRights, newBannedRights):
|
||||
action = .updateDefaultBannedRights(prev: TelegramChatBannedRights(apiBannedRights: prevBannedRights), new: TelegramChatBannedRights(apiBannedRights: newBannedRights))
|
||||
case let .channelAdminLogEventActionStopPoll(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .pollStopped(rendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeLinkedChat(prevValue, newValue):
|
||||
action = .linkedPeerUpdated(previous: prevValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(prevValue))], updated: newValue == 0 ? nil : peers[PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(newValue))])
|
||||
case let .channelAdminLogEventActionChangeLocation(prevValue, newValue):
|
||||
action = .changeGeoLocation(previous: PeerGeoLocation(apiLocation: prevValue), updated: PeerGeoLocation(apiLocation: newValue))
|
||||
case let .channelAdminLogEventActionToggleSlowMode(prevValue, newValue):
|
||||
action = .updateSlowmode(previous: prevValue == 0 ? nil : prevValue, updated: newValue == 0 ? nil : newValue)
|
||||
case .channelAdminLogEventActionStartGroupCall:
|
||||
action = .startGroupCall
|
||||
case .channelAdminLogEventActionDiscardGroupCall:
|
||||
action = .endGroupCall
|
||||
case let .channelAdminLogEventActionParticipantMute(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantMuteStatus(peerId: parsedParticipant.peerId, isMuted: true)
|
||||
case let .channelAdminLogEventActionParticipantUnmute(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantMuteStatus(peerId: parsedParticipant.peerId, isMuted: false)
|
||||
case let .channelAdminLogEventActionToggleGroupCallSetting(joinMuted):
|
||||
action = .updateGroupCallSettings(joinMuted: joinMuted == .boolTrue)
|
||||
case let .channelAdminLogEventActionExportedInviteDelete(invite):
|
||||
action = .deleteExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
||||
case let .channelAdminLogEventActionExportedInviteRevoke(invite):
|
||||
action = .revokeExportedInvitation(ExportedInvitation(apiExportedInvite: invite))
|
||||
case let .channelAdminLogEventActionExportedInviteEdit(prevInvite, newInvite):
|
||||
action = .editExportedInvitation(previous: ExportedInvitation(apiExportedInvite: prevInvite), updated: ExportedInvitation(apiExportedInvite: newInvite))
|
||||
case let .channelAdminLogEventActionParticipantJoinByInvite(flags, invite):
|
||||
action = .participantJoinedViaInvite(invitation: ExportedInvitation(apiExportedInvite: invite), joinedViaFolderLink: (flags & (1 << 0)) != 0)
|
||||
case let .channelAdminLogEventActionParticipantVolume(participant):
|
||||
let parsedParticipant = GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(participant)
|
||||
action = .groupCallUpdateParticipantVolume(peerId: parsedParticipant.peerId, volume: parsedParticipant.volume ?? 10000)
|
||||
case let .channelAdminLogEventActionChangeHistoryTTL(prevValue, newValue):
|
||||
action = .changeHistoryTTL(previousValue: prevValue, updatedValue: newValue)
|
||||
case let .channelAdminLogEventActionParticipantJoinByRequest(invite, approvedBy):
|
||||
action = .participantJoinByRequest(invitation: ExportedInvitation(apiExportedInvite: invite), approvedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(approvedBy)))
|
||||
case let .channelAdminLogEventActionToggleNoForwards(new):
|
||||
action = .toggleCopyProtection(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionSendMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message, peerIsForum: peer.isForum), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .sendMessage(rendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue):
|
||||
action = .changeAvailableReactions(previousValue: PeerAllowedReactions(apiReactions: prevValue), updatedValue: PeerAllowedReactions(apiReactions: newValue))
|
||||
case let .channelAdminLogEventActionChangeUsernames(prevValue, newValue):
|
||||
action = .changeUsernames(prev: prevValue, new: newValue)
|
||||
case let .channelAdminLogEventActionCreateTopic(topic):
|
||||
switch topic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
action = .createTopic(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor))
|
||||
case .forumTopicDeleted:
|
||||
action = .createTopic(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0))
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteTopic(topic):
|
||||
switch topic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
action = .deleteTopic(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor))
|
||||
case .forumTopicDeleted:
|
||||
action = .deleteTopic(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0))
|
||||
}
|
||||
case let .channelAdminLogEventActionEditTopic(prevTopic, newTopic):
|
||||
let prevInfo: AdminLogEventAction.ForumTopicInfo
|
||||
switch prevTopic {
|
||||
case let .forumTopic(flags, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
prevInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor), isClosed: (flags & (1 << 2)) != 0, isHidden: (flags & (1 << 6)) != 0)
|
||||
case .forumTopicDeleted:
|
||||
prevInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0), isClosed: false, isHidden: false)
|
||||
}
|
||||
|
||||
action = .pinTopic(prevInfo: prevInfo, newInfo: newInfo)
|
||||
case let .channelAdminLogEventActionToggleForum(newValue):
|
||||
action = .toggleForum(isForum: newValue == .boolTrue)
|
||||
case let .channelAdminLogEventActionToggleAntiSpam(newValue):
|
||||
action = .toggleAntiSpam(isEnabled: newValue == .boolTrue)
|
||||
let newInfo: AdminLogEventAction.ForumTopicInfo
|
||||
switch newTopic {
|
||||
case let .forumTopic(flags, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
newInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor), isClosed: (flags & (1 << 2)) != 0, isHidden: (flags & (1 << 6)) != 0)
|
||||
case .forumTopicDeleted:
|
||||
newInfo = AdminLogEventAction.ForumTopicInfo(info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0), isClosed: false, isHidden: false)
|
||||
}
|
||||
|
||||
action = .editTopic(prevInfo: prevInfo, newInfo: newInfo)
|
||||
case let .channelAdminLogEventActionPinTopic(_, prevTopic, newTopic):
|
||||
let prevInfo: EngineMessageHistoryThread.Info?
|
||||
switch prevTopic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
prevInfo = EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor)
|
||||
case .forumTopicDeleted:
|
||||
prevInfo = EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0)
|
||||
case .none:
|
||||
prevInfo = nil
|
||||
}
|
||||
|
||||
let newInfo: EngineMessageHistoryThread.Info?
|
||||
switch newTopic {
|
||||
case let .forumTopic(_, _, _, title, iconColor, iconEmojiId, _, _, _, _, _, _, _, _, _):
|
||||
newInfo = EngineMessageHistoryThread.Info(title: title, icon: iconEmojiId, iconColor: iconColor)
|
||||
case .forumTopicDeleted:
|
||||
newInfo = EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0)
|
||||
case .none:
|
||||
newInfo = nil
|
||||
}
|
||||
|
||||
action = .pinTopic(prevInfo: prevInfo, newInfo: newInfo)
|
||||
case let .channelAdminLogEventActionToggleForum(newValue):
|
||||
action = .toggleForum(isForum: newValue == .boolTrue)
|
||||
case let .channelAdminLogEventActionToggleAntiSpam(newValue):
|
||||
action = .toggleAntiSpam(isEnabled: newValue == .boolTrue)
|
||||
}
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
|
||||
if let action = action {
|
||||
events.append(AdminLogEvent(id: id, peerId: peerId, date: date, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> AdminLogEventsResult in
|
||||
updatePeers(transaction: transaction, peers: peers.map { $0.1 }, update: { return $1 })
|
||||
var peers = peers
|
||||
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
if peers[peerId] == nil, let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
return AdminLogEventsResult(peerId: peerId, peers: peers, events: events)
|
||||
} |> castError(MTRpcError.self)
|
||||
}
|
||||
|> castError(MTRpcError.self)
|
||||
}
|
||||
|
||||
} |> mapError {_ in return .generic}
|
||||
}
|
||||
|> mapError {_ in return .generic}
|
||||
}
|
||||
|
||||
return .complete()
|
||||
|
@ -168,11 +168,11 @@ func _internal_updateDefaultChannelMemberBannedRights(account: Account, peerId:
|
||||
return
|
||||
}
|
||||
if let peer = peer as? TelegramGroup {
|
||||
updatePeers(transaction: transaction, peers: [peer.updateDefaultBannedRights(rights, version: peer.version)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.updateDefaultBannedRights(rights, version: peer.version)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
} else if let peer = peer as? TelegramChannel {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedDefaultBannedRights(rights)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedDefaultBannedRights(rights)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
@ -90,25 +90,17 @@ func _internal_channelMembers(postbox: Postbox, network: Network, accountPeerId:
|
||||
var items: [RenderedChannelParticipant] = []
|
||||
switch result {
|
||||
case let .channelParticipants(_, participants, chats, users):
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var presences: [PeerId: Api.User] = [:]
|
||||
for user in users {
|
||||
let peer = TelegramUser(user: user)
|
||||
peers[peer.id] = peer
|
||||
presences[peer.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
for id in parsedPeers.allIds {
|
||||
if let peer = transaction.getPeer(id) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: presences)
|
||||
|
||||
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
|
||||
if let peer = peers[participant.peerId] {
|
||||
if let peer = parsedPeers.get(participant.peerId) {
|
||||
var renderedPresences: [PeerId: PeerPresence] = [:]
|
||||
if let presence = transaction.getPeerPresence(peerId: participant.peerId) {
|
||||
renderedPresences[participant.peerId] = presence
|
||||
|
@ -617,13 +617,7 @@ private func requestChatListFilters(accountPeerId: PeerId, postbox: Postbox, net
|
||||
}
|
||||
|> mapToSignal { users -> Signal<Never, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
@ -641,18 +635,12 @@ private func requestChatListFilters(accountPeerId: PeerId, postbox: Postbox, net
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let result = result {
|
||||
var peers: [Peer] = []
|
||||
let parsedPeers: AccumulatedPeers
|
||||
switch result {
|
||||
case .chats(let chats), .chatsSlice(_, let chats):
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
@ -671,18 +659,12 @@ private func requestChatListFilters(accountPeerId: PeerId, postbox: Postbox, net
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let result = result {
|
||||
var peers: [Peer] = []
|
||||
let parsedPeers: AccumulatedPeers
|
||||
switch result {
|
||||
case .chats(let chats), .chatsSlice(_, let chats):
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
@ -737,24 +719,15 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
|
||||
let parsedPeers: AccumulatedPeers
|
||||
|
||||
switch result {
|
||||
case let .peerDialogs(dialogs, messages, chats, users, _):
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
var topMessageIds = Set<MessageId>()
|
||||
|
||||
@ -833,15 +806,10 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
}
|
||||
}
|
||||
|
||||
var peerMap: [PeerId: Peer] = [:]
|
||||
for peer in peers {
|
||||
peerMap[peer.id] = peer
|
||||
}
|
||||
|
||||
var storeMessages: [StoreMessage] = []
|
||||
for message in messages {
|
||||
var peerIsForum = false
|
||||
if let peerId = message.peerId, let peer = peerMap[peerId], peer.isForum {
|
||||
if let peerId = message.peerId, let peer = parsedPeers.get(peerId), peer.isForum {
|
||||
peerIsForum = true
|
||||
}
|
||||
if let storeMessage = StoreMessage(apiMessage: message, peerIsForum: peerIsForum) {
|
||||
@ -864,11 +832,7 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
transaction.updateCurrentPeerNotificationSettings(notificationSettings)
|
||||
|
||||
|
@ -153,6 +153,7 @@ func _internal_exportChatFolder(account: Account, filterId: Int32, title: String
|
||||
}
|
||||
|
||||
func _internal_getExportedChatFolderLinks(account: Account, id: Int32) -> Signal<[ExportedChatFolderLink]?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.chatlists.getExportedInvites(chatlist: .inputChatlistDialogFilter(filterId: id)))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.chatlists.ExportedInvites?, NoError> in
|
||||
@ -165,24 +166,8 @@ func _internal_getExportedChatFolderLinks(account: Account, id: Int32) -> Signal
|
||||
return account.postbox.transaction { transaction -> [ExportedChatFolderLink]? in
|
||||
switch result {
|
||||
case let .exportedInvites(invites, chats, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var result: [ExportedChatFolderLink] = []
|
||||
for invite in invites {
|
||||
@ -280,6 +265,7 @@ public final class ChatFolderLinkContents {
|
||||
}
|
||||
|
||||
func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<ChatFolderLinkContents, CheckChatFolderLinkError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.chatlists.checkChatlistInvite(slug: slug))
|
||||
|> mapError { _ -> CheckChatFolderLinkError in
|
||||
return .generic
|
||||
@ -290,19 +276,10 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|
||||
case let .chatlistInvite(_, title, emoticon, peers, chats, users):
|
||||
let _ = emoticon
|
||||
|
||||
var allPeers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
var memberCounts: [PeerId: Int] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
allPeers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
allPeers.append(peer)
|
||||
}
|
||||
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _) = chat {
|
||||
if let participantsCount = participantsCount {
|
||||
memberCounts[chat.peerId] = Int(participantsCount)
|
||||
@ -310,10 +287,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: allPeers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var resultPeers: [EnginePeer] = []
|
||||
var alreadyMemberPeerIds = Set<EnginePeer.Id>()
|
||||
@ -329,19 +303,10 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|
||||
|
||||
return ChatFolderLinkContents(localFilterId: nil, title: title, peers: resultPeers, alreadyMemberPeerIds: alreadyMemberPeerIds, memberCounts: memberCounts)
|
||||
case let .chatlistInviteAlready(filterId, missingPeers, alreadyPeers, chats, users):
|
||||
var allPeers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
var memberCounts: [PeerId: Int] = [:]
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
allPeers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
allPeers.append(peer)
|
||||
}
|
||||
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _) = chat {
|
||||
if let participantsCount = participantsCount {
|
||||
memberCounts[chat.peerId] = Int(participantsCount)
|
||||
@ -349,10 +314,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: allPeers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let currentFilters = _internal_currentChatListFilters(transaction: transaction)
|
||||
var currentFilterTitle: String?
|
||||
@ -602,6 +564,7 @@ private struct FirstTimeFolderUpdatesKey: Hashable {
|
||||
private var firstTimeFolderUpdates = Set<FirstTimeFolderUpdatesKey>()
|
||||
|
||||
func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> Signal<Never, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> (ChatListFiltersState, AppConfiguration) in
|
||||
return (_internal_currentChatListFiltersState(transaction: transaction), currentAppConfiguration(transaction: transaction))
|
||||
}
|
||||
@ -654,19 +617,10 @@ func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> S
|
||||
switch result {
|
||||
case let .chatlistUpdates(missingPeers, chats, users):
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
var memberCounts: [ChatListFiltersState.ChatListFilterUpdates.MemberCount] = []
|
||||
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _) = chat {
|
||||
if let participantsCount = participantsCount {
|
||||
memberCounts.append(ChatListFiltersState.ChatListFilterUpdates.MemberCount(id: chat.peerId, count: participantsCount))
|
||||
@ -674,10 +628,7 @@ func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> S
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let _ = updateChatListFiltersState(transaction: transaction, { state in
|
||||
var state = state
|
||||
|
@ -3,35 +3,32 @@ import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
func _internal_findChannelById(postbox: Postbox, network: Network, channelId: Int64) -> Signal<Peer?, NoError> {
|
||||
func _internal_findChannelById(accountPeerId: PeerId, postbox: Postbox, network: Network, channelId: Int64) -> Signal<Peer?, NoError> {
|
||||
return network.request(Api.functions.channels.getChannels(id: [.inputChannel(channelId: channelId, accessHash: 0)]))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Chats?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Peer?, NoError> in
|
||||
guard let result = result else {
|
||||
return .single(nil)
|
||||
}
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
guard let result = result else {
|
||||
return nil
|
||||
}
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
case let .chats(apiChats):
|
||||
chats = apiChats
|
||||
case let .chatsSlice(_, apiChats):
|
||||
chats = apiChats
|
||||
}
|
||||
guard let chat = chats.first else {
|
||||
return .single(nil)
|
||||
}
|
||||
guard let peer = parseTelegramGroupOrChannel(chat: chat) else {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return peer
|
||||
}
|
||||
guard let id = chats.first?.peerId else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
return transaction.getPeer(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ private final class GroupsInCommonContextImpl {
|
||||
|
||||
let maxId = self.peers.last?.peerId.id
|
||||
let peerId = self.peerId
|
||||
let accountPeerId = self.account.peerId
|
||||
let network = self.account.network
|
||||
let postbox = self.account.postbox
|
||||
let signal: Signal<([Peer], Int), NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
@ -94,16 +95,15 @@ private final class GroupsInCommonContextImpl {
|
||||
|
||||
|
||||
return postbox.transaction { transaction -> ([Peer], Int) in
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
if let peer = transaction.getPeer(chat.peerId) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer? in
|
||||
return updated
|
||||
})
|
||||
|
||||
return (peers, count ?? 0)
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ public enum EditPeerExportedInvitationError {
|
||||
}
|
||||
|
||||
func _internal_editPeerExportedInvitation(account: Account, peerId: PeerId, link: String, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?) -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
var flags: Int32 = 0
|
||||
@ -144,14 +145,7 @@ func _internal_editPeerExportedInvitation(account: Account, peerId: PeerId, link
|
||||
|> mapToSignal { result -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
if case let .exportedChatInvite(invite, users) = result {
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
return ExportedInvitation(apiExportedInvite: invite)
|
||||
} else {
|
||||
return nil
|
||||
@ -176,6 +170,7 @@ public enum RevokeExportedInvitationResult {
|
||||
}
|
||||
|
||||
func _internal_revokePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal<RevokeExportedInvitationResult?, RevokePeerExportedInvitationError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<RevokeExportedInvitationResult?, RevokePeerExportedInvitationError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
let flags: Int32 = (1 << 2)
|
||||
@ -184,24 +179,10 @@ func _internal_revokePeerExportedInvitation(account: Account, peerId: PeerId, li
|
||||
|> mapToSignal { result -> Signal<RevokeExportedInvitationResult?, RevokePeerExportedInvitationError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
if case let .exportedChatInvite(invite, users) = result {
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
return .update(ExportedInvitation(apiExportedInvite: invite))
|
||||
} else if case let .exportedChatInviteReplaced(invite, newInvite, users) = result {
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
let previous = ExportedInvitation(apiExportedInvite: invite)
|
||||
let new = ExportedInvitation(apiExportedInvite: newInvite)
|
||||
@ -242,6 +223,7 @@ public struct ExportedInvitations : Equatable {
|
||||
}
|
||||
|
||||
func _internal_peerExportedInvitations(account: Account, peerId: PeerId, revoked: Bool, adminId: PeerId? = nil, offsetLink: ExportedInvitation? = nil) -> Signal<ExportedInvitations?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<ExportedInvitations?, NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let adminPeer = transaction.getPeer(adminId ?? account.peerId), let adminId = apiInputUser(adminPeer) {
|
||||
var flags: Int32 = 0
|
||||
@ -259,16 +241,8 @@ func _internal_peerExportedInvitations(account: Account, peerId: PeerId, revoked
|
||||
|> mapToSignal { result -> Signal<ExportedInvitations?, NoError> in
|
||||
return account.postbox.transaction { transaction -> ExportedInvitations? in
|
||||
if let result = result, case let .exportedChatInvites(count, apiInvites, users) = result {
|
||||
var peers: [Peer] = []
|
||||
var peersMap: [PeerId: Peer] = [:]
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peersMap[telegramUser.id] = telegramUser
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let invites = apiInvites.map { ExportedInvitation(apiExportedInvite: $0) }
|
||||
return ExportedInvitations(list: invites, totalCount: count)
|
||||
@ -447,6 +421,7 @@ private final class PeerExportedInvitationsContextImpl {
|
||||
}
|
||||
self.isLoadingMore = true
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let peerId = self.peerId
|
||||
let adminId = self.adminId
|
||||
let revoked = self.revoked
|
||||
@ -488,13 +463,7 @@ private final class PeerExportedInvitationsContextImpl {
|
||||
}
|
||||
switch result {
|
||||
case let .exportedChatInvites(count, invites, users):
|
||||
var peers: [Peer] = []
|
||||
for apiUser in users {
|
||||
peers.append(TelegramUser(user: apiUser))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
let invitations: [ExportedInvitation] = invites.compactMap { ExportedInvitation(apiExportedInvite: $0) }
|
||||
if populateCache {
|
||||
if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: count >= 50, count: count)) {
|
||||
@ -916,6 +885,7 @@ private final class PeerInvitationImportersContextImpl {
|
||||
}
|
||||
self.isLoadingMore = true
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
let peerId = self.peerId
|
||||
let link = self.link
|
||||
let populateCache = self.populateCache
|
||||
@ -968,13 +938,7 @@ private final class PeerInvitationImportersContextImpl {
|
||||
}
|
||||
switch result {
|
||||
case let .chatInviteImporters(count, importers, users):
|
||||
var peers: [Peer] = []
|
||||
for apiUser in users {
|
||||
peers.append(TelegramUser(user: apiUser))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
var resultImporters: [PeerInvitationImportersState.Importer] = []
|
||||
for importer in importers {
|
||||
let peerId: PeerId
|
||||
@ -1050,7 +1014,7 @@ private final class PeerInvitationImportersContextImpl {
|
||||
self.updateDisposables.add(self.account.postbox.transaction({ transaction in
|
||||
let peer = transaction.getPeer(self.peerId)
|
||||
if let peer = peer as? TelegramGroup {
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { current, _ in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { current, _ in
|
||||
var updated = current
|
||||
if let current = current as? TelegramGroup {
|
||||
updated = current.updateParticipantCount(current.participantCount + 1)
|
||||
@ -1167,6 +1131,7 @@ public struct ExportedInvitationCreator : Equatable {
|
||||
}
|
||||
|
||||
func _internal_peerExportedInvitationsCreators(account: Account, peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<[ExportedInvitationCreator], NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
var isCreator = false
|
||||
@ -1187,27 +1152,20 @@ func _internal_peerExportedInvitationsCreators(account: Account, peerId: PeerId)
|
||||
return account.postbox.transaction { transaction -> [ExportedInvitationCreator] in
|
||||
if let result = result, case let .chatAdminsWithInvites(admins, users) = result {
|
||||
var creators: [ExportedInvitationCreator] = []
|
||||
var peers: [Peer] = []
|
||||
var peersMap: [PeerId: Peer] = [:]
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peersMap[telegramUser.id] = telegramUser
|
||||
}
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users)
|
||||
|
||||
for admin in admins {
|
||||
switch admin {
|
||||
case let .chatAdminWithInvites(adminId, invitesCount, revokedInvitesCount):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId))
|
||||
if let peer = peersMap[peerId], peerId != account.peerId {
|
||||
if let peer = parsedPeers.get(peerId), peerId != account.peerId {
|
||||
creators.append(ExportedInvitationCreator(peer: RenderedPeer(peer: peer), count: invitesCount, revokedCount: revokedInvitesCount))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
return creators
|
||||
} else {
|
||||
|
@ -89,6 +89,7 @@ func _internal_joinChatInteractively(with hash: String, account: Account) -> Sig
|
||||
}
|
||||
|
||||
func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal<ExternalJoiningChatState, JoinLinkInfoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.messages.checkChatInvite(hash: hash), automaticFloodWait: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.ChatInvite?, JoinLinkInfoError> in
|
||||
@ -108,10 +109,8 @@ func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal<E
|
||||
case let .chatInviteAlready(chat):
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
return account.postbox.transaction({ (transaction) -> ExternalJoiningChatState in
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { (previous, updated) -> Peer? in
|
||||
return updated
|
||||
})
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [chat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
return .alreadyJoined(EnginePeer(peer))
|
||||
})
|
||||
|> castError(JoinLinkInfoError.self)
|
||||
@ -120,9 +119,8 @@ func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal<E
|
||||
case let .chatInvitePeek(chat, expires):
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
return account.postbox.transaction({ (transaction) -> ExternalJoiningChatState in
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { (previous, updated) -> Peer? in
|
||||
return updated
|
||||
})
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [chat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
return .peek(EnginePeer(peer), expires)
|
||||
})
|
||||
|
@ -8,7 +8,7 @@ public enum AvailableChannelDiscussionGroupError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_availableGroupsForChannelDiscussion(postbox: Postbox, network: Network) -> Signal<[Peer], AvailableChannelDiscussionGroupError> {
|
||||
func _internal_availableGroupsForChannelDiscussion(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<[Peer], AvailableChannelDiscussionGroupError> {
|
||||
return network.request(Api.functions.channels.getGroupsForDiscussion())
|
||||
|> mapError { error in
|
||||
return .generic
|
||||
@ -16,15 +16,17 @@ func _internal_availableGroupsForChannelDiscussion(postbox: Postbox, network: Ne
|
||||
|> mapToSignal { result -> Signal<[Peer], AvailableChannelDiscussionGroupError> in
|
||||
let chats: [Api.Chat]
|
||||
switch result {
|
||||
case let .chats(c):
|
||||
chats = c
|
||||
case let .chatsSlice(_, c):
|
||||
chats = c
|
||||
case let .chats(c):
|
||||
chats = c
|
||||
case let .chatsSlice(_, c):
|
||||
chats = c
|
||||
}
|
||||
|
||||
let peers = chats.compactMap(parseTelegramGroupOrChannel)
|
||||
return postbox.transaction { transation -> [Peer] in
|
||||
updatePeers(transaction: transation, peers: peers, update: { _, updated in updated })
|
||||
return postbox.transaction { transaction -> [Peer] in
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: [])
|
||||
let peers = chats.compactMap(parseTelegramGroupOrChannel)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
return peers
|
||||
}
|
||||
|> castError(AvailableChannelDiscussionGroupError.self)
|
||||
|
@ -18,7 +18,7 @@ public final class NotificationExceptionsList: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_notificationExceptionsList(postbox: Postbox, network: Network) -> Signal<NotificationExceptionsList, NoError> {
|
||||
func _internal_notificationExceptionsList(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<NotificationExceptionsList, NoError> {
|
||||
var flags: Int32 = 0
|
||||
flags |= 1 << 1
|
||||
flags |= 1 << 2
|
||||
@ -29,21 +29,18 @@ func _internal_notificationExceptionsList(postbox: Postbox, network: Network) ->
|
||||
return postbox.transaction { transaction -> NotificationExceptionsList in
|
||||
switch result {
|
||||
case let .updates(updates, users, chats, _, _):
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var settings: [PeerId: TelegramPeerNotificationSettings] = [:]
|
||||
|
||||
for user in users {
|
||||
let peer = TelegramUser(user: user)
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId,peers: parsedPeers)
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
for id in parsedPeers.allIds {
|
||||
if let peer = transaction.getPeer(id) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in updated })
|
||||
|
||||
for update in updates {
|
||||
switch update {
|
||||
case let .updateNotifySettings(apiPeer, notifySettings):
|
||||
|
@ -283,7 +283,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
||||
}
|
||||
return postbox.transaction { transaction -> (UpdatePeerPhotoStatus, MediaResource?, MediaResource?) in
|
||||
if let peer = transaction.getPeer(peer.id) {
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { (_, peer) -> Peer? in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { (_, peer) -> Peer? in
|
||||
if let peer = peer as? TelegramUser {
|
||||
if customPeerPhotoMode == .suggest || fallback {
|
||||
return peer
|
||||
@ -369,7 +369,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> (UpdatePeerPhotoStatus, MediaResource?, MediaResource?) in
|
||||
updatePeers(transaction: transaction, peers: [groupOrChannel], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [groupOrChannel], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
return (.complete(groupOrChannel.profileImageRepresentations), photoResult.resource, videoResult?.resource)
|
||||
@ -471,7 +471,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
||||
}
|
||||
return postbox.transaction { transaction -> UpdatePeerPhotoStatus in
|
||||
if let peer = transaction.getPeer(peer.id) {
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { (_, peer) -> Peer? in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer], update: { (_, peer) -> Peer? in
|
||||
if let peer = peer as? TelegramUser {
|
||||
if customPeerPhotoMode == .suggest || fallback {
|
||||
return peer
|
||||
@ -499,7 +499,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
||||
updatedUsers = apiUsers.map { TelegramUser(user: $0) }
|
||||
}
|
||||
return postbox.transaction { transaction -> UpdatePeerPhotoStatus in
|
||||
updatePeers(transaction: transaction, peers: updatedUsers, update: { (_, updatedPeer) -> Peer? in
|
||||
updatePeersCustom(transaction: transaction, peers: updatedUsers, update: { (_, updatedPeer) -> Peer? in
|
||||
return updatedPeer
|
||||
})
|
||||
if fallback {
|
||||
@ -542,7 +542,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
||||
if chat.peerId == peer.id {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
return postbox.transaction { transaction -> UpdatePeerPhotoStatus in
|
||||
updatePeers(transaction: transaction, peers: [groupOrChannel], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [groupOrChannel], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
|
||||
|
@ -65,18 +65,10 @@ func _internal_managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox
|
||||
return postbox.transaction { transaction -> Void in
|
||||
switch result {
|
||||
case let .topPeers(_, _, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { return $1 })
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: true, ids: peers.map { $0.id })) {
|
||||
if let entry = CodableEntry(CachedRecentPeers(enabled: true, ids: users.map { $0.peerId })) {
|
||||
transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry)
|
||||
}
|
||||
case .topPeersNotModified:
|
||||
@ -155,59 +147,52 @@ func _internal_updateRecentPeersEnabled(postbox: Postbox, network: Network, enab
|
||||
|
||||
func _internal_managedRecentlyUsedInlineBots(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
|
||||
let remotePeers = network.request(Api.functions.contacts.getTopPeers(flags: 1 << 2, offset: 0, limit: 16, hash: 0))
|
||||
|> retryRequest
|
||||
|> map { result -> ([Peer], [PeerId: Api.User], [(PeerId, Double)])? in
|
||||
switch result {
|
||||
case .topPeersDisabled:
|
||||
break
|
||||
case let .topPeers(categories, _, users):
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
var peersWithRating: [(PeerId, Double)] = []
|
||||
for category in categories {
|
||||
switch category {
|
||||
case let .topPeerCategoryPeers(_, _, topPeers):
|
||||
for topPeer in topPeers {
|
||||
switch topPeer {
|
||||
case let .topPeer(apiPeer, rating):
|
||||
peersWithRating.append((apiPeer.peerId, rating))
|
||||
}
|
||||
}
|
||||
|> retryRequest
|
||||
|> map { result -> (AccumulatedPeers, [(PeerId, Double)])? in
|
||||
switch result {
|
||||
case .topPeersDisabled:
|
||||
break
|
||||
case let .topPeers(categories, _, users):
|
||||
let parsedPeers = AccumulatedPeers(users: users)
|
||||
|
||||
var peersWithRating: [(PeerId, Double)] = []
|
||||
for category in categories {
|
||||
switch category {
|
||||
case let .topPeerCategoryPeers(_, _, topPeers):
|
||||
for topPeer in topPeers {
|
||||
switch topPeer {
|
||||
case let .topPeer(apiPeer, rating):
|
||||
peersWithRating.append((apiPeer.peerId, rating))
|
||||
}
|
||||
}
|
||||
return (peers, peerPresences, peersWithRating)
|
||||
case .topPeersNotModified:
|
||||
break
|
||||
}
|
||||
}
|
||||
return ([], [:], [])
|
||||
return (parsedPeers, peersWithRating)
|
||||
case .topPeersNotModified:
|
||||
break
|
||||
}
|
||||
return (AccumulatedPeers(), [])
|
||||
}
|
||||
|
||||
let updatedRemotePeers = remotePeers
|
||||
|> mapToSignal { peersAndPresences -> Signal<Void, NoError> in
|
||||
if let (peers, peerPresences, peersWithRating) = peersAndPresences {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { return $1 })
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
|
||||
let sortedPeersWithRating = peersWithRating.sorted(by: { $0.1 > $1.1 })
|
||||
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots, items: sortedPeersWithRating.compactMap { (peerId, rating) in
|
||||
if let entry = CodableEntry(RecentPeerItem(rating: rating)) {
|
||||
return OrderedItemListEntry(id: RecentPeerItemId(peerId).rawValue, contents: entry)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
|> mapToSignal { peersAndPresences -> Signal<Void, NoError> in
|
||||
if let (parsedPeers, peersWithRating) = peersAndPresences {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let sortedPeersWithRating = peersWithRating.sorted(by: { $0.1 > $1.1 })
|
||||
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots, items: sortedPeersWithRating.compactMap { (peerId, rating) in
|
||||
if let entry = CodableEntry(RecentPeerItem(rating: rating)) {
|
||||
return OrderedItemListEntry(id: RecentPeerItemId(peerId).rawValue, contents: entry)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
return updatedRemotePeers
|
||||
|
@ -15,7 +15,7 @@ func _internal_terminateSecretChat(transaction: Transaction, peerId: PeerId, req
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
@ -52,7 +52,7 @@ func _internal_removePeerChat(account: Account, transaction: Transaction, mediaB
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat {
|
||||
updatePeers(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmbeddedState(updatedState.embeddedState.peerState)], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32
|
||||
normalizedName = String(normalizedName[name.index(after: name.startIndex)...])
|
||||
}
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.postbox.transaction { transaction -> CachedResolvedByNamePeer? in
|
||||
return transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)))?.get(CachedResolvedByNamePeer.self)
|
||||
} |> mapToSignal { cachedEntry -> Signal<PeerId?, NoError> in
|
||||
@ -36,28 +38,14 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32
|
||||
var peerId: PeerId? = nil
|
||||
|
||||
switch result {
|
||||
case let .resolvedPeer(apiPeer, chats, users):
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers[user.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
case let .resolvedPeer(apiPeer, chats, users):
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
if let peer = peers[apiPeer.peerId] {
|
||||
peerId = peer.id
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
if let peer = parsedPeers.get(apiPeer.peerId) {
|
||||
peerId = peer.id
|
||||
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
@ -81,6 +69,8 @@ func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int
|
||||
normalizedPhone = String(normalizedPhone[normalizedPhone.index(after: normalizedPhone.startIndex)...])
|
||||
}
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.postbox.transaction { transaction -> CachedResolvedByPhonePeer? in
|
||||
return transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByPhonePeers, key: CachedResolvedByPhonePeer.key(name: normalizedPhone)))?.get(CachedResolvedByPhonePeer.self)
|
||||
} |> mapToSignal { cachedEntry -> Signal<PeerId?, NoError> in
|
||||
@ -98,26 +88,12 @@ func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int
|
||||
|
||||
switch result {
|
||||
case let .resolvedPeer(apiPeer, chats, users):
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers[user.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
if let peer = peers[apiPeer.peerId] {
|
||||
if let peer = parsedPeers.get(apiPeer.peerId) {
|
||||
peerId = peer.id
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ public struct FoundPeer: Equatable {
|
||||
}
|
||||
|
||||
func _internal_searchPeers(account: Account, query: String) -> Signal<([FoundPeer], [FoundPeer]), NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let searchResult = account.network.request(Api.functions.contacts.search(q: query, limit: 20), automaticFloodWait: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ in
|
||||
@ -31,37 +33,29 @@ func _internal_searchPeers(account: Account, query: String) -> Signal<([FoundPee
|
||||
switch result {
|
||||
case let .found(myResults, results, chats, users):
|
||||
return account.postbox.transaction { transaction -> ([FoundPeer], [FoundPeer]) in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var subscribers: [PeerId: Int32] = [:]
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers[user.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers[groupOrChannel.id] = groupOrChannel
|
||||
switch chat {
|
||||
/*feed*/
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
}
|
||||
default:
|
||||
break
|
||||
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _):
|
||||
if let participantsCount = participantsCount {
|
||||
subscribers[groupOrChannel.id] = participantsCount
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var renderedMyPeers: [FoundPeer] = []
|
||||
for result in myResults {
|
||||
let peerId: PeerId = result.peerId
|
||||
if let peer = peers[peerId] {
|
||||
if let peer = parsedPeers.get(peerId) {
|
||||
if let group = peer as? TelegramGroup, group.migrationReference != nil {
|
||||
continue
|
||||
}
|
||||
@ -72,7 +66,7 @@ func _internal_searchPeers(account: Account, query: String) -> Signal<([FoundPee
|
||||
var renderedPeers: [FoundPeer] = []
|
||||
for result in results {
|
||||
let peerId: PeerId = result.peerId
|
||||
if let peer = peers[peerId] {
|
||||
if let peer = parsedPeers.get(peerId) {
|
||||
if let group = peer as? TelegramGroup, group.migrationReference != nil {
|
||||
continue
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import MtProtoKit
|
||||
|
||||
|
||||
func _internal_supportPeerId(account: Account) -> Signal<PeerId?, NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
return account.network.request(Api.functions.help.getSupport())
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ in
|
||||
@ -13,14 +15,12 @@ func _internal_supportPeerId(account: Account) -> Signal<PeerId?, NoError> {
|
||||
|> mapToSignal { support -> Signal<PeerId?, NoError> in
|
||||
if let support = support {
|
||||
switch support {
|
||||
case let .support(phoneNumber: _, user: user):
|
||||
let user = TelegramUser(user: user)
|
||||
return account.postbox.transaction { transaction -> PeerId in
|
||||
updatePeers(transaction: transaction, peers: [user], update: { (previous, updated) -> Peer? in
|
||||
return updated
|
||||
})
|
||||
return user.id
|
||||
}
|
||||
case let .support(_, user):
|
||||
return account.postbox.transaction { transaction -> PeerId in
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: [user])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
return user.peerId
|
||||
}
|
||||
}
|
||||
}
|
||||
return .single(nil)
|
||||
|
@ -93,7 +93,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func findChannelById(channelId: Int64) -> Signal<EnginePeer?, NoError> {
|
||||
return _internal_findChannelById(postbox: self.account.postbox, network: self.account.network, channelId: channelId)
|
||||
return _internal_findChannelById(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, channelId: channelId)
|
||||
|> map { peer in
|
||||
return peer.flatMap(EnginePeer.init)
|
||||
}
|
||||
@ -132,7 +132,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func updatedRemotePeer(peer: PeerReference) -> Signal<Peer, UpdatedRemotePeerError> {
|
||||
return _internal_updatedRemotePeer(postbox: self.account.postbox, network: self.account.network, peer: peer)
|
||||
return _internal_updatedRemotePeer(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, peer: peer)
|
||||
}
|
||||
|
||||
public func chatOnlineMembers(peerId: PeerId) -> Signal<Int32, NoError> {
|
||||
@ -327,7 +327,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func channelAdminEventLog(peerId: PeerId) -> ChannelAdminEventLogContext {
|
||||
return ChannelAdminEventLogContext(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
|
||||
return ChannelAdminEventLogContext(postbox: self.account.postbox, network: self.account.network, peerId: peerId, accountPeerId: self.account.peerId)
|
||||
}
|
||||
|
||||
public func updateChannelMemberBannedRights(peerId: PeerId, memberId: PeerId, rights: TelegramChatBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> {
|
||||
@ -415,7 +415,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func availableGroupsForChannelDiscussion() -> Signal<[EnginePeer], AvailableChannelDiscussionGroupError> {
|
||||
return _internal_availableGroupsForChannelDiscussion(postbox: self.account.postbox, network: self.account.network)
|
||||
return _internal_availableGroupsForChannelDiscussion(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network)
|
||||
|> map { peers -> [EnginePeer] in
|
||||
return peers.map(EnginePeer.init)
|
||||
}
|
||||
@ -637,7 +637,7 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func notificationExceptionsList() -> Signal<NotificationExceptionsList, NoError> {
|
||||
return _internal_notificationExceptionsList(postbox: self.account.postbox, network: self.account.network)
|
||||
return _internal_notificationExceptionsList(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network)
|
||||
}
|
||||
|
||||
public func fetchAndUpdateCachedPeerData(peerId: PeerId) -> Signal<Bool, NoError> {
|
||||
|
@ -29,7 +29,7 @@ func _internal_updateBotName(account: Account, peerId: PeerId, name: String) ->
|
||||
return current
|
||||
}
|
||||
})
|
||||
updatePeers(transaction: transaction, peers: [peer]) { _, peer in
|
||||
updatePeersCustom(transaction: transaction, peers: [peer]) { _, peer in
|
||||
var updatedPeer = peer
|
||||
if let user = peer as? TelegramUser, user.firstName == previousBotName {
|
||||
updatedPeer = user.withUpdatedNames(firstName: name, lastName: nil)
|
||||
|
@ -78,30 +78,17 @@ func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, accountP
|
||||
return network.request(Api.functions.messages.getPeerSettings(peer: inputPeer))
|
||||
|> retryRequest
|
||||
|> mapToSignal { peerSettings -> Signal<Bool, NoError> in
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
|
||||
let peerStatusSettings: PeerStatusSettings
|
||||
switch peerSettings {
|
||||
return postbox.transaction { transaction -> Bool in
|
||||
let parsedPeers: AccumulatedPeers
|
||||
|
||||
let peerStatusSettings: PeerStatusSettings
|
||||
switch peerSettings {
|
||||
case let .peerSettings(settings, chats, users):
|
||||
peerStatusSettings = PeerStatusSettings(apiSettings: settings)
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
return postbox.transaction { transaction -> Bool in
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
|
||||
switch peer.id.namespace {
|
||||
@ -220,32 +207,18 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
switch result {
|
||||
case let .userFull(fullUser, chats, users):
|
||||
var accountUser: Api.User?
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let peer = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
for user in users {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
if telegramUser.id == accountPeerId {
|
||||
if user.peerId == accountPeerId {
|
||||
accountUser = user
|
||||
}
|
||||
}
|
||||
let _ = accountUser
|
||||
|
||||
switch fullUser {
|
||||
case let .userFull(_, _, _, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
updatePeers(transaction: transaction, peers: peers, update: { previous, updated -> Peer in
|
||||
if previous?.id == accountPeerId, let accountUser = accountUser, let user = TelegramUser.merge(previous as? TelegramUser, rhs: accountUser) {
|
||||
return user
|
||||
}
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: userFullNotifySettings)])
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
}
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { peerId, current in
|
||||
let previous: CachedUserData
|
||||
@ -368,25 +341,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
let exportedInvitation = chatFullExportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) }
|
||||
let pinnedMessageId = chatFullPinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var flags = CachedGroupFlags()
|
||||
if (chatFullFlags & 1 << 7) != 0 {
|
||||
@ -561,42 +517,16 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
migrationReference = ChannelMigrationReference(maxMessageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(migratedFromChatId)), namespace: Namespaces.Message.Cloud, id: migratedFromMaxId))
|
||||
}
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: Api.User] = [:]
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
var parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
|
||||
if let participantResult = participantResult {
|
||||
switch participantResult {
|
||||
case let .channelParticipant(_, chats, users):
|
||||
for user in users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
peers.append(telegramUser)
|
||||
peerPresences[telegramUser.id] = user
|
||||
}
|
||||
}
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
parsedPeers = parsedPeers.union(with: AccumulatedPeers(transaction: transaction, chats: chats, users: users))
|
||||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
})
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let stickerPack: StickerPackCollectionInfo? = stickerSet.flatMap { apiSet -> StickerPackCollectionInfo in
|
||||
let namespace: ItemCollectionId.Namespace
|
||||
|
@ -10,6 +10,7 @@ public enum UpdatePeerTitleError {
|
||||
}
|
||||
|
||||
func _internal_updatePeerTitle(account: Account, peerId: PeerId, title: String) -> Signal<Void, UpdatePeerTitleError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.postbox.transaction { transaction -> Signal<Void, UpdatePeerTitleError> in
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let peer = peer as? TelegramChannel, let inputChannel = apiInputChannel(peer) {
|
||||
@ -21,10 +22,9 @@ func _internal_updatePeerTitle(account: Account, peerId: PeerId, title: String)
|
||||
account.stateManager.addUpdates(result)
|
||||
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let apiChat = apiUpdatesGroups(result).first, let updatedPeer = parseTelegramGroupOrChannel(chat: apiChat) {
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
if let apiChat = apiUpdatesGroups(result).first {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [apiChat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
} |> mapError { _ -> UpdatePeerTitleError in }
|
||||
}
|
||||
@ -37,10 +37,9 @@ func _internal_updatePeerTitle(account: Account, peerId: PeerId, title: String)
|
||||
account.stateManager.addUpdates(result)
|
||||
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let apiChat = apiUpdatesGroups(result).first, let updatedPeer = parseTelegramGroupOrChannel(chat: apiChat) {
|
||||
updatePeers(transaction: transaction, peers: [updatedPeer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
if let apiChat = apiUpdatesGroups(result).first {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [apiChat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
}
|
||||
} |> mapError { _ -> UpdatePeerTitleError in }
|
||||
}
|
||||
|
@ -6,35 +6,31 @@ import MtProtoKit
|
||||
|
||||
|
||||
public func requestBlockedPeers(account: Account) -> Signal<[Peer], NoError> {
|
||||
let accountPeerId = account.peerId
|
||||
return account.network.request(Api.functions.contacts.getBlocked(offset: 0, limit: 100))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<[Peer], NoError> in
|
||||
return account.postbox.transaction { transaction -> [Peer] in
|
||||
var peers: [Peer] = []
|
||||
let apiUsers: [Api.User]
|
||||
let apiChats: [Api.Chat]
|
||||
switch result {
|
||||
case let .blocked(_, chats, users):
|
||||
apiUsers = users
|
||||
apiChats = chats
|
||||
case let .blockedSlice(_, _, chats, users):
|
||||
apiUsers = users
|
||||
apiChats = chats
|
||||
case let .blocked(_, chats, users):
|
||||
apiUsers = users
|
||||
apiChats = chats
|
||||
case let .blockedSlice(_, _, chats, users):
|
||||
apiUsers = users
|
||||
apiChats = chats
|
||||
}
|
||||
for chat in apiChats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: apiChats, users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var peers: [Peer] = []
|
||||
for id in parsedPeers.allIds {
|
||||
if let peer = transaction.getPeer(id) {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
for user in apiUsers {
|
||||
let parsed = TelegramUser(user: user)
|
||||
peers.append(parsed)
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
|
||||
return peers
|
||||
}
|
||||
}
|
||||
|
@ -57,53 +57,38 @@ public final class BlockedPeersContext {
|
||||
}
|
||||
self._state = BlockedPeersContextState(isLoadingMore: true, canLoadMore: self._state.canLoadMore, totalCount: self._state.totalCount, peers: self._state.peers)
|
||||
let postbox = self.account.postbox
|
||||
let accountPeerId = self.account.peerId
|
||||
self.disposable.set((self.account.network.request(Api.functions.contacts.getBlocked(offset: Int32(self._state.peers.count), limit: 64))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<(peers: [RenderedPeer], canLoadMore: Bool, totalCount: Int?), NoError> in
|
||||
return postbox.transaction { transaction -> (peers: [RenderedPeer], canLoadMore: Bool, totalCount: Int?) in
|
||||
switch result {
|
||||
case let .blocked(blocked, chats, users):
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
|
||||
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var renderedPeers: [RenderedPeer] = []
|
||||
for blockedPeer in blocked {
|
||||
switch blockedPeer {
|
||||
case let .peerBlocked(peerId, _):
|
||||
if let peer = transaction.getPeer(peerId.peerId) {
|
||||
renderedPeers.append(RenderedPeer(peer: peer))
|
||||
}
|
||||
case let .peerBlocked(peerId, _):
|
||||
if let peer = transaction.getPeer(peerId.peerId) {
|
||||
renderedPeers.append(RenderedPeer(peer: peer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (renderedPeers, false, nil)
|
||||
case let .blockedSlice(count, blocked, chats, users):
|
||||
var peers: [Peer] = []
|
||||
for chat in chats {
|
||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||
peers.append(groupOrChannel)
|
||||
}
|
||||
}
|
||||
for user in users {
|
||||
peers.append(TelegramUser(user: user))
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
var renderedPeers: [RenderedPeer] = []
|
||||
for blockedPeer in blocked {
|
||||
switch blockedPeer {
|
||||
case let .peerBlocked(peerId, _):
|
||||
if let peer = transaction.getPeer(peerId.peerId) {
|
||||
renderedPeers.append(RenderedPeer(peer: peer))
|
||||
}
|
||||
case let .peerBlocked(peerId, _):
|
||||
if let peer = transaction.getPeer(peerId.peerId) {
|
||||
renderedPeers.append(RenderedPeer(peer: peer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ public func _internal_updateCloseFriends(account: Account, peerIds: [EnginePeer.
|
||||
}
|
||||
}
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: updatedPeers, update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: updatedPeers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> AccountPrivacySettings in
|
||||
updatePeers(transaction: transaction, peers: peers.map { $0.peer }, update: { _, updated in
|
||||
updatePeersCustom(transaction: transaction, peers: peers.map { $0.peer }, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
|
||||
|
@ -240,7 +240,7 @@ public struct EncryptedSecureIdForm {
|
||||
let errors: [Api.SecureValueError]
|
||||
}
|
||||
|
||||
public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: String, publicKey: String) -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> {
|
||||
public func requestSecureIdForm(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, scope: String, publicKey: String) -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> {
|
||||
if peerId.namespace != Namespaces.Peer.CloudUser {
|
||||
return .fail(.serverError("BOT_INVALID"))
|
||||
}
|
||||
@ -263,14 +263,7 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer
|
||||
return postbox.transaction { transaction -> EncryptedSecureIdForm in
|
||||
switch result {
|
||||
case let .authorizationForm(_, requiredTypes, values, errors, users, termsUrl):
|
||||
var peers: [Peer] = []
|
||||
for user in users {
|
||||
let parsed = TelegramUser(user: user)
|
||||
peers.append(parsed)
|
||||
}
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
return EncryptedSecureIdForm(peerId: peerId, requestedFields: requiredTypes.map { requiredType in
|
||||
switch requiredType {
|
||||
|
@ -2,7 +2,6 @@ import Foundation
|
||||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
|
||||
func updatePeerChatInclusionWithMinTimestamp(transaction: Transaction, id: PeerId, minTimestamp: Int32, forceRootGroupIfNotExists: Bool) {
|
||||
let currentInclusion = transaction.getPeerChatListInclusion(id)
|
||||
var updatedInclusion: PeerChatListInclusion?
|
||||
@ -39,7 +38,31 @@ func minTimestampForPeerInclusion(_ peer: Peer) -> Int32? {
|
||||
}
|
||||
}
|
||||
|
||||
public func updatePeers(transaction: Transaction, peers: [Peer], update: (Peer?, Peer) -> Peer?) {
|
||||
func updatePeers(transaction: Transaction, accountPeerId: PeerId, peers: AccumulatedPeers) {
|
||||
var parsedPeers: [Peer] = []
|
||||
for (_, user) in peers.users {
|
||||
if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) {
|
||||
parsedPeers.append(telegramUser)
|
||||
|
||||
switch user {
|
||||
case let .user(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, storiesMaxId):
|
||||
if let storiesMaxId = storiesMaxId {
|
||||
transaction.setStoryItemsInexactMaxId(peerId: user.peerId, id: storiesMaxId)
|
||||
}
|
||||
case .userEmpty:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for (_, peer) in peers.peers {
|
||||
parsedPeers.append(peer)
|
||||
}
|
||||
updatePeersCustom(transaction: transaction, peers: parsedPeers, update: { _, updated in updated })
|
||||
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peers.users)
|
||||
}
|
||||
|
||||
public func updatePeersCustom(transaction: Transaction, peers: [Peer], update: (Peer?, Peer) -> Peer?) {
|
||||
transaction.updatePeersInternal(peers, update: { previous, updated in
|
||||
let peerId = updated.id
|
||||
|
||||
|
@ -223,6 +223,62 @@ func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer], associ
|
||||
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
|
||||
}
|
||||
|
||||
func locallyRenderedMessage(message: StoreMessage, peers: AccumulatedPeers, associatedThreadInfo: Message.AssociatedThreadInfo? = nil) -> Message? {
|
||||
guard case let .Id(id) = message.id else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var messagePeers = SimpleDictionary<PeerId, Peer>()
|
||||
|
||||
var author: Peer?
|
||||
if let authorId = message.authorId {
|
||||
author = peers.get(authorId)
|
||||
if let author = author {
|
||||
messagePeers[author.id] = author
|
||||
}
|
||||
}
|
||||
|
||||
if let peer = peers.get(id.peerId) {
|
||||
messagePeers[peer.id] = peer
|
||||
|
||||
if let group = peer as? TelegramGroup, let migrationReference = group.migrationReference {
|
||||
if let channelPeer = peers.get(migrationReference.peerId) {
|
||||
messagePeers[channelPeer.id] = channelPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for media in message.media {
|
||||
for peerId in media.peerIds {
|
||||
if let peer = peers.get(peerId) {
|
||||
messagePeers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var forwardInfo: MessageForwardInfo?
|
||||
if let info = message.forwardInfo {
|
||||
forwardInfo = MessageForwardInfo(author: info.authorId.flatMap({ peers.get($0) }), source: info.sourceId.flatMap({ peers.get($0) }), sourceMessageId: info.sourceMessageId, date: info.date, authorSignature: info.authorSignature, psaType: info.psaType, flags: info.flags)
|
||||
if let author = forwardInfo?.author {
|
||||
messagePeers[author.id] = author
|
||||
}
|
||||
if let source = forwardInfo?.source {
|
||||
messagePeers[source.id] = source
|
||||
}
|
||||
}
|
||||
|
||||
var hasher = Hasher()
|
||||
hasher.combine(id.id)
|
||||
hasher.combine(id.peerId)
|
||||
|
||||
let hashValue = Int64(hasher.finalize())
|
||||
let first = UInt32((hashValue >> 32) & 0xffffffff)
|
||||
let second = UInt32(hashValue & 0xffffffff)
|
||||
let stableId = first &+ second
|
||||
|
||||
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
|
||||
}
|
||||
|
||||
public extension Message {
|
||||
func effectivelyIncoming(_ accountPeerId: PeerId) -> Bool {
|
||||
if self.id.peerId == accountPeerId {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user