This commit is contained in:
Ali 2023-07-07 02:03:11 +04:00
parent 3150e296a3
commit f3ee06dd32
105 changed files with 2621 additions and 2416 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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)
}
}
}
}

View File

@ -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
}
}

View File

@ -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
}

View File

@ -288,7 +288,8 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
topForumTopicItems: [],
hasFailed: false,
isContact: false,
autoremoveTimeout: nil
autoremoveTimeout: nil,
storyStats: nil
))
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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),

View File

@ -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:

View File

@ -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 {

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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() {

View File

@ -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() {
}
}

View File

@ -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

View File

@ -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

View File

@ -1363,7 +1363,8 @@ private func threadList(context: AccountContext, peerId: EnginePeer.Id) -> Signa
topForumTopicItems: [],
hasFailed: false,
isContact: false,
autoremoveTimeout: nil
autoremoveTimeout: nil,
storyStats: nil
))
}

View File

@ -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

View File

@ -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)
})

View File

@ -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)

View File

@ -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)
}

View File

@ -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

View File

@ -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)

View File

@ -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)
})
}

View File

@ -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

View File

@ -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)

View File

@ -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),

View File

@ -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))
}

View File

@ -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())

View File

@ -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 {

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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()
})
}

View File

@ -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 {

View File

@ -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
})
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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
})
}

View File

@ -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)

View File

@ -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 }
}
}

View File

@ -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
})
}

View File

@ -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]))
}
}
}

View File

@ -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)

View File

@ -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()
}
}

View File

@ -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)

View File

@ -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] = []

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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)) }
}
}

View File

@ -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?

View File

@ -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
}
}

View File

@ -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)

View File

@ -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> {

View File

@ -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)

View File

@ -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> {

View File

@ -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
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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
})
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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)
})

View File

@ -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)

View File

@ -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):

View File

@ -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
})

View File

@ -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

View File

@ -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
})
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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> {

View File

@ -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)

View File

@ -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

View File

@ -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 }
}

View File

@ -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
}
}

View File

@ -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))
}
}
}

View File

@ -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
})
}

View File

@ -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
})

View File

@ -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 {

View File

@ -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

View File

@ -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