diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 2deba07c1e..9327276de1 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -696,8 +696,8 @@ public protocol SharedAccountContext: AnyObject { func openStorageUsage(context: AccountContext) func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController) func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void) - func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set) -> Signal - func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal + func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set) -> Signal + func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal func resolveUrl(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) func openAddContact(context: AccountContext, firstName: String, lastName: String, phoneNumber: String, label: String, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void) diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index 59d79f3dbe..99e1293f84 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -16,21 +16,25 @@ import PremiumUI func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chatListController: ChatListControllerImpl?) -> Signal<[ContextMenuItem], NoError> { let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) let strings = presentationData.strings - return context.account.postbox.transaction { [weak chatListController] transaction -> [ContextMenuItem] in + return combineLatest( + context.engine.messages.unreadChatListPeerIds(groupId: EngineChatList.Group(groupId), filterPredicate: nil), + context.engine.data.get( + TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ApplicationSpecificPreferencesKeys.chatArchiveSettings) + ) + ) + |> map { [weak chatListController] unreadChatListPeerIds, chatArchiveSettingsPreference -> [ContextMenuItem] in var items: [ContextMenuItem] = [] - if !transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: nil).isEmpty { + if !unreadChatListPeerIds.isEmpty { items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = (context.account.postbox.transaction { transaction in - markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: nil) - } + let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: EngineChatList.Group(groupId), filterPredicate: nil)]) |> deliverOnMainQueue).start(completed: { f(.default) }) }))) } - let settings = transaction.getPreferencesEntry(key: ApplicationSpecificPreferencesKeys.chatArchiveSettings)?.get(ChatArchiveSettings.self) ?? ChatArchiveSettings.default + let settings = chatArchiveSettingsPreference?.get(ChatArchiveSettings.self) ?? ChatArchiveSettings.default let isPinned = !settings.isHiddenByDefault items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_HideArchive : strings.ChatList_Context_UnhideArchive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin": "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { [weak chatListController] _, f in chatListController?.toggleArchivedFolderHiddenByDefault() @@ -75,34 +79,41 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch ) |> mapToSignal { filters, pinnedItemIds -> Signal<[ContextMenuItem], NoError> in let isPinned = pinnedItemIds.contains(.peer(peerId)) - - return context.account.postbox.transaction { [weak chatListController] transaction -> [ContextMenuItem] in - if promoInfo != nil { - return [] + + let renderedPeer = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.RenderedPeer(id: peerId)) + + return renderedPeer + |> mapToSignal { renderedPeer -> Signal<[ContextMenuItem], NoError> in + guard let renderedPeer = renderedPeer else { + return .single([]) } + guard let peer = renderedPeer.chatMainPeer else { + return .single([]) + } + + return context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.IsContact(id: peer.id), + TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peer.id), + TelegramEngine.EngineData.Item.Messages.ReadState(id: peer.id) + ) + |> map { [weak chatListController] isContact, notificationSettings, readState -> [ContextMenuItem] in + if promoInfo != nil { + return [] + } - var items: [ContextMenuItem] = [] + var items: [ContextMenuItem] = [] - if case let .search(search) = source { - switch search { - case .recentPeers: - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in - let _ = (context.engine.peers.removeRecentPeer(peerId: peerId) - |> deliverOnMainQueue).start(completed: { - f(.default) - }) - }))) - items.append(.separator) - case .recentSearch: - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in - let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId) - |> deliverOnMainQueue).start(completed: { - f(.default) - }) - }))) - items.append(.separator) - case .search: - if recentlySearchedPeers.contains(where: { $0.peer.peerId == peerId }) { + if case let .search(search) = source { + switch search { + case .recentPeers: + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in + let _ = (context.engine.peers.removeRecentPeer(peerId: peerId) + |> deliverOnMainQueue).start(completed: { + f(.default) + }) + }))) + items.append(.separator) + case .recentSearch: items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId) |> deliverOnMainQueue).start(completed: { @@ -110,320 +121,308 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch }) }))) items.append(.separator) - } - } - } - - let isSavedMessages = peerId == context.account.peerId - - let chatPeer = transaction.getPeer(peerId) - var maybePeer: Peer? - if let chatPeer = chatPeer { - if let chatPeer = chatPeer as? TelegramSecretChat { - maybePeer = transaction.getPeer(chatPeer.regularPeerId) - } else { - maybePeer = chatPeer - } - } - - guard let peer = maybePeer else { - return [] - } - - if !isSavedMessages, let peer = peer as? TelegramUser, !peer.flags.contains(.isSupport) && peer.botInfo == nil && !peer.isDeleted { - if !transaction.isPeerContact(peerId: peer.id) { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToContacts, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { _, f in - context.sharedContext.openAddPersonContact(context: context, peerId: peerId, pushController: { controller in - if let navigationController = chatListController?.navigationController as? NavigationController { - navigationController.pushViewController(controller) - } - }, present: { c, a in - if let chatListController = chatListController { - chatListController.present(c, in: .window(.root), with: a) - } - }) - f(.default) - }))) - items.append(.separator) - } - } - - var isMuted = false - if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { - if case .muted = notificationSettings.muteState { - isMuted = true - } - } - - var isUnread = false - if let readState = transaction.getCombinedPeerReadState(peerId), readState.isUnread { - isUnread = true - } - - let isContact = transaction.isPeerContact(peerId: peerId) - - if case let .chatList(currentFilter) = source { - if let currentFilter = currentFilter, case let .filter(id, title, emoticon, data) = currentFilter { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/RemoveFromFolder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in - let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in - var filters = filters - for i in 0 ..< filters.count { - if filters[i].id == currentFilter.id { - var updatedData = data - let _ = updatedData.addExcludePeer(peerId: peer.id) - filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData) - break - } - } - return filters - } - |> deliverOnMainQueue).start(completed: { - c.dismiss(completion: { - chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatRemovedFromFolder(chatTitle: EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in - return false - }), in: .current) - }) - }) - }))) - } else { - var hasFolders = false - - for case let .filter(_, _, _, data) in filters { - let predicate = chatListFilterPredicate(filter: data) - if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { - continue - } - - var data = data - if data.addIncludePeer(peerId: peer.id) { - hasFolders = true - break - } - } - - if hasFolders { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in - var updatedItems: [ContextMenuItem] = [] - - for filter in filters { - if case let .filter(_, title, _, data) = filter { - let predicate = chatListFilterPredicate(filter: data) - if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { - continue - } - - var data = data - if !data.addIncludePeer(peerId: peer.id) { - continue - } - - let filterType = chatListFilterType(data) - updatedItems.append(.action(ContextMenuActionItem(text: title, icon: { theme in - let imageName: String - switch filterType { - case .generic: - imageName = "Chat/Context Menu/List" - case .unmuted: - imageName = "Chat/Context Menu/Unmute" - case .unread: - imageName = "Chat/Context Menu/MarkAsUnread" - case .channels: - imageName = "Chat/Context Menu/Channels" - case .groups: - imageName = "Chat/Context Menu/Groups" - case .bots: - imageName = "Chat/Context Menu/Bots" - case .contacts: - imageName = "Chat/Context Menu/User" - case .nonContacts: - imageName = "Chat/Context Menu/UnknownUser" - } - return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor) - }, action: { c, f in - c.dismiss(completion: { - let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in - var filters = filters - for i in 0 ..< filters.count { - if filters[i].id == filter.id { - if case let .filter(id, title, emoticon, data) = filter { - var updatedData = data - let _ = updatedData.addIncludePeer(peerId: peer.id) - filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData) - } - break - } - } - return filters - }).start() - - chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in - return false - }), in: .current) - }) - }))) - } - } - - updatedItems.append(.separator) - updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in - c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController, joined: joined) |> map { ContextController.Items(content: .list($0)) }, minHeight: nil) - }))) - - c.setItems(.single(ContextController.Items(content: .list(updatedItems))), minHeight: nil) - }))) - } - } - } - - if isUnread { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start() - f(.default) - }))) - } else { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsUnread, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsUnread"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start() - f(.default) - }))) - } - - let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId - if let group = peerGroup { - if archiveEnabled { - let isArchived = group == .archive - items.append(.action(ContextMenuActionItem(text: isArchived ? strings.ChatList_Context_Unarchive : strings.ChatList_Context_Archive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isArchived ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"), color: theme.contextMenu.primaryColor) }, action: { _, f in - if isArchived { - let _ = (context.account.postbox.transaction { transaction -> Void in - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) - } - |> deliverOnMainQueue).start(completed: { - f(.default) - }) - } else { - if let chatListController = chatListController { - chatListController.archiveChats(peerIds: [peerId]) - f(.default) - } else { - let _ = (context.account.postbox.transaction { transaction -> Void in - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: Namespaces.PeerGroup.archive) - } + case .search: + if recentlySearchedPeers.contains(where: { $0.peer.peerId == peerId }) { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in + let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId) |> deliverOnMainQueue).start(completed: { f(.default) }) - } + }))) + items.append(.separator) } - }))) - } - - if isPinned || chatListFilter == nil || peerId.namespace != Namespaces.Peer.SecretChat { - items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { c, f in - let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: .peer(peerId)) - |> deliverOnMainQueue).start(next: { result in - switch result { - case .done: - f(.default) - case let .limitExceeded(count, _): - f(.default) - - var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: { - let premiumScreen = PremiumIntroScreen(context: context, source: .pinnedChats) - replaceImpl?(premiumScreen) - }) - chatListController?.push(controller) - replaceImpl = { [weak controller] c in - controller?.replace(with: c) - } - } - }) - }))) - } - - if !isSavedMessages, let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { - var isMuted = false - if case .muted = notificationSettings.muteState { - isMuted = true } - items.append(.action(ContextMenuActionItem(text: isMuted ? strings.ChatList_Context_Unmute : strings.ChatList_Context_Mute, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = (context.engine.peers.togglePeerMuted(peerId: peerId) - |> deliverOnMainQueue).start(completed: { - f(.default) - }) - }))) } - } else { - if case .search = source { - if let peer = peer as? TelegramChannel { - let text: String - if case .broadcast = peer.info { - text = strings.ChatList_Context_JoinChannel - } else { - text = strings.ChatList_Context_JoinChat - } - items.append(.action(ContextMenuActionItem(text: text, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in - var createSignal = context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peerId, hash: nil) - var cancelImpl: (() -> Void)? - let progressSignal = Signal { subscriber in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { - cancelImpl?() - })) - chatListController?.present(controller, in: .window(.root)) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() - } - } - } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - createSignal = createSignal - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() - } - } - let joinChannelDisposable = MetaDisposable() - cancelImpl = { - joinChannelDisposable.set(nil) - } + let isSavedMessages = peerId == context.account.peerId - joinChannelDisposable.set((createSignal - |> deliverOnMainQueue).start(next: { _ in - }, error: { _ in + if !isSavedMessages, case let .user(peer) = peer, !peer.flags.contains(.isSupport), peer.botInfo == nil && !peer.isDeleted { + if !isContact { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToContacts, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { _, f in + context.sharedContext.openAddPersonContact(context: context, peerId: peerId, pushController: { controller in + if let navigationController = chatListController?.navigationController as? NavigationController { + navigationController.pushViewController(controller) + } + }, present: { c, a in if let chatListController = chatListController { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - chatListController.present(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + chatListController.present(c, in: .window(.root), with: a) } - }, completed: { - if let navigationController = (chatListController?.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } - })) + }) f(.default) }))) + items.append(.separator) } } - } - if case .chatList = source, peerGroup != nil { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in - if let chatListController = chatListController { - chatListController.deletePeerChat(peerId: peerId, joined: joined) + var isMuted = false + if case .muted = notificationSettings.muteState { + isMuted = true + } + + var isUnread = false + if let readState = readState, readState.isUnread { + isUnread = true + } + + if case let .chatList(currentFilter) = source { + if let currentFilter = currentFilter, case let .filter(id, title, emoticon, data) = currentFilter { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/RemoveFromFolder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in + var filters = filters + for i in 0 ..< filters.count { + if filters[i].id == currentFilter.id { + var updatedData = data + let _ = updatedData.addExcludePeer(peerId: peer.id) + filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData) + break + } + } + return filters + } + |> deliverOnMainQueue).start(completed: { + c.dismiss(completion: { + chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatRemovedFromFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in + return false + }), in: .current) + }) + }) + }))) + } else { + var hasFolders = false + + for case let .filter(_, _, _, data) in filters { + let predicate = chatListFilterPredicate(filter: data) + if predicate.includes(peer: peer._asPeer(), groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { + continue + } + + var data = data + if data.addIncludePeer(peerId: peer.id) { + hasFolders = true + break + } + } + + if hasFolders { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in + var updatedItems: [ContextMenuItem] = [] + + for filter in filters { + if case let .filter(_, title, _, data) = filter { + let predicate = chatListFilterPredicate(filter: data) + if predicate.includes(peer: peer._asPeer(), groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { + continue + } + + var data = data + if !data.addIncludePeer(peerId: peer.id) { + continue + } + + let filterType = chatListFilterType(data) + updatedItems.append(.action(ContextMenuActionItem(text: title, icon: { theme in + let imageName: String + switch filterType { + case .generic: + imageName = "Chat/Context Menu/List" + case .unmuted: + imageName = "Chat/Context Menu/Unmute" + case .unread: + imageName = "Chat/Context Menu/MarkAsUnread" + case .channels: + imageName = "Chat/Context Menu/Channels" + case .groups: + imageName = "Chat/Context Menu/Groups" + case .bots: + imageName = "Chat/Context Menu/Bots" + case .contacts: + imageName = "Chat/Context Menu/User" + case .nonContacts: + imageName = "Chat/Context Menu/UnknownUser" + } + return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor) + }, action: { c, f in + c.dismiss(completion: { + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in + var filters = filters + for i in 0 ..< filters.count { + if filters[i].id == filter.id { + if case let .filter(id, title, emoticon, data) = filter { + var updatedData = data + let _ = updatedData.addIncludePeer(peerId: peer.id) + filters[i] = .filter(id: id, title: title, emoticon: emoticon, data: updatedData) + } + break + } + } + return filters + }).start() + + chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in + return false + }), in: .current) + }) + }))) + } + } + + updatedItems.append(.separator) + updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) + }, action: { c, _ in + c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController, joined: joined) |> map { ContextController.Items(content: .list($0)) }, minHeight: nil) + }))) + + c.setItems(.single(ContextController.Items(content: .list(updatedItems))), minHeight: nil) + }))) + } } - f(.default) - }))) - } + } - if let item = items.last, case .separator = item { - items.removeLast() - } + if isUnread { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in + let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start() + f(.default) + }))) + } else { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAsUnread, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsUnread"), color: theme.contextMenu.primaryColor) }, action: { _, f in + let _ = togglePeerUnreadMarkInteractively(postbox: context.account.postbox, viewTracker: context.account.viewTracker, peerId: peerId).start() + f(.default) + }))) + } - return items + let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId + if let group = peerGroup { + if archiveEnabled { + let isArchived = group == .archive + items.append(.action(ContextMenuActionItem(text: isArchived ? strings.ChatList_Context_Unarchive : strings.ChatList_Context_Archive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isArchived ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"), color: theme.contextMenu.primaryColor) }, action: { _, f in + if isArchived { + let _ = (context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .root) + |> deliverOnMainQueue).start(completed: { + f(.default) + }) + } else { + if let chatListController = chatListController { + chatListController.archiveChats(peerIds: [peerId]) + f(.default) + } else { + let _ = (context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .archive) + |> deliverOnMainQueue).start(completed: { + f(.default) + }) + } + } + }))) + } + + if isPinned || chatListFilter == nil || peerId.namespace != Namespaces.Peer.SecretChat { + items.append(.action(ContextMenuActionItem(text: isPinned ? strings.ChatList_Context_Unpin : strings.ChatList_Context_Pin, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isPinned ? "Chat/Context Menu/Unpin" : "Chat/Context Menu/Pin"), color: theme.contextMenu.primaryColor) }, action: { c, f in + let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: .peer(peerId)) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .done: + f(.default) + case let .limitExceeded(count, _): + f(.default) + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: { + let premiumScreen = PremiumIntroScreen(context: context, source: .pinnedChats) + replaceImpl?(premiumScreen) + }) + chatListController?.push(controller) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + } + }) + }))) + } + + if !isSavedMessages { + var isMuted = false + if case .muted = notificationSettings.muteState { + isMuted = true + } + items.append(.action(ContextMenuActionItem(text: isMuted ? strings.ChatList_Context_Unmute : strings.ChatList_Context_Mute, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) }, action: { _, f in + let _ = (context.engine.peers.togglePeerMuted(peerId: peerId) + |> deliverOnMainQueue).start(completed: { + f(.default) + }) + }))) + } + } else { + if case .search = source { + if case let .channel(peer) = peer { + let text: String + if case .broadcast = peer.info { + text = strings.ChatList_Context_JoinChannel + } else { + text = strings.ChatList_Context_JoinChat + } + items.append(.action(ContextMenuActionItem(text: text, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in + var createSignal = context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peerId, hash: nil) + var cancelImpl: (() -> Void)? + let progressSignal = Signal { subscriber in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { + cancelImpl?() + })) + chatListController?.present(controller, in: .window(.root)) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + createSignal = createSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + let joinChannelDisposable = MetaDisposable() + cancelImpl = { + joinChannelDisposable.set(nil) + } + + joinChannelDisposable.set((createSignal + |> deliverOnMainQueue).start(next: { _ in + }, error: { _ in + if let chatListController = chatListController { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + chatListController.present(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + } + }, completed: { + if let navigationController = (chatListController?.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) + } + })) + f(.default) + }))) + } + } + } + + if case .chatList = source, peerGroup != nil { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in + if let chatListController = chatListController { + chatListController.deletePeerChat(peerId: peerId, joined: joined) + } + f(.default) + }))) + } + + if let item = items.last, case .separator = item { + items.removeLast() + } + + return items + } } } } diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index d200e99fc9..25794a1b58 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -964,7 +964,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.archiveChats(peerIds: [peerId]) } else { strongSelf.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerId) - let _ = updatePeerGroupIdInteractively(postbox: strongSelf.context.account.postbox, peerId: peerId, groupId: group ? Namespaces.PeerGroup.archive : .root).start(completed: { + let _ = strongSelf.context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: group ? .archive : .root).start(completed: { guard let strongSelf = self else { return } @@ -2419,7 +2419,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController override public func toolbarActionSelected(action: ToolbarActionOption) { let peerIds = self.chatListDisplayNode.containerNode.currentItemNode.currentState.selectedPeerIds if case .left = action { - let signal: Signal + let signal: Signal var completion: (() -> Void)? let context = self.context if !peerIds.isEmpty { @@ -2432,6 +2432,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController togglePeerUnreadMarkInteractively(transaction: transaction, viewTracker: context.account.viewTracker, peerId: peerId, setToValue: false) } } + |> ignoreValues } else { let groupId = self.groupId let filterPredicate: ChatListFilterPredicate? @@ -2440,14 +2441,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } else { filterPredicate = nil } - signal = self.context.account.postbox.transaction { transaction -> Void in - markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: filterPredicate) - if let filterPredicate = filterPredicate { - for additionalGroupId in filterPredicate.includeAdditionalPeerGroupIds { - markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: additionalGroupId, filterPredicate: filterPredicate) - } + var markItems: [(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?)] = [] + markItems.append((EngineChatList.Group(groupId), filterPredicate)) + if let filterPredicate = filterPredicate { + for additionalGroupId in filterPredicate.includeAdditionalPeerGroupIds { + markItems.append((EngineChatList.Group(additionalGroupId), filterPredicate)) } } + signal = self.context.engine.messages.markAllChatsAsReadInteractively(items: markItems) } let _ = (signal |> deliverOnMainQueue).start(completed: { [weak self] in @@ -2545,11 +2546,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } else { if !peerIds.isEmpty { self.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds.first!) - let _ = (self.context.account.postbox.transaction { transaction -> Void in - for peerId in peerIds { - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) - } - } + let _ = (self.context.engine.peers.updatePeersGroupIdInteractively(peerIds: Array(peerIds), groupId: .root) |> deliverOnMainQueue).start(completed: { [weak self] in guard let strongSelf = self else { return @@ -3047,15 +3044,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard !peerIds.isEmpty else { return } - let postbox = self.context.account.postbox + let engine = self.context.engine self.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds[0]) let _ = (ApplicationSpecificNotice.incrementArchiveChatTips(accountManager: self.context.sharedContext.accountManager, count: 1) |> deliverOnMainQueue).start(next: { [weak self] previousHintCount in - let _ = (postbox.transaction { transaction -> Void in - for peerId in peerIds { - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: Namespaces.PeerGroup.archive) - } - } + let _ = (engine.peers.updatePeersGroupIdInteractively(peerIds: peerIds, groupId: .archive) |> deliverOnMainQueue).start(completed: { guard let strongSelf = self else { return @@ -3072,11 +3065,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } if value == .undo { strongSelf.chatListDisplayNode.containerNode.currentItemNode.setCurrentRemovingPeerId(peerIds[0]) - let _ = (postbox.transaction { transaction -> Void in - for peerId in peerIds { - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) - } - } + let _ = (engine.peers.updatePeersGroupIdInteractively(peerIds: peerIds, groupId: .root) |> deliverOnMainQueue).start(completed: { guard let strongSelf = self else { return diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 20059ce320..1dfa98f74a 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -719,7 +719,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } let (peers, messages) = strongSelf.currentMessages - return strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers) + return strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers) } self.selectionPanelNode = selectionPanelNode self.addSubnode(selectionPanelNode) @@ -825,7 +825,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } let items = combineLatest(queue: .mainQueue(), - context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: [message.id: message], peers: [:]), + context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: [message.id: message], peers: [:]), isCachedValue |> take(1) ) |> deliverOnMainQueue @@ -934,7 +934,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo let context = self.context let (peers, messages) = self.currentMessages - let items = context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers) + let items = context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers) |> map { [weak self] actions -> [ContextMenuItem] in guard let strongSelf = self else { return [] @@ -1000,7 +1000,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo let strings = strongSelf.presentationData.strings let (peers, messages) = strongSelf.currentMessages - let items = context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers) + let items = context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: [message.id], messages: messages, peers: peers) |> map { actions -> [ContextMenuItem] in var items: [ContextMenuItem] = [] @@ -1129,7 +1129,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.context.engine.messages.ensureMessagesAreLocallyAvailable(messages: messages.values.filter { messageIds.contains($0.id) }) - self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers) + self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: messageIds, messages: messages, peers: peers) |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self, !actions.options.isEmpty { let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 6ce6594fda..c7532572df 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -581,8 +581,6 @@ public enum ChatListGlobalScrollOption { } public enum ChatListNodeScrollPosition { - case auto - case autoUp case top } @@ -1895,29 +1893,6 @@ public final class ChatListNode: ListView { public func scrollToPosition(_ position: ChatListNodeScrollPosition) { if let view = self.chatListView?.originalView { - if case .auto = position { - switch self.visibleContentOffset() { - case .none, .unknown: - if let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() { - self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex) - return - } - case let .known(offset): - if offset <= 0.0 { - self.scrollToEarliestUnread(earlierThan: nil) - return - } else { - if let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() { - self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex) - return - } - } - } - } else if case .autoUp = position, let maxVisibleChatListIndex = self.currentlyVisibleLatestChatListIndex() { - self.scrollToEarliestUnread(earlierThan: maxVisibleChatListIndex) - return - } - if view.laterIndex == nil { self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) } else { @@ -1938,7 +1913,7 @@ public final class ChatListNode: ListView { private func relativeUnreadChatListIndex(position: EngineChatList.RelativePosition) -> Signal { let groupId = self.groupId - let postbox = self.context.account.postbox + let engine = self.context.engine return self.context.sharedContext.accountManager.transaction { transaction -> Signal in var filter = true if let inAppNotificationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.inAppNotificationSettings)?.get(InAppNotificationSettings.self) { @@ -1947,31 +1922,11 @@ public final class ChatListNode: ListView { filter = true } } - return postbox.transaction { transaction -> EngineChatList.Item.Index? in - return transaction.getRelativeUnreadChatListIndex(filtered: filter, position: position._asPosition(), groupId: groupId._asGroup()) - } + return engine.messages.getRelativeUnreadChatListIndex(filtered: filter, position: position, groupId: groupId) } |> switchToLatest } - public func scrollToEarliestUnread(earlierThan: EngineChatList.Item.Index?) { - let _ = (relativeUnreadChatListIndex(position: .earlier(than: earlierThan)) |> deliverOnMainQueue).start(next: { [weak self] index in - guard let strongSelf = self else { - return - } - - if let index = index { - let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: self?.currentlyVisibleLatestChatListIndex() ?? .absoluteUpperBound - , scrollPosition: .center(.top), animated: true, filter: strongSelf.chatListFilter) - strongSelf.setChatListLocation(location) - } else { - let location: ChatListNodeLocation = .scroll(index: .absoluteUpperBound, sourceIndex: .absoluteLowerBound - , scrollPosition: .top(0.0), animated: true, filter: strongSelf.chatListFilter) - strongSelf.setChatListLocation(location) - } - }) - } - public func selectChat(_ option: ChatListSelectionOption) { guard let interaction = self.interaction else { return diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index 973cecdbcc..a0ab15bc75 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -230,7 +230,7 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati if let timecode = timecode { startState = .single((timecode: timecode, rate: 1.0)) } else { - startState = mediaPlaybackStoredState(postbox: context.account.postbox, messageId: message.id) + startState = mediaPlaybackStoredState(engine: context.engine, messageId: message.id) |> map { state in return (state?.timestamp, state?.playbackRate.doubleValue ?? 1.0) } diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 2232cd77dd..ea2423ad1f 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -1093,7 +1093,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } private func commitDeleteMessages(_ messages: [EngineMessage], ask: Bool) { - self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in + self.messageContextDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: Set(messages.map { $0.id })) |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self, let controllerInteration = strongSelf.controllerInteraction, !actions.options.isEmpty { var presentationData = strongSelf.presentationData if !presentationData.theme.overallDarkAppearance { diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index b0b5242ae6..edd50e3721 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -317,7 +317,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { Queue.concurrentDefaultQueue().async { if let message = strongSelf.message, !message.isCopyProtected() && !imageReference.media.flags.contains(.hasStickers) { - strongSelf.recognitionDisposable.set((recognizedContent(postbox: strongSelf.context.account.postbox, image: { return generate(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))?.generateImage() }, messageId: message.id) + strongSelf.recognitionDisposable.set((recognizedContent(engine: strongSelf.context.engine, image: { return generate(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))?.generateImage() }, messageId: message.id) |> deliverOnMainQueue).start(next: { [weak self] results in if let strongSelf = self { strongSelf.recognizedContentNode?.removeFromSupernode() diff --git a/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift b/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift index ee35ce3601..a910e80f66 100644 --- a/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift +++ b/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift @@ -26,36 +26,30 @@ private final class CachedImageRecognizedContent: Codable { } } -private func cachedImageRecognizedContent(postbox: Postbox, messageId: MessageId) -> Signal { - return postbox.transaction { transaction -> CachedImageRecognizedContent? in - let key = ValueBoxKey(length: 20) - key.setInt32(0, value: messageId.namespace) - key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) - key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) - key.setInt32(16, value: messageId.id) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, key: key))?.get(CachedImageRecognizedContent.self) { - return entry - } else { - return nil - } +private func cachedImageRecognizedContent(engine: TelegramEngine, messageId: MessageId) -> Signal { + let key = ValueBoxKey(length: 20) + key.setInt32(0, value: messageId.namespace) + key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) + key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) + key.setInt32(16, value: messageId.id) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key)) + |> map { entry -> CachedImageRecognizedContent? in + return entry?.get(CachedImageRecognizedContent.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 50, highWaterItemCount: 100) - -private func updateCachedImageRecognizedContent(postbox: Postbox, messageId: MessageId, content: CachedImageRecognizedContent?) -> Signal { - return postbox.transaction { transaction -> Void in - let key = ValueBoxKey(length: 20) - key.setInt32(0, value: messageId.namespace) - key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) - key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) - key.setInt32(16, value: messageId.id) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, key: key) - if let content = content, let entry = CodableEntry(content) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } else { - transaction.removeItemCacheEntry(id: id) - } +private func updateCachedImageRecognizedContent(engine: TelegramEngine, messageId: MessageId, content: CachedImageRecognizedContent?) -> Signal { + let key = ValueBoxKey(length: 20) + key.setInt32(0, value: messageId.namespace) + key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) + key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) + key.setInt32(16, value: messageId.id) + + if let content = content { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key, item: content) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.cachedImageRecognizedContent, id: key) } } @@ -338,8 +332,8 @@ private func recognizeContent(in image: UIImage?) -> Signal<[RecognizedContent], } } -public func recognizedContent(postbox: Postbox, image: @escaping () -> UIImage?, messageId: MessageId) -> Signal<[RecognizedContent], NoError> { - return cachedImageRecognizedContent(postbox: postbox, messageId: messageId) +public func recognizedContent(engine: TelegramEngine, image: @escaping () -> UIImage?, messageId: MessageId) -> Signal<[RecognizedContent], NoError> { + return cachedImageRecognizedContent(engine: engine, messageId: messageId) |> mapToSignal { cachedContent -> Signal<[RecognizedContent], NoError> in if let cachedContent = cachedContent { return .single(cachedContent.results) @@ -349,7 +343,7 @@ public func recognizedContent(postbox: Postbox, image: @escaping () -> UIImage?, |> then( recognizeContent(in: image()) |> beforeNext { results in - let _ = updateCachedImageRecognizedContent(postbox: postbox, messageId: messageId, content: CachedImageRecognizedContent(results: results)).start() + let _ = updateCachedImageRecognizedContent(engine: engine, messageId: messageId, content: CachedImageRecognizedContent(results: results)).start() } ) } diff --git a/submodules/InstantPageCache/Sources/CachedInstantPages.swift b/submodules/InstantPageCache/Sources/CachedInstantPages.swift index 569d02f99e..aef6b86364 100644 --- a/submodules/InstantPageCache/Sources/CachedInstantPages.swift +++ b/submodules/InstantPageCache/Sources/CachedInstantPages.swift @@ -32,29 +32,23 @@ public final class CachedInstantPage: Codable { } } -public func cachedInstantPage(postbox: Postbox, url: String) -> Signal { - return postbox.transaction { transaction -> CachedInstantPage? in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue)) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, key: key))?.get(CachedInstantPage.self) { - return entry - } else { - return nil - } +public func cachedInstantPage(engine: TelegramEngine, url: String) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue)) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key)) + |> map { entry -> CachedInstantPage? in + return entry?.get(CachedInstantPage.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 5, highWaterItemCount: 10) - -public func updateCachedInstantPage(postbox: Postbox, url: String, webPage: TelegramMediaWebpage?) -> Signal { - return postbox.transaction { transaction -> Void in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue)) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, key: key) - if let webPage = webPage, let entry = CodableEntry(CachedInstantPage(webPage: webPage, timestamp: Int32(CFAbsoluteTimeGetCurrent()))) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } else { - transaction.removeItemCacheEntry(id: id) - } +public func updateCachedInstantPage(engine: TelegramEngine, url: String, webPage: TelegramMediaWebpage?) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: Int64(bitPattern: url.persistentHashValue)) + + if let webPage = webPage { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key, item: CachedInstantPage(webPage: webPage, timestamp: Int32(CFAbsoluteTimeGetCurrent()))) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.cachedInstantPages, id: key) } } diff --git a/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift b/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift index 5b468626b6..5ac6bde65b 100644 --- a/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift +++ b/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift @@ -51,18 +51,18 @@ public func cachedPrivacyPage(context: AccountContext) -> Signal Signal { let (cachedUrl, anchor) = extractAnchor(string: url) - return cachedInstantPage(postbox: context.account.postbox, url: cachedUrl) + return cachedInstantPage(engine: context.engine, url: cachedUrl) |> mapToSignal { cachedInstantPage -> Signal in let updated = resolveInstantViewUrl(account: context.account, url: url) |> afterNext { result in if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage { if instantPage.isComplete { - let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start() + let _ = updateCachedInstantPage(engine: context.engine, url: cachedUrl, webPage: webPage).start() } else { let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage) - |> mapToSignal { webPage -> Signal in + |> mapToSignal { webPage -> Signal in if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { - return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage) + return updateCachedInstantPage(engine: context.engine, url: cachedUrl, webPage: webPage) } else { return .complete() } diff --git a/submodules/InstantPageUI/Sources/InstantPageController.swift b/submodules/InstantPageUI/Sources/InstantPageController.swift index 7529938848..d0d77e26bf 100644 --- a/submodules/InstantPageUI/Sources/InstantPageController.swift +++ b/submodules/InstantPageUI/Sources/InstantPageController.swift @@ -141,7 +141,7 @@ public final class InstantPageController: ViewController { } override public func viewWillDisappear(_ animated: Bool) { - let _ = updateInstantPageStoredStateInteractively(postbox: self.context.account.postbox, webPage: self.webPage, state: self.controllerNode.currentState).start() + let _ = updateInstantPageStoredStateInteractively(engine: self.context.engine, webPage: self.webPage, state: self.controllerNode.currentState).start() } override public func loadDisplayNode() { @@ -167,7 +167,7 @@ public final class InstantPageController: ViewController { } }) - self.storedStateDisposable = (instantPageStoredState(postbox: self.context.account.postbox, webPage: self.webPage) + self.storedStateDisposable = (instantPageStoredState(engine: self.context.engine, webPage: self.webPage) |> deliverOnMainQueue).start(next: { [weak self] state in if let strongSelf = self { strongSelf.controllerNode.updateWebPage(strongSelf.webPage, anchor: strongSelf.anchor, state: state) diff --git a/submodules/InstantPageUI/Sources/InstantPageStoredState.swift b/submodules/InstantPageUI/Sources/InstantPageStoredState.swift index 992f9e55f0..9d2606e675 100644 --- a/submodules/InstantPageUI/Sources/InstantPageStoredState.swift +++ b/submodules/InstantPageUI/Sources/InstantPageStoredState.swift @@ -57,29 +57,23 @@ public final class InstantPageStoredState: Codable { } } -public func instantPageStoredState(postbox: Postbox, webPage: TelegramMediaWebpage) -> Signal { - return postbox.transaction { transaction -> InstantPageStoredState? in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: webPage.webpageId.id) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, key: key))?.get(InstantPageStoredState.self) { - return entry - } else { - return nil - } +public func instantPageStoredState(engine: TelegramEngine, webPage: TelegramMediaWebpage) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: webPage.webpageId.id) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key)) + |> map { entry -> InstantPageStoredState? in + return entry?.get(InstantPageStoredState.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200) - -public func updateInstantPageStoredStateInteractively(postbox: Postbox, webPage: TelegramMediaWebpage, state: InstantPageStoredState?) -> Signal { - return postbox.transaction { transaction -> Void in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: webPage.webpageId.id) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, key: key) - if let state = state, let entry = CodableEntry(state) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } else { - transaction.removeItemCacheEntry(id: id) - } +public func updateInstantPageStoredStateInteractively(engine: TelegramEngine, webPage: TelegramMediaWebpage, state: InstantPageStoredState?) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: webPage.webpageId.id) + + if let state = state { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key, item: state) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.instantPageStoredState, id: key) } } diff --git a/submodules/LocationUI/Sources/CachedGeocodes.swift b/submodules/LocationUI/Sources/CachedGeocodes.swift index 5b76e80543..bfc039a29b 100644 --- a/submodules/LocationUI/Sources/CachedGeocodes.swift +++ b/submodules/LocationUI/Sources/CachedGeocodes.swift @@ -32,34 +32,27 @@ public final class CachedGeocode: Codable { } } -private func cachedGeocode(postbox: Postbox, address: DeviceContactAddressData) -> Signal { - return postbox.transaction { transaction -> CachedGeocode? in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue)) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, key: key))?.get(CachedGeocode.self) { - return entry - } else { - return nil - } +private func cachedGeocode(engine: TelegramEngine, address: DeviceContactAddressData) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue)) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, id: key)) + |> map { entry -> CachedGeocode? in + return entry?.get(CachedGeocode.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20) - -private func updateCachedGeocode(postbox: Postbox, address: DeviceContactAddressData, latitude: Double, longitude: Double) -> Signal<(Double, Double), NoError> { - return postbox.transaction { transaction -> (Double, Double) in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue)) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, key: key) - if let entry = CodableEntry(CachedGeocode(latitude: latitude, longitude: longitude)) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } - return (latitude, longitude) - } +private func updateCachedGeocode(engine: TelegramEngine, address: DeviceContactAddressData, latitude: Double, longitude: Double) -> Signal<(Double, Double), NoError> { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: Int64(bitPattern: address.string.persistentHashValue)) + + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedGeocodes, id: key, item: CachedGeocode(latitude: latitude, longitude: longitude)) + |> map { _ -> (Double, Double) in } + |> then(.single((latitude, longitude))) } -public func geocodeAddress(postbox: Postbox, address: DeviceContactAddressData) -> Signal<(Double, Double)?, NoError> { - return cachedGeocode(postbox: postbox, address: address) +public func geocodeAddress(engine: TelegramEngine, address: DeviceContactAddressData) -> Signal<(Double, Double)?, NoError> { + return cachedGeocode(engine: engine, address: address) |> mapToSignal { cached -> Signal<(Double, Double)?, NoError> in if let cached = cached { return .single((cached.latitude, cached.longitude)) @@ -67,7 +60,7 @@ public func geocodeAddress(postbox: Postbox, address: DeviceContactAddressData) return geocodeLocation(dictionary: address.dictionary) |> mapToSignal { coordinate in if let (latitude, longitude) = coordinate { - return updateCachedGeocode(postbox: postbox, address: address, latitude: latitude, longitude: longitude) + return updateCachedGeocode(engine: engine, address: address, latitude: latitude, longitude: longitude) |> map(Optional.init) } else { return .single(nil) diff --git a/submodules/LocationUI/Sources/LocationPickerControllerNode.swift b/submodules/LocationUI/Sources/LocationPickerControllerNode.swift index fbcb0c307f..32a5ab79f9 100644 --- a/submodules/LocationUI/Sources/LocationPickerControllerNode.swift +++ b/submodules/LocationUI/Sources/LocationPickerControllerNode.swift @@ -420,12 +420,12 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM let home: Signal<(Double, Double)?, NoError> let work: Signal<(Double, Double)?, NoError> if let address = homeAddress { - home = geocodeAddress(postbox: context.account.postbox, address: address) + home = geocodeAddress(engine: context.engine, address: address) } else { home = .single(nil) } if let address = workAddress { - work = geocodeAddress(postbox: context.account.postbox, address: address) + work = geocodeAddress(engine: context.engine, address: address) } else { work = .single(nil) } diff --git a/submodules/LocationUI/Sources/LocationUtils.swift b/submodules/LocationUI/Sources/LocationUtils.swift index 6cd7effb50..b8a0ecb457 100644 --- a/submodules/LocationUI/Sources/LocationUtils.swift +++ b/submodules/LocationUI/Sources/LocationUtils.swift @@ -33,9 +33,8 @@ public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool } public func nearbyVenues(context: AccountContext, latitude: Double, longitude: Double, query: String? = nil) -> Signal<[TelegramMediaMap], NoError> { - return context.account.postbox.transaction { transaction -> SearchBotsConfiguration in - return currentSearchBotsConfiguration(transaction: transaction) - } |> mapToSignal { searchBotsConfiguration in + return context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots()) + |> mapToSignal { searchBotsConfiguration in return context.engine.peers.resolvePeerByName(name: searchBotsConfiguration.venueBotUsername ?? "foursquare") |> take(1) |> mapToSignal { peer -> Signal in diff --git a/submodules/MediaResources/Sources/MediaPlaybackStoredState.swift b/submodules/MediaResources/Sources/MediaPlaybackStoredState.swift index 15735b38f7..d9bef73942 100644 --- a/submodules/MediaResources/Sources/MediaPlaybackStoredState.swift +++ b/submodules/MediaResources/Sources/MediaPlaybackStoredState.swift @@ -29,35 +29,29 @@ public final class MediaPlaybackStoredState: Codable { } } -public func mediaPlaybackStoredState(postbox: Postbox, messageId: MessageId) -> Signal { - return postbox.transaction { transaction -> MediaPlaybackStoredState? in - let key = ValueBoxKey(length: 20) - key.setInt32(0, value: messageId.namespace) - key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) - key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) - key.setInt32(16, value: messageId.id) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, key: key))?.get(MediaPlaybackStoredState.self) { - return entry - } else { - return nil - } +public func mediaPlaybackStoredState(engine: TelegramEngine, messageId: MessageId) -> Signal { + let key = ValueBoxKey(length: 20) + key.setInt32(0, value: messageId.namespace) + key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) + key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) + key.setInt32(16, value: messageId.id) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key)) + |> map { entry -> MediaPlaybackStoredState? in + return entry?.get(MediaPlaybackStoredState.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 25, highWaterItemCount: 50) - -public func updateMediaPlaybackStoredStateInteractively(postbox: Postbox, messageId: MessageId, state: MediaPlaybackStoredState?) -> Signal { - return postbox.transaction { transaction -> Void in - let key = ValueBoxKey(length: 20) - key.setInt32(0, value: messageId.namespace) - key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) - key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) - key.setInt32(16, value: messageId.id) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, key: key) - if let state = state, let entry = CodableEntry(state) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } else { - transaction.removeItemCacheEntry(id: id) - } +public func updateMediaPlaybackStoredStateInteractively(engine: TelegramEngine, messageId: MessageId, state: MediaPlaybackStoredState?) -> Signal { + let key = ValueBoxKey(length: 20) + key.setInt32(0, value: messageId.namespace) + key.setInt32(4, value: messageId.peerId.namespace._internalGetInt32Value()) + key.setInt64(8, value: messageId.peerId.id._internalGetInt64Value()) + key.setInt32(16, value: messageId.id) + + if let state = state { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key, item: state) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.mediaPlaybackStoredState, id: key) } } diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index 16fd59a309..7294747475 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -387,11 +387,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } private func peerNearbyContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, present: @escaping (ViewController) -> Void) -> Signal<[ContextMenuItem], NoError> { - return context.account.postbox.transaction { _ -> [ContextMenuItem] in - let items: [ContextMenuItem] = [] - - return items - } + return .single([]) } private class PeersNearbyControllerImpl: ItemListController { diff --git a/submodules/Postbox/Sources/ItemCacheMetaTable.swift b/submodules/Postbox/Sources/ItemCacheMetaTable.swift index 9ff8c2c0fa..e9a1975b85 100644 --- a/submodules/Postbox/Sources/ItemCacheMetaTable.swift +++ b/submodules/Postbox/Sources/ItemCacheMetaTable.swift @@ -2,16 +2,6 @@ import Foundation public typealias ItemCacheCollectionId = Int8 -public struct ItemCacheCollectionSpec { - public let lowWaterItemCount: Int32 - public let highWaterItemCount: Int32 - - public init(lowWaterItemCount: Int32, highWaterItemCount: Int32) { - self.lowWaterItemCount = lowWaterItemCount - self.highWaterItemCount = highWaterItemCount - } -} - struct ItemCacheCollectionState: PostboxCoding { let nextAccessIndex: Int32 diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index e931d54cba..dded53e249 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -740,9 +740,9 @@ public final class Transaction { return self.postbox?.storedMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp) } - public func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry, collectionSpec: ItemCacheCollectionSpec) { + public func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry) { assert(!self.disposed) - self.postbox?.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) + self.postbox?.putItemCacheEntry(id: id, entry: entry) } public func removeItemCacheEntry(id: ItemCacheEntryId) { @@ -2351,7 +2351,7 @@ final class PostboxImpl { } } - fileprivate func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry, collectionSpec: ItemCacheCollectionSpec) { + fileprivate func putItemCacheEntry(id: ItemCacheEntryId, entry: CodableEntry) { self.itemCacheTable.put(id: id, entry: entry, metaTable: self.itemCacheMetaTable) self.currentUpdatedCacheEntryKeys.insert(id) } diff --git a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSoundsController.swift b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSoundsController.swift index 6edfb1b9c0..a2c275326c 100644 --- a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSoundsController.swift +++ b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSoundsController.swift @@ -675,9 +675,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions ActionSheetButtonItem(title: presentationData.strings.Notifications_Reset, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let modifyPeers = context.account.postbox.transaction { transaction -> Void in - transaction.resetAllPeerNotificationSettings(TelegramPeerNotificationSettings.defaultSettings) - } + let modifyPeers = context.engine.peers.resetAllPeerNotificationSettings() let updateGlobal = updateGlobalNotificationSettingsInteractively(postbox: context.account.postbox, { _ in return GlobalNotificationSettingsSet.defaultSettings }) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift index a420a24df4..cd1f8d11c5 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift @@ -222,9 +222,7 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri actionsDisposable.add(removePeerDisposable) let peersPromise = Promise<[SelectivePrivacyPeer]>() - peersPromise.set(context.account.postbox.transaction { transaction -> [SelectivePrivacyPeer] in - return Array(initialPeers.values) - }) + peersPromise.set(.single(Array(initialPeers.values))) let arguments = SelectivePrivacyPeersControllerArguments(context: context, setPeerIdWithRevealedOptions: { peerId, fromPeerId in updateState { state in diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift index 1016a473cb..1028217957 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift @@ -365,10 +365,10 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo self.addSubnode(self.listNode) let interaction = SettingsSearchInteraction(openItem: { result in - addRecentSettingsSearchItem(postbox: context.account.postbox, item: result.id) + addRecentSettingsSearchItem(engine: context.engine, item: result.id) openResult(result) }, deleteRecentItem: { id in - removeRecentSettingsSearchItem(postbox: context.account.postbox, item: id) + removeRecentSettingsSearchItem(engine: context.engine, item: id) }) let searchableItems = Promise<[SettingsSearchableItem]>() @@ -449,7 +449,7 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo |> deliverOnMainQueue).start(next: { [weak self] recentSearchItems, faqItems, presentationData in if let strongSelf = self { let recentHeader = ChatListSearchItemHeader(type: .recentPeers, theme: presentationData.theme, strings: presentationData.strings, actionTitle: presentationData.strings.WebSearch_RecentSectionClear, action: { - clearRecentSettingsSearchItems(postbox: context.account.postbox) + clearRecentSettingsSearchItems(engine: context.engine) }) let faqHeader = ChatListSearchItemHeader(type: .faq, theme: presentationData.theme, strings: presentationData.strings) diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchRecentQueries.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchRecentQueries.swift index 158a5645f6..5168028286 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchRecentQueries.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchRecentQueries.swift @@ -1,6 +1,7 @@ import Foundation import UIKit import Postbox +import TelegramCore import SwiftSignalKit import TelegramUIPreferences @@ -37,42 +38,32 @@ public final class RecentSettingsSearchQueryItem: Codable { } } -func addRecentSettingsSearchItem(postbox: Postbox, item: SettingsSearchableItemId) { - let _ = (postbox.transaction { transaction in - let itemId = SettingsSearchRecentQueryItemId(item.index) - if let entry = CodableEntry(RecentSettingsSearchQueryItem()) { - transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100) - } - }).start() +func addRecentSettingsSearchItem(engine: TelegramEngine, item: SettingsSearchableItemId) { + let itemId = SettingsSearchRecentQueryItemId(item.index) + let _ = engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, id: itemId.rawValue, item: RecentSettingsSearchQueryItem(), removeTailIfCountExceeds: 100).start() } -func removeRecentSettingsSearchItem(postbox: Postbox, item: SettingsSearchableItemId) { - let _ = (postbox.transaction { transaction -> Void in - let itemId = SettingsSearchRecentQueryItemId(item.index) - transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, itemId: itemId.rawValue) - }).start() +func removeRecentSettingsSearchItem(engine: TelegramEngine, item: SettingsSearchableItemId) { + let itemId = SettingsSearchRecentQueryItemId(item.index) + let _ = engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, id: itemId.rawValue).start() } -func clearRecentSettingsSearchItems(postbox: Postbox) { - let _ = (postbox.transaction { transaction -> Void in - transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems, items: []) - }).start() +func clearRecentSettingsSearchItems(engine: TelegramEngine) { + let _ = engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems).start() } func settingsSearchRecentItems(postbox: Postbox) -> Signal<[SettingsSearchableItemId], NoError> { return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)]) - |> mapToSignal { view -> Signal<[SettingsSearchableItemId], NoError> in - return postbox.transaction { transaction -> [SettingsSearchableItemId] in - var result: [SettingsSearchableItemId] = [] - if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)] as? OrderedItemListView { - for item in view.items { - let index = SettingsSearchRecentQueryItemId(item.id).value - if let itemId = SettingsSearchableItemId(index: index) { - result.append(itemId) - } + |> map { view -> [SettingsSearchableItemId] in + var result: [SettingsSearchableItemId] = [] + if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.settingsSearchRecentItems)] as? OrderedItemListView { + for item in view.items { + let index = SettingsSearchRecentQueryItemId(item.id).value + if let itemId = SettingsSearchableItemId(index: index) { + result.append(itemId) } } - return result } + return result } } diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 3d319da1cf..0b894e70a8 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -599,7 +599,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll let resolvedWallpaper: TelegramWallpaper? if let theme = theme, case let .file(file) = theme.chat.defaultWallpaper, file.id != 0 { resolvedWallpaper = theme.chat.defaultWallpaper - updateCachedWallpaper(account: context.account, wallpaper: theme.chat.defaultWallpaper) + updateCachedWallpaper(engine: context.engine, wallpaper: theme.chat.defaultWallpaper) } else { resolvedWallpaper = nil } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift index 540ec13610..d794567dd5 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift @@ -433,7 +433,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { let query = strongSelf.queryValue.query if !query.isEmpty { - let _ = addRecentWallpaperSearchQuery(postbox: strongSelf.context.account.postbox, string: query).start() + let _ = addRecentWallpaperSearchQuery(engine: strongSelf.context.engine, string: query).start() } } }, selectColor: { [weak self] color in @@ -444,12 +444,10 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { return query }, updateInterface: true) }, deleteRecentQuery: { query in - let _ = removeRecentWallpaperSearchQuery(postbox: context.account.postbox, string: query).start() + let _ = removeRecentWallpaperSearchQuery(engine: context.engine, string: query).start() }) - let configuration = self.context.account.postbox.transaction { transaction -> SearchBotsConfiguration in - return currentSearchBotsConfiguration(transaction: transaction) - } + let configuration = self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots()) let foundItems = self.queryPromise.get() |> mapToSignal { query -> Signal<([ThemeGridSearchEntry], Bool)?, NoError> in @@ -582,7 +580,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { } let header = ChatListSearchItemHeader(type: .recentPeers, theme: presentationData.theme, strings: presentationData.strings, actionTitle: presentationData.strings.WebSearch_RecentSectionClear, action: { - _ = clearRecentWallpaperSearchQueries(postbox: strongSelf.context.account.postbox).start() + let _ = clearRecentWallpaperSearchQueries(engine: strongSelf.context.engine).start() }) let previousEntries = previousRecentItems.swap(entries) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperSearchRecentQueries.swift b/submodules/SettingsUI/Sources/Themes/WallpaperSearchRecentQueries.swift index 0f4bd3a2cd..179b87ded6 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperSearchRecentQueries.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperSearchRecentQueries.swift @@ -1,5 +1,6 @@ import Foundation import Postbox +import TelegramCore import SwiftSignalKit import TelegramUIPreferences @@ -34,42 +35,36 @@ public final class RecentWallpaperSearchQueryItem: Codable { } } -func addRecentWallpaperSearchQuery(postbox: Postbox, string: String) -> Signal { - return postbox.transaction { transaction in - if let itemId = WallpaperSearchRecentQueryItemId(string) { - if let entry = CodableEntry(RecentWallpaperSearchQueryItem()) { - transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100) - } - } +func addRecentWallpaperSearchQuery(engine: TelegramEngine, string: String) -> Signal { + if let itemId = WallpaperSearchRecentQueryItemId(string) { + return engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, id: itemId.rawValue, item: RecentWallpaperSearchQueryItem(), removeTailIfCountExceeds: 100) + } else { + return .complete() } } -func removeRecentWallpaperSearchQuery(postbox: Postbox, string: String) -> Signal { - return postbox.transaction { transaction -> Void in - if let itemId = WallpaperSearchRecentQueryItemId(string) { - transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, itemId: itemId.rawValue) - } +func removeRecentWallpaperSearchQuery(engine: TelegramEngine, string: String) -> Signal { + if let itemId = WallpaperSearchRecentQueryItemId(string) { + return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, id: itemId.rawValue) + } else { + return .complete() } } -func clearRecentWallpaperSearchQueries(postbox: Postbox) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries, items: []) - } +func clearRecentWallpaperSearchQueries(engine: TelegramEngine) -> Signal { + return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries) } func wallpaperSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> { return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)]) - |> mapToSignal { view -> Signal<[String], NoError> in - return postbox.transaction { transaction -> [String] in - var result: [String] = [] - if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)] as? OrderedItemListView { - for item in view.items { - let value = WallpaperSearchRecentQueryItemId(item.id).value - result.append(value) - } - } - return result + |> map { view -> [String] in + var result: [String] = [] + if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.wallpaperSearchRecentQueries)] as? OrderedItemListView { + for item in view.items { + let value = WallpaperSearchRecentQueryItemId(item.id).value + result.append(value) } + } + return result } } diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index bba1391f98..2986094052 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -673,24 +673,19 @@ public final class ShareController: ViewController { for (id, status, error) in statuses { if let error = error { Queue.mainQueue().async { - let _ = (account.postbox.transaction { transaction -> Peer? in - TelegramEngine(account: account).messages.deleteMessages(transaction: transaction, ids: [id]) - return transaction.getPeer(id.peerId) - } + let _ = TelegramEngine(account: account).messages.deleteMessagesInteractively(messageIds: [id], type: .forEveryone).start() + let _ = (TelegramEngine(account: account).data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id.peerId)) |> deliverOnMainQueue).start(next: { peer in guard let strongSelf = self, let peer = peer else { return } if !displayedError, case .slowmodeActive = error { displayedError = true - strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) } }) } } - let _ = account.postbox.transaction({ transaction in - - }).start() if status != nil { hasStatuses = true } diff --git a/submodules/TelegramCallsUI/Sources/PresentationCall.swift b/submodules/TelegramCallsUI/Sources/PresentationCall.swift index a3fbe2a1ae..91c8bf2189 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCall.swift @@ -211,7 +211,6 @@ public final class PresentationCallImpl: PresentationCall { private let serializedData: String? private let dataSaving: VoiceCallDataSaving - private let derivedState: VoipDerivedState private let proxyServer: ProxyServerSettings? private let auxiliaryServers: [OngoingCallContext.AuxiliaryServer] private let currentNetworkType: NetworkType @@ -307,7 +306,6 @@ public final class PresentationCallImpl: PresentationCall { callKitIntegration: CallKitIntegration?, serializedData: String?, dataSaving: VoiceCallDataSaving, - derivedState: VoipDerivedState, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), initialState: CallSession?, internalId: CallSessionInternalId, @@ -363,7 +361,6 @@ public final class PresentationCallImpl: PresentationCall { self.serializedData = serializedData self.dataSaving = dataSaving - self.derivedState = derivedState self.proxyServer = proxyServer self.currentNetworkType = currentNetworkType self.updatedNetworkType = updatedNetworkType @@ -692,7 +689,7 @@ public final class PresentationCallImpl: PresentationCall { let updatedConnections = connections - let ongoingContext = OngoingCallContext(account: self.context.account, callSessionManager: self.callSessionManager, callId: id, internalId: self.internalId, proxyServer: proxyServer, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, derivedState: self.derivedState, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: updatedConnections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, enableTCP: self.enableTCP, enableStunMarking: self.enableStunMarking, audioSessionActive: self.audioSessionActive.get(), logName: logName, preferredVideoCodec: self.preferredVideoCodec) + let ongoingContext = OngoingCallContext(account: self.context.account, callSessionManager: self.callSessionManager, callId: id, internalId: self.internalId, proxyServer: proxyServer, initialNetworkType: self.currentNetworkType, updatedNetworkType: self.updatedNetworkType, serializedData: self.serializedData, dataSaving: dataSaving, key: key, isOutgoing: sessionState.isOutgoing, video: self.videoCapturer, connections: updatedConnections, maxLayer: maxLayer, version: version, allowP2P: allowsP2P, enableTCP: self.enableTCP, enableStunMarking: self.enableStunMarking, audioSessionActive: self.audioSessionActive.get(), logName: logName, preferredVideoCodec: self.preferredVideoCodec) self.ongoingContext = ongoingContext ongoingContext.setIsMuted(self.isMutedValue) if let requestedVideoAspect = self.requestedVideoAspect { diff --git a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift index 525514c4d0..1b8988d4ab 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift @@ -287,14 +287,13 @@ public final class PresentationCallManagerImpl: PresentationCallManager { private func ringingStatesUpdated(_ ringingStates: [(AccountContext, Peer, CallSessionRingingState, Bool, NetworkType)], enableCallKit: Bool) { if let firstState = ringingStates.first { if self.currentCall == nil && self.currentGroupCall == nil { - self.currentCallDisposable.set((combineLatest(firstState.0.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1)) + self.currentCallDisposable.set((combineLatest(firstState.0.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1)) |> deliverOnMainQueue).start(next: { [weak self] preferences, sharedData in guard let strongSelf = self else { return } let configuration = preferences.values[PreferencesKeys.voipConfiguration]?.get(VoipConfiguration.self) ?? .defaultValue - let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState]?.get(VoipDerivedState.self) ?? .default let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings]?.get(AutodownloadSettings.self) ?? .defaultSettings let experimentalSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings]?.get(ExperimentalUISettings.self) ?? .defaultSettings let appConfiguration = preferences.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue @@ -306,7 +305,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager { callKitIntegration: enableCallKit ? callKitIntegrationIfEnabled(strongSelf.callKitIntegration, settings: strongSelf.callSettings) : nil, serializedData: configuration.serializedData, dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings), - derivedState: derivedState, getDeviceAccessData: strongSelf.getDeviceAccessData, initialState: nil, internalId: firstState.2.id, @@ -508,7 +506,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager { return (combineLatest(queue: .mainQueue(), request, networkType |> take(1), context.account.postbox.peerView(id: peerId) |> map { peerView -> Bool in return peerView.peerIsContact - } |> take(1), context.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, ApplicationSpecificPreferencesKeys.voipDerivedState, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1), areVideoCallsAvailable) + } |> take(1), context.account.postbox.preferencesView(keys: [PreferencesKeys.voipConfiguration, PreferencesKeys.appConfiguration]) |> take(1), accountManager.sharedData(keys: [SharedDataKeys.autodownloadSettings, ApplicationSpecificSharedDataKeys.experimentalUISettings]) |> take(1), areVideoCallsAvailable) |> deliverOnMainQueue |> beforeNext { internalId, currentNetworkType, isContact, preferences, sharedData, areVideoCallsAvailable in if let strongSelf = self, accessEnabled { @@ -517,7 +515,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager { } let configuration = preferences.values[PreferencesKeys.voipConfiguration]?.get(VoipConfiguration.self) ?? .defaultValue - let derivedState = preferences.values[ApplicationSpecificPreferencesKeys.voipDerivedState]?.get(VoipDerivedState.self) ?? .default let autodownloadSettings = sharedData.entries[SharedDataKeys.autodownloadSettings]?.get(AutodownloadSettings.self) ?? .defaultSettings let appConfiguration = preferences.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue @@ -535,7 +532,6 @@ public final class PresentationCallManagerImpl: PresentationCallManager { ), serializedData: configuration.serializedData, dataSaving: effectiveDataSaving(for: strongSelf.callSettings, autodownloadSettings: autodownloadSettings), - derivedState: derivedState, getDeviceAccessData: strongSelf.getDeviceAccessData, initialState: nil, internalId: internalId, diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index e77aa38bdd..151c19a43a 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -1708,17 +1708,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { |> distinctUntilChanged |> runOn(.mainQueue()) } else { - peerAdminIds = strongSelf.account.postbox.transaction { transaction -> [PeerId] in - var result: [PeerId] = [] - if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData { - if let participants = cachedData.participants { - for participant in participants.participants { - if case .creator = participant { - result.append(participant.peerId) - } else if case .admin = participant { - result.append(participant.peerId) - } - } + peerAdminIds = strongSelf.accountContext.engine.data.get( + TelegramEngine.EngineData.Item.Peer.LegacyGroupParticipants(id: peerId) + ) + |> map { participants -> [EnginePeer.Id] in + guard case let .known(participants) = participants else { + return [] + } + var result: [EnginePeer.Id] = [] + for participant in participants { + if case .creator = participant { + result.append(participant.peerId) + } else if case .admin = participant { + result.append(participant.peerId) } } return result @@ -1801,17 +1803,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } else if case .invalidJoinAsPeer = error { let peerId = strongSelf.peerId let _ = strongSelf.accountContext.engine.calls.clearCachedGroupCallDisplayAsAvailablePeers(peerId: peerId).start() - let _ = (strongSelf.accountContext.account.postbox.transaction { transaction -> Void in - transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in - if let current = current as? CachedChannelData { - return current.withUpdatedCallJoinPeerId(nil) - } else if let current = current as? CachedGroupData { - return current.withUpdatedCallJoinPeerId(nil) - } else { - return current - } - }) - }).start() } strongSelf.markAsCanBeRemoved() })) diff --git a/submodules/TelegramCore/Sources/Settings/ContentSettings.swift b/submodules/TelegramCore/Sources/Settings/ContentSettings.swift index b3b0b9d160..077f47f26a 100644 --- a/submodules/TelegramCore/Sources/Settings/ContentSettings.swift +++ b/submodules/TelegramCore/Sources/Settings/ContentSettings.swift @@ -13,7 +13,7 @@ public struct ContentSettings: Equatable { } } -private extension ContentSettings { +extension ContentSettings { init(appConfiguration: AppConfiguration) { var reasons: [String] = [] if let data = appConfiguration.data, let reasonsData = data["ignore_restriction_reasons"] as? [String] { diff --git a/submodules/TelegramCore/Sources/Settings/PeerContactSettings.swift b/submodules/TelegramCore/Sources/Settings/PeerContactSettings.swift index 3182f41a13..b63d453e09 100644 --- a/submodules/TelegramCore/Sources/Settings/PeerContactSettings.swift +++ b/submodules/TelegramCore/Sources/Settings/PeerContactSettings.swift @@ -39,7 +39,8 @@ extension PeerStatusSettings { public func unarchiveAutomaticallyArchivedPeer(account: Account, peerId: PeerId) { let _ = (account.postbox.transaction { transaction -> Void in - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) + _internal_updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) + transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in if let currentData = current as? CachedUserData, let currentStatusSettings = currentData.peerStatusSettings { var statusSettings = currentStatusSettings diff --git a/submodules/TelegramCore/Sources/State/AvailableReactions.swift b/submodules/TelegramCore/Sources/State/AvailableReactions.swift index 4d9907e4dd..105613876a 100644 --- a/submodules/TelegramCore/Sources/State/AvailableReactions.swift +++ b/submodules/TelegramCore/Sources/State/AvailableReactions.swift @@ -258,7 +258,7 @@ func _internal_setCachedAvailableReactions(transaction: Transaction, availableRe key.setInt64(0, value: 0) if let entry = CodableEntry(availableReactions) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.availableReactions, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.availableReactions, key: key), entry: entry) } } diff --git a/submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift b/submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift index 307a8f24e0..0d56508966 100644 --- a/submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift +++ b/submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift @@ -2,9 +2,6 @@ import Foundation import Postbox import SwiftSignalKit - -private let cachedSentMediaCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10000, highWaterItemCount: 20000) - enum CachedSentMediaReferenceKey { case image(hash: Data) case file(hash: Data) @@ -39,5 +36,5 @@ func cachedSentMediaReference(postbox: Postbox, key: CachedSentMediaReferenceKey } func storeCachedSentMediaReference(transaction: Transaction, key: CachedSentMediaReferenceKey, media: Media) { - //transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key), entry: media, collectionSpec: cachedSentMediaCollectionSpec) + //transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSentMediaReferences, key: key.key), entry: media) } diff --git a/submodules/TelegramCore/Sources/State/SynchronizeGroupedPeersOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeGroupedPeersOperation.swift index 26eeb4b465..e9c7ec2531 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeGroupedPeersOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeGroupedPeersOperation.swift @@ -2,14 +2,7 @@ import Foundation import Postbox import SwiftSignalKit - -public func updatePeerGroupIdInteractively(postbox: Postbox, peerId: PeerId, groupId: PeerGroupId) -> Signal { - return postbox.transaction { transaction -> Void in - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: groupId) - } -} - -public func updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) { +func _internal_updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) { let initialInclusion = transaction.getPeerChatListInclusion(peerId) var updatedInclusion = initialInclusion switch initialInclusion { diff --git a/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift b/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift index b3b5d74eb4..4078d75f68 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift @@ -40,7 +40,7 @@ func addRecentlyUsedSticker(transaction: Transaction, fileReference: FileMediaRe } } -public func clearRecentlyUsedStickers(transaction: Transaction) { +func _internal_clearRecentlyUsedStickers(transaction: Transaction) { transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudRecentStickers, items: []) addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .clear) } diff --git a/submodules/TelegramCore/Sources/State/SynchronizeSavedGifsOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeSavedGifsOperation.swift index d9dd0f2602..78ec4caada 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeSavedGifsOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeSavedGifsOperation.swift @@ -23,7 +23,7 @@ func addSynchronizeSavedGifsOperation(transaction: Transaction, operation: Synch transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeSavedGifsOperation(content: .sync)) } -public func isGifSaved(transaction: Transaction, mediaId: MediaId) -> Bool { +public func getIsGifSaved(transaction: Transaction, mediaId: MediaId) -> Bool { if transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: RecentMediaItemId(mediaId).rawValue) != nil { return true } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift index 01c1c18da7..a9d94da795 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift @@ -353,7 +353,7 @@ func _internal_cacheTwoStepPasswordToken(postbox: Postbox, token: TemporaryTwoSt let key = ValueBoxKey(length: 1) key.setUInt8(0, value: 0) if let token = token.flatMap(CodableEntry.init) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key), entry: token, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key), entry: token) } else { transaction.removeItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedTwoStepToken, key: key)) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index 5e11c473fb..7453cb4b8e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -480,6 +480,18 @@ func _internal_joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, } else if error.errorDescription == "GROUPCALL_PARTICIPANTS_TOO_MUCH" { return .fail(.tooManyParticipants) } else if error.errorDescription == "JOIN_AS_PEER_INVALID" { + let _ = (account.postbox.transaction { transaction -> Void in + transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in + if let current = current as? CachedChannelData { + return current.withUpdatedCallJoinPeerId(nil) + } else if let current = current as? CachedGroupData { + return current.withUpdatedCallJoinPeerId(nil) + } else { + return current + } + }) + }).start() + return .fail(.invalidJoinAsPeer) } else if error.errorDescription == "GROUPCALL_INVALID" { return account.postbox.transaction { transaction -> Signal in @@ -2381,7 +2393,7 @@ func _internal_cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: return account.postbox.transaction { transaction -> [FoundPeer] in let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) if let entry = CodableEntry(CachedDisplayAsPeers(peerIds: peers.map { $0.peer.id }, timestamp: currentTimestamp)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedGroupCallDisplayAsPeers, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedGroupCallDisplayAsPeers, key: key), entry: entry) } return peers } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/Configuration.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/Configuration.swift index 9f229e9994..2c8297da86 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/Configuration.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/Configuration.swift @@ -11,6 +11,7 @@ public enum EngineConfiguration { public var maxSupergroupMemberCount: Int32 public var maxMessageForwardBatchSize: Int32 public var maxSavedGifCount: Int32 + public var maxFavedStickerCount: Int32 public var maxRecentStickerCount: Int32 public var maxMessageEditingInterval: Int32 public var maxMediaCaptionLength: Int32 @@ -25,6 +26,7 @@ public enum EngineConfiguration { maxSupergroupMemberCount: Int32, maxMessageForwardBatchSize: Int32, maxSavedGifCount: Int32, + maxFavedStickerCount: Int32, maxRecentStickerCount: Int32, maxMessageEditingInterval: Int32, maxMediaCaptionLength: Int32, @@ -38,6 +40,7 @@ public enum EngineConfiguration { self.maxSupergroupMemberCount = maxSupergroupMemberCount self.maxMessageForwardBatchSize = maxMessageForwardBatchSize self.maxSavedGifCount = maxSavedGifCount + self.maxFavedStickerCount = maxFavedStickerCount self.maxRecentStickerCount = maxRecentStickerCount self.maxMessageEditingInterval = maxMessageEditingInterval self.maxMediaCaptionLength = maxMediaCaptionLength @@ -89,7 +92,9 @@ public enum EngineConfiguration { } } -extension EngineConfiguration.Limits { +public typealias EngineContentSettings = ContentSettings + +public extension EngineConfiguration.Limits { init(_ limitsConfiguration: LimitsConfiguration) { self.init( maxPinnedChatCount: limitsConfiguration.maxPinnedChatCount, @@ -98,6 +103,7 @@ extension EngineConfiguration.Limits { maxSupergroupMemberCount: limitsConfiguration.maxSupergroupMemberCount, maxMessageForwardBatchSize: limitsConfiguration.maxMessageForwardBatchSize, maxSavedGifCount: limitsConfiguration.maxSavedGifCount, + maxFavedStickerCount: limitsConfiguration.maxFavedStickerCount, maxRecentStickerCount: limitsConfiguration.maxRecentStickerCount, maxMessageEditingInterval: limitsConfiguration.maxMessageEditingInterval, maxMediaCaptionLength: limitsConfiguration.maxMediaCaptionLength, @@ -106,6 +112,24 @@ extension EngineConfiguration.Limits { maxMessageRevokeIntervalInPrivateChats: limitsConfiguration.maxMessageRevokeIntervalInPrivateChats ) } + + func _asLimits() -> LimitsConfiguration { + return LimitsConfiguration( + maxPinnedChatCount: self.maxPinnedChatCount, + maxArchivedPinnedChatCount: self.maxArchivedPinnedChatCount, + maxGroupMemberCount: self.maxGroupMemberCount, + maxSupergroupMemberCount: self.maxSupergroupMemberCount, + maxMessageForwardBatchSize: self.maxMessageForwardBatchSize, + maxSavedGifCount: self.maxSavedGifCount, + maxRecentStickerCount: self.maxRecentStickerCount, + maxFavedStickerCount: self.maxFavedStickerCount, + maxMessageEditingInterval: self.maxMessageEditingInterval, + maxMediaCaptionLength: self.maxMediaCaptionLength, + canRemoveIncomingMessagesInPrivateChats: self.canRemoveIncomingMessagesInPrivateChats, + maxMessageRevokeInterval: self.maxMessageRevokeInterval, + maxMessageRevokeIntervalInPrivateChats: self.maxMessageRevokeIntervalInPrivateChats + ) + } } public extension EngineConfiguration.UserLimits { @@ -155,6 +179,27 @@ public extension EngineConfiguration.SearchBots { public extension TelegramEngine.EngineData.Item { enum Configuration { + public struct App: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = AppConfiguration + + public init() { + } + + var key: PostboxViewKey { + return .preferences(keys: Set([PreferencesKeys.appConfiguration])) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? PreferencesView else { + preconditionFailure() + } + guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else { + return AppConfiguration.defaultValue + } + return appConfiguration + } + } + public struct Limits: TelegramEngineDataItem, PostboxViewDataItem { public typealias Result = EngineConfiguration.Limits @@ -240,5 +285,49 @@ public extension TelegramEngine.EngineData.Item { return EngineConfiguration.SearchBots(value) } } + + public struct ApplicationSpecificPreference: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = PreferencesEntry? + + private let itemKey: ValueBoxKey + public init(key: ValueBoxKey) { + self.itemKey = key + } + + var key: PostboxViewKey { + return .preferences(keys: Set([self.itemKey])) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? PreferencesView else { + preconditionFailure() + } + guard let value = view.values[self.itemKey] else { + return nil + } + return value + } + } + + public struct ContentSettings: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = EngineContentSettings + + public init() { + } + + var key: PostboxViewKey { + return .preferences(keys: Set([PreferencesKeys.appConfiguration])) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? PreferencesView else { + preconditionFailure() + } + guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else { + return EngineContentSettings(appConfiguration: AppConfiguration.defaultValue) + } + return EngineContentSettings(appConfiguration: appConfiguration) + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/ItemCache.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/ItemCache.swift new file mode 100644 index 0000000000..8227f2ab26 --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/ItemCache.swift @@ -0,0 +1,29 @@ +import SwiftSignalKit +import Postbox + +public extension TelegramEngine.EngineData.Item { + enum ItemCache { + public struct Item: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = CodableEntry? + + private let collectionId: Int8 + private let id: ValueBoxKey + + public init(collectionId: Int8, id: ValueBoxKey) { + self.collectionId = collectionId + self.id = id + } + + var key: PostboxViewKey { + return .cachedItem(ItemCacheEntryId(collectionId: collectionId, key: self.id)) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedItemView else { + preconditionFailure() + } + return view.value + } + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/Messages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/Messages.swift index 6c7eb13d8b..af5a5064c2 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/Messages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/Messages.swift @@ -127,6 +127,31 @@ public extension TelegramEngine.EngineData.Item { return result } } + + public struct ReadState: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = CombinedPeerReadState? + + fileprivate let id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + var key: PostboxViewKey { + return .combinedReadState(peerId: self.id) + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CombinedReadStateView else { + preconditionFailure() + } + + return view.state + } + } public struct PeerUnreadCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public typealias Result = Int @@ -144,7 +169,7 @@ public extension TelegramEngine.EngineData.Item { self.id = id } - func extract(view: PostboxView) -> Int { + func extract(view: PostboxView) -> Result { guard let view = view as? UnreadMessageCountsView else { preconditionFailure() } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeerSummary.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeerSummary.swift index 61cc894da5..ce1435d5e8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeerSummary.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeerSummary.swift @@ -8,6 +8,81 @@ public enum EnginePeerCachedInfoItem { case unknown } +public enum EngineChannelParticipant: Equatable { + case creator(id: EnginePeer.Id, adminInfo: ChannelParticipantAdminInfo?, rank: String?) + case member(id: EnginePeer.Id, invitedAt: Int32, adminInfo: ChannelParticipantAdminInfo?, banInfo: ChannelParticipantBannedInfo?, rank: String?) + + public var peerId: EnginePeer.Id { + switch self { + case let .creator(id, _, _): + return id + case let .member(id, _, _, _, _): + return id + } + } +} + +public extension EngineChannelParticipant { + init(_ participant: ChannelParticipant) { + switch participant { + case let .creator(id, adminInfo, rank): + self = .creator(id: id, adminInfo: adminInfo, rank: rank) + case let .member(id, invitedAt, adminInfo, banInfo, rank): + self = .member(id: id, invitedAt: invitedAt, adminInfo: adminInfo, banInfo: banInfo, rank: rank) + } + } + + func _asParticipant() -> ChannelParticipant { + switch self { + case let .creator(id, adminInfo, rank): + return .creator(id: id, adminInfo: adminInfo, rank: rank) + case let .member(id, invitedAt, adminInfo, banInfo, rank): + return .member(id: id, invitedAt: invitedAt, adminInfo: adminInfo, banInfo: banInfo, rank: rank) + } + } +} + +public enum EngineLegacyGroupParticipant: Equatable { + case member(id: EnginePeer.Id, invitedBy: EnginePeer.Id, invitedAt: Int32) + case creator(id: EnginePeer.Id) + case admin(id: EnginePeer.Id, invitedBy: EnginePeer.Id, invitedAt: Int32) + + public var peerId: EnginePeer.Id { + switch self { + case let .member(id, _, _): + return id + case let .creator(id): + return id + case let .admin(id, _, _): + return id + } + } +} + +public extension EngineLegacyGroupParticipant { + init(_ participant: GroupParticipant) { + switch participant { + case let .member(id, invitedBy, invitedAt): + self = .member(id: id, invitedBy: invitedBy, invitedAt: invitedAt) + case let .creator(id): + self = .creator(id: id) + case let .admin(id, invitedBy, invitedAt): + self = .admin(id: id, invitedBy: invitedBy, invitedAt: invitedAt) + } + } + + func _asParticipant() -> GroupParticipant { + switch self { + case let .member(id, invitedBy, invitedAt): + return .member(id: id, invitedBy: invitedBy, invitedAt: invitedAt) + case let .creator(id): + return .creator(id: id) + case let .admin(id, invitedBy, invitedAt): + return .admin(id: id, invitedBy: invitedBy, invitedAt: invitedAt) + } + } +} + public extension TelegramEngine.EngineData.Item { enum NotificationSettings { public struct Global: TelegramEngineDataItem, PostboxViewDataItem { @@ -675,5 +750,37 @@ public extension TelegramEngine.EngineData.Item { } } } + + public struct LegacyGroupParticipants: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = EnginePeerCachedInfoItem<[EngineLegacyGroupParticipant]> + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + var key: PostboxViewKey { + return .cachedPeerData(peerId: self.id) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedPeerDataView else { + preconditionFailure() + } + if let cachedData = view.cachedPeerData as? CachedGroupData { + if let participants = cachedData.participants { + return .known(participants.participants.map(EngineLegacyGroupParticipant.init)) + } else { + return .unknown + } + } else { + return .unknown + } + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/ItemCache/TelegramEngineItemCache.swift b/submodules/TelegramCore/Sources/TelegramEngine/ItemCache/TelegramEngineItemCache.swift new file mode 100644 index 0000000000..8ca176672c --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/ItemCache/TelegramEngineItemCache.swift @@ -0,0 +1,29 @@ +import Foundation +import SwiftSignalKit +import Postbox + +public extension TelegramEngine { + final class ItemCache { + private let account: Account + + init(account: Account) { + self.account = account + } + + public func put(collectionId: Int8, id: ValueBoxKey, item: T) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + if let entry = CodableEntry(item) { + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: collectionId, key: id), entry: entry) + } + } + |> ignoreValues + } + + public func remove(collectionId: Int8, id: ValueBoxKey) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + transaction.removeItemCacheEntry(id: ItemCacheEntryId(collectionId: collectionId, key: id)) + } + |> ignoreValues + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift index 11f8604116..b4db9bdc32 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift @@ -57,7 +57,7 @@ func _internal_availableLocalizations(postbox: Postbox, network: Network, allowC let infos: [LocalizationInfo] = languages.map(LocalizationInfo.init(apiLanguage:)) return postbox.transaction { transaction -> [LocalizationInfo] in if let entry = CodableEntry(CachedLocalizationInfos(list: infos)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)), entry: entry) } return infos } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index fa04f9b11e..49f8de5810 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -304,8 +304,6 @@ private class AdMessagesHistoryContextImpl { }, forKey: "messages") } - private static let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 5, highWaterItemCount: 10) - public static func getCached(postbox: Postbox, peerId: PeerId) -> Signal { return postbox.transaction { transaction -> CachedState? in let key = ValueBoxKey(length: 8) @@ -323,7 +321,7 @@ private class AdMessagesHistoryContextImpl { key.setInt64(0, value: peerId.toInt64()) let id = ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAdMessageStates, key: key) if let state = state, let entry = CodableEntry(state) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: id, entry: entry) } else { transaction.removeItemCacheEntry(id: id) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift index 80f02a38dd..22985d0bcb 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift @@ -176,7 +176,7 @@ public func clearPeerUnseenReactionsInteractively(account: Account, peerId: Peer |> ignoreValues } -public func markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) { +func _internal_markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) { for peerId in transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: filterPredicate) { togglePeerUnreadMarkInteractively(transaction: transaction, viewTracker: viewTracker, peerId: peerId, setToValue: false) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AttachMenuBots.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AttachMenuBots.swift index 1892584241..ee62b054b8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AttachMenuBots.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AttachMenuBots.swift @@ -222,7 +222,7 @@ private func setCachedAttachMenuBots(transaction: Transaction, attachMenuBots: A let entryId = ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.attachMenuBots, key: key) if let entry = CodableEntry(attachMenuBots) { - transaction.putItemCacheEntry(id: entryId, entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10)) + transaction.putItemCacheEntry(id: entryId, entry: entry) } else { transaction.removeItemCacheEntry(id: entryId) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Polls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Polls.swift index e4290a9a73..bfe5d5ab8c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Polls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Polls.swift @@ -149,8 +149,6 @@ func _internal_requestClosePoll(postbox: Postbox, network: Network, stateManager } } -private let cachedPollResultsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 20, highWaterItemCount: 40) - final class CachedPollOptionResult: Codable { let peerIds: [PeerId] let count: Int32 @@ -299,7 +297,7 @@ private final class PollResultsOptionContext { } if populateCache { if let entry = CodableEntry(CachedPollOptionResult(peerIds: resultPeers.map { $0.peerId }, count: count)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier)), entry: entry, collectionSpec: cachedPollResultsCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier)), entry: entry) } } return (resultPeers, Int(count), nextOffset) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift index 42394a57d6..813825597c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift @@ -33,8 +33,6 @@ public final class CachedChatContextResult: Codable { } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 40, highWaterItemCount: 60) - private struct RequestData: Codable { let version: String let botId: PeerId @@ -146,7 +144,7 @@ func _internal_requestChatContextResults(account: Account, botId: PeerId, peerId if let keyData = try? JSONEncoder().encode(requestData) { let key = ValueBoxKey(MemoryBuffer(data: keyData)) if let entry = CodableEntry(CachedChatContextResult(data: resultData, timestamp: Int32(Date().timeIntervalSince1970))) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedContextResults, key: key), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedContextResults, key: key), entry: entry) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift index bb9571419e..6286a65156 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift @@ -62,7 +62,7 @@ func _internal_cachedPeerSendAsAvailablePeers(account: Account, peerId: PeerId) return account.postbox.transaction { transaction -> [FoundPeer] in let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) if let entry = CodableEntry(CachedSendAsPeers(peerIds: peers.map { $0.peer.id }, timestamp: currentTimestamp)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSendAsPeers, key: key), entry: entry) } return peers } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index 7a1fd67ab9..31e0c5345c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -51,12 +51,15 @@ public extension TelegramEngine { return _internal_searchMessageIdByTimestamp(account: self.account, peerId: peerId, threadId: threadId, timestamp: timestamp) } - public func deleteMessages(transaction: Transaction, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) { - return _internal_deleteMessages(transaction: transaction, mediaBox: self.account.postbox.mediaBox, ids: ids, deleteMedia: deleteMedia, manualAddMessageThreadStatsDifference: manualAddMessageThreadStatsDifference) + public func deleteMessages(transaction: Transaction, ids: [MessageId]) { + return _internal_deleteMessages(transaction: transaction, mediaBox: self.account.postbox.mediaBox, ids: ids, deleteMedia: true, manualAddMessageThreadStatsDifference: nil) } - public func deleteAllMessagesWithAuthor(transaction: Transaction, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { - return _internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, authorId: authorId, namespace: namespace) + public func deleteAllMessagesWithAuthor(peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + _internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, authorId: authorId, namespace: namespace) + } + |> ignoreValues } public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, peerId: PeerId, forwardAuthorId: PeerId, namespace: MessageId.Namespace) { @@ -378,5 +381,27 @@ public extension TelegramEngine { return transaction.getMessageFailedGroup(id)?.map(EngineMessage.init) ?? [] } } + + public func unreadChatListPeerIds(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?) -> Signal<[EnginePeer.Id], NoError> { + return self.account.postbox.transaction { transaction -> [EnginePeer.Id] in + return transaction.getUnreadChatListPeerIds(groupId: groupId._asGroup(), filterPredicate: filterPredicate) + } + } + + public func markAllChatsAsReadInteractively(items: [(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?)]) -> Signal { + let account = self.account + return self.account.postbox.transaction { transaction -> Void in + for (groupId, filterPredicate) in items { + _internal_markAllChatsAsReadInteractively(transaction: transaction, viewTracker: account.viewTracker, groupId: groupId._asGroup(), filterPredicate: filterPredicate) + } + } + |> ignoreValues + } + + public func getRelativeUnreadChatListIndex(filtered: Bool, position: EngineChatList.RelativePosition, groupId: EngineChatList.Group) -> Signal { + return self.account.postbox.transaction { transaction -> EngineChatList.Item.Index? in + return transaction.getRelativeUnreadChatListIndex(filtered: filtered, position: position._asPosition(), groupId: groupId._asGroup()) + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift b/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift index 87a04bf2ff..4a7624a38c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/OrderedLists/TelegramEngineOrderedLists.swift @@ -10,6 +10,27 @@ public extension TelegramEngine { self.account = account } + public func addOrMoveToFirstPosition(collectionId: Int32, id: MemoryBuffer, item: T, removeTailIfCountExceeds: Int?) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + if let entry = CodableEntry(item) { + transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: collectionId, item: OrderedItemListEntry(id: id, contents: entry), removeTailIfCountExceeds: removeTailIfCountExceeds) + } + } + |> ignoreValues + } + public func clear(collectionId: Int32) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + transaction.replaceOrderedItemListItems(collectionId: collectionId, items: []) + } + |> ignoreValues + } + + public func removeItem(collectionId: Int32, id: MemoryBuffer) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + transaction.removeOrderedItemListItem(collectionId: collectionId, itemId: id) + } + |> ignoreValues + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift index 3a9d5ed71a..d90c0f814b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift @@ -317,8 +317,6 @@ func _internal_deleteAllRevokedPeerExportedInvitations(account: Account, peerId: |> switchToLatest } -private let cachedPeerExportedInvitationsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20) - public struct PeerExportedInvitationsState: Equatable { public var invitations: [ExportedInvitation] public var isLoadingMore: Bool @@ -500,7 +498,7 @@ private final class PeerExportedInvitationsContextImpl { let invitations: [ExportedInvitation] = invites.compactMap { ExportedInvitation(apiExportedInvite: $0) } if populateCache { if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: count >= 50, count: count)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry, collectionSpec: cachedPeerExportedInvitationsCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry) } } return (invitations, count) @@ -590,7 +588,7 @@ private final class PeerExportedInvitationsContextImpl { let count = self.count self.updateDisposable.set(self.account.postbox.transaction({ transaction in if let entry = CodableEntry(CachedPeerExportedInvitations(invitations: invitations, canLoadMore: canLoadMore, count: count)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry, collectionSpec: cachedPeerExportedInvitationsCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerExportedInvitations, key: CachedPeerExportedInvitations.key(peerId: peerId, revoked: revoked)), entry: entry) } }).start()) } @@ -660,10 +658,6 @@ public final class PeerExportedInvitationsContext { } } - - -private let cachedPeerInvitationImportersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20) - public struct PeerInvitationImportersState: Equatable { public struct Importer: Equatable { public var peer: RenderedPeer @@ -977,7 +971,7 @@ private final class PeerInvitationImportersContextImpl { } if populateCache && query == nil { if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry) } } return (resultImporters, count) @@ -1073,7 +1067,7 @@ private final class PeerInvitationImportersContextImpl { let link = self.link self.updateDisposables.add(self.account.postbox.transaction({ transaction in if let entry = CodableEntry(CachedPeerInvitationImporters(importers: resultImporters, count: count)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry, collectionSpec: cachedPeerInvitationImportersCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerInvitationImporters, key: CachedPeerInvitationImporters.key(peerId: peerId, link: link ?? "requests", requested: self.requested)), entry: entry) } }).start()) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationSoundList.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationSoundList.swift index 643824bc7a..4b2847d778 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationSoundList.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationSoundList.swift @@ -135,7 +135,7 @@ public func _internal_cachedNotificationSoundList(transaction: Transaction) -> N func _internal_setCachedNotificationSoundList(transaction: Transaction, notificationSoundList: NotificationSoundList) { if let entry = CodableEntry(notificationSoundList) { - transaction.putItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey(), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10)) + transaction.putItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey(), entry: entry) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift index d595bae9a2..edb1be713d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift @@ -3,14 +3,11 @@ import Postbox import TelegramApi import SwiftSignalKit - public enum RecentPeers { case peers([Peer]) case disabled } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1) - private func cachedRecentPeersEntryId() -> ItemCacheEntryId { return ItemCacheEntryId(collectionId: 101, key: CachedRecentPeers.cacheKey()) } @@ -82,13 +79,13 @@ func _internal_managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) if let entry = CodableEntry(CachedRecentPeers(enabled: true, ids: peers.map { $0.id })) { - transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry) } case .topPeersNotModified: break case .topPeersDisabled: if let entry = CodableEntry(CachedRecentPeers(enabled: false, ids: [])) { - transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry) } } } @@ -109,7 +106,7 @@ func _internal_removeRecentPeer(account: Account, peerId: PeerId) -> Signal Void in if !enabled { if let entry = CodableEntry(CachedRecentPeers(enabled: false, ids: [])) { - transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: entry) } } else { let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId())?.get(CachedRecentPeers.self) if let codableEntry = CodableEntry(CachedRecentPeers(enabled: true, ids: entry?.ids ?? [])) { - transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: codableEntry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: cachedRecentPeersEntryId(), entry: codableEntry) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift index d179804a00..fbc388cbc3 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift @@ -3,9 +3,6 @@ import Postbox import TelegramApi import SwiftSignalKit - -private let resolvedByNamePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200) - public enum ResolvePeerByNameOptionCached { case none case cached @@ -65,7 +62,7 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32 let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) if let entry = CodableEntry(CachedResolvedByNamePeer(peerId: peerId, timestamp: timestamp)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: entry, collectionSpec: resolvedByNamePeersCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: entry) } return peerId } @@ -78,8 +75,6 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32 } } -private let resolvedByPhonePeersCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 150, highWaterItemCount: 200) - func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int32 = 2 * 60 * 60 * 24) -> Signal { var normalizedPhone = phone if normalizedPhone.hasPrefix("+") { @@ -128,7 +123,7 @@ func _internal_resolvePeerByPhone(account: Account, phone: String, ageLimit: Int let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) if let entry = CodableEntry(CachedResolvedByPhonePeer(peerId: peerId, timestamp: timestamp)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByPhonePeers, key: CachedResolvedByPhonePeer.key(name: normalizedPhone)), entry: entry, collectionSpec: resolvedByNamePeersCollectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByPhonePeers, key: CachedResolvedByPhonePeer.key(name: normalizedPhone)), entry: entry) } return peerId } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 93f6b62634..6eeb70e3c7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -756,6 +756,22 @@ public extension TelegramEngine { } } } + + public func updatePeersGroupIdInteractively(peerIds: [EnginePeer.Id], groupId: EngineChatList.Group) -> Signal { + return self.account.postbox.transaction { transaction -> Void in + for peerId in peerIds { + _internal_updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: groupId._asGroup()) + } + } + |> ignoreValues + } + + public func resetAllPeerNotificationSettings() -> Signal { + return self.account.postbox.transaction { transaction -> Void in + transaction.resetAllPeerNotificationSettings(TelegramPeerNotificationSettings.defaultSettings) + } + |> ignoreValues + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdConfiguration.swift b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdConfiguration.swift index c101294da2..d0ef354b86 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdConfiguration.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdConfiguration.swift @@ -36,7 +36,7 @@ public func secureIdConfiguration(postbox: Postbox, network: Network) -> Signal< } return postbox.transaction { transaction -> SecureIdConfiguration in if let entry = CodableEntry(parsed) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSecureIdConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedSecureIdConfiguration, key: ValueBoxKey(length: 0)), entry: entry) } return parsed.value } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift index 1d1b28301d..8c71c80536 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift @@ -3,9 +3,6 @@ import Postbox import SwiftSignalKit import MurMurHash32 - -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200) - public enum CachedStickerPackResult { case none case fetching @@ -14,10 +11,10 @@ public enum CachedStickerPackResult { func cacheStickerPack(transaction: Transaction, info: StickerPackCollectionInfo, items: [StickerPackItem], reference: StickerPackReference? = nil) { if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(info.id)), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(info.id)), entry: entry) } if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(shortName: info.shortName.lowercased())), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(shortName: info.shortName.lowercased())), entry: entry) } if let reference = reference { @@ -38,7 +35,7 @@ func cacheStickerPack(transaction: Transaction, info: StickerPackCollectionInfo, } if let namespace = namespace, let id = id { if let entry = CodableEntry(CachedStickerPack(info: info, items: items, hash: info.hash)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))), entry: entry) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift index 04fafcb902..7060d8e146 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift @@ -43,8 +43,6 @@ public final class FoundStickerItem: Equatable { } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200) - public struct SearchStickersScope: OptionSet { public var rawValue: Int32 @@ -244,7 +242,7 @@ func _internal_searchStickers(account: Account, query: String, scope: SearchStic let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(query)), entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerQueryResults, key: CachedStickerQueryResult.cacheKey(query)), entry: entry) } return result diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift index f2360e5dd7..f82e3afc7a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift @@ -118,5 +118,18 @@ public extension TelegramEngine { return getIsStickerSaved(transaction: transaction, fileId: id) } } + + public func isGifSaved(id: EngineMedia.Id) -> Signal { + return self.account.postbox.transaction { transaction -> Bool in + return getIsGifSaved(transaction: transaction, mediaId: id) + } + } + + public func clearRecentlyUsedStickers() -> Signal { + return self.account.postbox.transaction { transaction -> Void in + _internal_clearRecentlyUsedStickers(transaction: transaction) + } + |> ignoreValues + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index fe567190d2..cc2804b4aa 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -79,6 +79,10 @@ public final class TelegramEngine { public lazy var orderedLists: OrderedLists = { return OrderedLists(account: self.account) }() + + public lazy var itemCache: ItemCache = { + return ItemCache(account: self.account) + }() } public final class TelegramEngineUnauthorized { diff --git a/submodules/TelegramCore/Sources/Themes.swift b/submodules/TelegramCore/Sources/Themes.swift index b8b18c59ad..83caf21a85 100644 --- a/submodules/TelegramCore/Sources/Themes.swift +++ b/submodules/TelegramCore/Sources/Themes.swift @@ -55,7 +55,7 @@ public func telegramThemes(postbox: Postbox, network: Network, accountManager: A } transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: entries) if let entry = CodableEntry(CachedThemesConfiguration(hash: hash)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedThemesConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedThemesConfiguration, key: ValueBoxKey(length: 0)), entry: entry) } return items } diff --git a/submodules/TelegramCore/Sources/Wallpapers.swift b/submodules/TelegramCore/Sources/Wallpapers.swift index 4620f45e99..2846a09c81 100644 --- a/submodules/TelegramCore/Sources/Wallpapers.swift +++ b/submodules/TelegramCore/Sources/Wallpapers.swift @@ -49,7 +49,7 @@ public func telegramWallpapers(postbox: Postbox, network: Network, forceUpdate: } transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudWallpapers, items: entries) if let entry = CodableEntry(CachedWallpapersConfiguration(hash: hash)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedWallpapersConfiguration, key: ValueBoxKey(length: 0)), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 1, highWaterItemCount: 1)) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedWallpapersConfiguration, key: ValueBoxKey(length: 0)), entry: entry) } return items } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 4387dd42b3..e87727767e 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -893,7 +893,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let timestamp = timestamp { storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate)) } - let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start() + let _ = updateMediaPlaybackStoredStateInteractively(engine: strongSelf.context.engine, messageId: messageId, state: storedState).start() }, editMedia: { [weak self] messageId, snapshots, transitionCompletion in guard let strongSelf = self else { return @@ -6517,7 +6517,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, deleteSelectedMessages: { [weak self] in if let strongSelf = self { if let messageIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !messageIds.isEmpty { - strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds) + strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds) |> deliverOnMainQueue).start(next: { actions in if let strongSelf = self, !actions.options.isEmpty { if let banAuthor = actions.banAuthor { @@ -6633,7 +6633,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, deleteMessages: { [weak self] messages, contextController, completion in if let strongSelf = self, !messages.isEmpty { let messageIds = Set(messages.map { $0.id }) - strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds) + strongSelf.messageContextDisposable.set((strongSelf.context.sharedContext.chatAvailableMessageActions(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: messageIds) |> deliverOnMainQueue).start(next: { actions in if let strongSelf = self, !actions.options.isEmpty { if let banAuthor = actions.banAuthor { @@ -7968,20 +7968,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if let stickerFile = stickerFile { let context = strongSelf.context - let _ = (context.account.postbox.transaction { transaction -> Signal<(SavedStickerResult, Bool), AddSavedStickerError> in - let isSaved: Bool - if getIsStickerSaved(transaction: transaction, fileId: stickerFile.fileId) { - isSaved = true - } else { - isSaved = false - } + let _ = (context.engine.stickers.isStickerSaved(id: stickerFile.fileId) + |> castError(AddSavedStickerError.self) + |> mapToSignal { isSaved -> Signal<(SavedStickerResult, Bool), AddSavedStickerError> in return context.engine.stickers.toggleStickerSaved(file: stickerFile, saved: !isSaved) |> map { result -> (SavedStickerResult, Bool) in return (result, !isSaved) } } - |> castError(AddSavedStickerError.self) - |> switchToLatest |> deliverOnMainQueue).start(next: { [weak self] result, added in if let strongSelf = self { switch result { @@ -8185,9 +8179,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) }) }) - let _ = (strongSelf.context.account.postbox.transaction { transaction -> Void in - updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root) - } + let _ = (strongSelf.context.engine.peers.updatePeersGroupIdInteractively(peerIds: [peerId], groupId: .root) |> deliverOnMainQueue).start() }, openLinkEditing: { [weak self] in if let strongSelf = self { @@ -15068,9 +15060,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) if actions.contains(3) { let context = strongSelf.context - let _ = context.account.postbox.transaction({ transaction -> Void in - context.engine.messages.deleteAllMessagesWithAuthor(transaction: transaction, peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud) - }).start() + let _ = context.engine.messages.deleteAllMessagesWithAuthor(peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud).start() let _ = strongSelf.context.engine.messages.clearAuthorHistory(peerId: peerId, memberId: author.id).start() } else if actions.contains(0) { let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index f2d888ede1..a622aaa073 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -1583,129 +1583,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.loadStateUpdated = f } - /*private func updateHistoryScrollingArea(transition: ContainedViewLayoutTransition) { - guard let historyScrollingArea = self.historyScrollingArea else { - return - } - guard let transactionState = self.opaqueTransactionState as? ChatHistoryTransactionOpaqueState else { - return - } - - let historyView = transactionState.historyView - - var updatedScrollingState = self.scrollingState - if var scrollingState = updatedScrollingState { - let convertedIndex = historyView.filteredEntries.count - scrollingState.topItem.index - 1 - if convertedIndex < 0 || convertedIndex >= historyView.filteredEntries.count { - return - } - let firstItem = historyView.filteredEntries[convertedIndex] - var location: MessageHistoryEntryLocation? - switch firstItem { - case let .MessageEntry(_, _, _, locationValue, _, _): - location = locationValue - case let .MessageGroupEntry(_, group, _): - if let locationValue = group.last?.4 { - location = locationValue - } - default: - break - } - - if let location = location { - let locationDelta = (location.count - location.index - 1) - scrollingState.topItem.index - scrollingState.topItem.index += locationDelta - scrollingState.bottomItem.index += locationDelta - scrollingState.itemCount = max(scrollingState.itemCount, location.count) - } - - updatedScrollingState = scrollingState - } - - historyScrollingArea.update( - containerSize: self.bounds.size, - containerInsets: UIEdgeInsets(top: self.scrollIndicatorInsets.top, left: 0.0, bottom: self.scrollIndicatorInsets.bottom, right: 0.0), - scrollingState: updatedScrollingState, - isScrolling: self.isDragging || self.isDeceleratingAfterTracking, - theme: self.currentPresentationData.theme.theme, - transition: transition - ) - } - - private func navigateToAbsolutePosition(position: Float) { - guard let transactionState = self.opaqueTransactionState as? ChatHistoryTransactionOpaqueState else { - return - } - - let historyView = transactionState.historyView - - let convertedIndex = 0 - if convertedIndex < 0 || convertedIndex >= historyView.filteredEntries.count { - self.historyScrollingArea?.resetNavigatingToPosition() - return - } - let firstItem = historyView.filteredEntries[convertedIndex] - var location: MessageHistoryEntryLocation? - switch firstItem { - case let .MessageEntry(_, _, _, locationValue, _, _): - location = locationValue - case let .MessageGroupEntry(_, group, _): - if let locationValue = group.last?.4 { - location = locationValue - } - default: - break - } - - if let location = location { - var absoluteIndex = Int(Float(location.count) * position) - if absoluteIndex >= location.count { - absoluteIndex = location.count - 1 - } - if absoluteIndex < 0 { - absoluteIndex = 0 - } - if case let .peer(peerId) = self.chatLocation { - let _ = (self.context.account.postbox.transaction { transaction -> MessageIndex? in - return transaction.findMessageAtAbsoluteIndex(peerId: peerId, namespace: Namespaces.Message.Cloud, index: absoluteIndex) - } - |> deliverOnMainQueue).start(next: { [weak self] index in - guard let strongSelf = self else { - return - } - if let index = index { - let content: ChatHistoryLocation = .Scroll(index: .message(index), anchorIndex: .message(index), sourceIndex: .message(index), scrollPosition: .top(0.0), animated: false, highlight: false) - - strongSelf.scrollNavigationDisposable.set((preloadedChatHistoryViewForLocation(ChatHistoryLocationInput(content: content, id: 0), context: strongSelf.context, chatLocation: strongSelf.chatLocation, subject: strongSelf.subject, chatLocationContextHolder: strongSelf.chatLocationContextHolder, fixedCombinedReadStates: nil, tagMask: nil, additionalData: []) - |> map { historyView -> Bool in - switch historyView { - case .Loading: - return false - case .HistoryView: - return true - } - } - |> filter { $0 } - |> take(1) - |> deliverOnMainQueue).start(next: { _ in - guard let strongSelf = self else { - return - } - strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: content, id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) - Queue.mainQueue().after(0.5, { - self?.historyScrollingArea?.resetNavigatingToPosition() - }) - })) - } else { - strongSelf.historyScrollingArea?.resetNavigatingToPosition() - } - }) - } - } else { - self.historyScrollingArea?.resetNavigatingToPosition() - } - }*/ - private func maybeUpdateOverscrollAction(offset: CGFloat?) { if self.freezeOverscrollControl { return @@ -2304,7 +2181,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if historyView.originalView.laterId == nil { for entry in historyView.filteredEntries.reversed() { if case let .MessageEntry(message, _, _, _, _, _) = entry { - if canEditMessage(context: context, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, message: message) { + if canEditMessage(context: context, limitsConfiguration: context.currentLimitsConfiguration.with { EngineConfiguration.Limits($0) }, message: message) { return message } } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index a954d58c06..ae5d8a6de2 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -42,11 +42,11 @@ private struct MessageContextMenuData { let messageActions: ChatAvailableMessageActions } -func canEditMessage(context: AccountContext, limitsConfiguration: LimitsConfiguration, message: Message) -> Bool { +func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: Message) -> Bool { return canEditMessage(accountPeerId: context.account.peerId, limitsConfiguration: limitsConfiguration, message: message) } -private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsConfiguration, message: Message, reschedule: Bool = false) -> Bool { +private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: EngineConfiguration.Limits, message: Message, reschedule: Bool = false) -> Bool { var hasEditRights = false var unlimitedInterval = reschedule @@ -153,7 +153,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo } if !hasUneditableAttributes || reschedule { - if canPerformEditingActions(limits: limitsConfiguration, accountPeerId: accountPeerId, message: message, unlimitedInterval: unlimitedInterval) { + if canPerformEditingActions(limits: limitsConfiguration._asLimits(), accountPeerId: accountPeerId, message: message, unlimitedInterval: unlimitedInterval) { return true } } @@ -161,7 +161,7 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo return false } -private func canViewReadStats(message: Message, cachedData: CachedPeerData?, isMessageRead: Bool, appConfig: AppConfiguration) -> Bool { +private func canViewReadStats(message: Message, participantCount: Int?, isMessageRead: Bool, appConfig: AppConfiguration) -> Bool { guard let peer = message.peers[message.id.peerId] else { return false } @@ -210,12 +210,8 @@ private func canViewReadStats(message: Message, cachedData: CachedPeerData?, isM case let channel as TelegramChannel: if case .broadcast = channel.info { return false - } else if let cachedData = cachedData as? CachedChannelData { - if let memberCount = cachedData.participantsSummary.memberCount { - if Int(memberCount) > maxParticipantCount { - return false - } - } else { + } else if let participantCount = participantCount { + if participantCount > maxParticipantCount { return false } } else { @@ -555,36 +551,47 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState |> map(Optional.init) } - let loadLimits = context.account.postbox.transaction { transaction -> (LimitsConfiguration, AppConfiguration) in - let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue - let appConfig = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue - return (limitsConfiguration, appConfig) + let loadLimits = context.engine.data.get( + TelegramEngine.EngineData.Item.Configuration.Limits(), + TelegramEngine.EngineData.Item.Configuration.App() + ) + + struct InfoSummaryData { + var linkedDiscusionPeerId: EnginePeerCachedInfoItem + var canViewStats: Bool + var participantCount: Int? } - let cachedData = context.account.postbox.transaction { transaction -> CachedPeerData? in - return transaction.getPeerCachedData(peerId: messages[0].id.peerId) + let infoSummaryData = context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.LinkedDiscussionPeerId(id: messages[0].id.peerId), + TelegramEngine.EngineData.Item.Peer.CanViewStats(id: messages[0].id.peerId), + TelegramEngine.EngineData.Item.Peer.ParticipantCount(id: messages[0].id.peerId) + ) + |> map { linkedDiscusionPeerId, canViewStats, participantCount -> InfoSummaryData in + return InfoSummaryData( + linkedDiscusionPeerId: linkedDiscusionPeerId, + canViewStats: canViewStats, + participantCount: participantCount + ) } - //let readState = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.PeerUnreadCount) - let readState = context.account.postbox.transaction { transaction -> CombinedPeerReadState? in - return transaction.getCombinedPeerReadState(messages[0].id.peerId) - } + let readState = context.engine.data.get(TelegramEngine.EngineData.Item.Messages.ReadState(id: messages[0].id.peerId)) - let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest( + let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?), NoError> = combineLatest( loadLimits, loadStickerSaveStatusSignal, loadResourceStatusSignal, - context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })), + context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })), context.account.pendingUpdateMessageManager.updatingMessageMedia |> take(1), - cachedData, + infoSummaryData, readState, ApplicationSpecificNotice.getMessageViewsPrivacyTips(accountManager: context.sharedContext.accountManager), context.engine.stickers.availableReactions(), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings, SharedDataKeys.loggingSettings]), context.engine.peers.notificationSoundList() |> take(1) ) - |> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, cachedData, readState, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in + |> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, readState, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?) in let (limitsConfiguration, appConfig) = limitsAndAppConfig var canEdit = false if !isAction { @@ -611,12 +618,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState loggingSettings = LoggingSettings.defaultSettings } - return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, cachedData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList) + return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList) } return dataSignal |> deliverOnMainQueue - |> map { data, updatingMessageMedia, cachedData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList -> ContextController.Items in + |> map { data, updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList -> ContextController.Items in var actions: [ContextMenuItem] = [] var isPinnedMessages = false @@ -988,7 +995,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState var threadId: Int64? var threadMessageCount: Int = 0 if case .peer = chatPresentationInterfaceState.chatLocation, let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .group = channel.info { - if let cachedData = cachedData as? CachedChannelData, case let .known(maybeValue) = cachedData.linkedDiscussionPeerId, let _ = maybeValue { + if case let .known(maybeValue) = infoSummaryData.linkedDiscusionPeerId, let _ = maybeValue { if let value = messages[0].threadId { threadId = value } else { @@ -1265,7 +1272,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } } - if let cachedData = cachedData as? CachedChannelData, cachedData.flags.contains(.canViewStats), views >= 100 { + if infoSummaryData.canViewStats, views >= 100 { actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextViewStats, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.actionSheet.primaryTextColor) }, action: { c, _ in @@ -1359,7 +1366,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } } - let canViewStats = canViewReadStats(message: message, cachedData: cachedData, isMessageRead: isMessageRead, appConfig: appConfig) + let canViewStats = canViewReadStats(message: message, participantCount: infoSummaryData.participantCount, isMessageRead: isMessageRead, appConfig: appConfig) var reactionCount = 0 for reaction in mergedMessageReactionsAndPeers(message: message).reactions { reactionCount += Int(reaction.count) @@ -1467,9 +1474,13 @@ private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: return false } -func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, messageIds: Set, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:]) -> Signal { - return postbox.transaction { transaction -> ChatAvailableMessageActions in - let limitsConfiguration: LimitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue +func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: PeerId, messageIds: Set, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:]) -> Signal { + return engine.data.get( + TelegramEngine.EngineData.Item.Configuration.Limits(), + EngineDataMap(Set(messageIds.map(\.peerId)).map(TelegramEngine.EngineData.Item.Peer.Peer.init)), + EngineDataMap(Set(messageIds).map(TelegramEngine.EngineData.Item.Messages.Message.init)) + ) + |> map { limitsConfiguration, peerMap, messageMap -> ChatAvailableMessageActions in var optionsMap: [MessageId: ChatAvailableMessageActionOptions] = [:] var banPeer: Peer? var hadPersonalIncoming = false @@ -1478,8 +1489,8 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me var isCopyProtected = false func getPeer(_ peerId: PeerId) -> Peer? { - if let peer = transaction.getPeer(peerId) { - return peer + if let maybePeer = peerMap[peerId], let peer = maybePeer { + return peer._asPeer() } else if let peer = peers[peerId] { return peer } else { @@ -1488,8 +1499,8 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me } func getMessage(_ messageId: MessageId) -> Message? { - if let message = transaction.getMessage(messageId) { - return message + if let maybeMessage = messageMap[messageId], let message = maybeMessage { + return message._asMessage() } else if let message = messages[messageId] { return message } else { @@ -1638,7 +1649,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me } optionsMap[id]!.insert(.deleteLocally) var canDeleteGlobally = false - if canPerformDeleteActions(limits: limitsConfiguration, accountPeerId: accountPeerId, message: message) { + if canPerformDeleteActions(limits: limitsConfiguration._asLimits(), accountPeerId: accountPeerId, message: message) { canDeleteGlobally = true } else if limitsConfiguration.canRemoveIncomingMessagesInPrivateChats { canDeleteGlobally = true diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index fc7889ba3c..4c526fb04a 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -928,9 +928,7 @@ final class ChatMediaInputNode: ChatInputNode { var items: [ActionSheetItem] = [] items.append(ActionSheetButtonItem(title: strongSelf.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (context.account.postbox.transaction { transaction in - clearRecentlyUsedStickers(transaction: transaction) - }).start() + let _ = context.engine.stickers.clearRecentlyUsedStickers().start() })) actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in @@ -1407,16 +1405,15 @@ final class ChatMediaInputNode: ChatInputNode { canSaveGif = false } - let _ = (self.context.account.postbox.transaction { transaction -> Bool in - if !canSaveGif { - return false - } - return isGifSaved(transaction: transaction, mediaId: file.file.media.fileId) - } + let _ = (self.context.engine.stickers.isGifSaved(id: file.file.media.fileId) |> deliverOnMainQueue).start(next: { [weak self] isGifSaved in guard let strongSelf = self else { return } + var isGifSaved = isGifSaved + if !canSaveGif { + isGifSaved = false + } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) @@ -1530,9 +1527,7 @@ final class ChatMediaInputNode: ChatInputNode { if let (itemNode, item) = searchContainerNode.itemAt(point: point.offsetBy(dx: -searchContainerNode.frame.minX, dy: -searchContainerNode.frame.minY)) { if let item = item as? StickerPreviewPeekItem { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self { diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index 9a0371e894..ce79c1a430 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -292,9 +292,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { switch resourceStatus.mediaStatus { case let .fetchStatus(fetchStatus): if let context = self.context, let message = self.message, message.flags.isSending { - let _ = context.account.postbox.transaction({ transaction -> Void in - context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id]) - }).start() + let _ = context.engine.messages.deleteMessagesInteractively(messageIds: [message.id], type: .forEveryone).start() } else { switch fetchStatus { case .Fetching: diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift index 07329b053d..57a9143653 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift @@ -846,10 +846,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { switch fetchStatus { case .Fetching: if item.message.flags.isSending { - let messageId = item.message.id - let _ = item.context.account.postbox.transaction({ transaction -> Void in - item.context.engine.messages.deleteMessages(transaction: transaction, ids: [messageId]) - }).start() + let _ = item.context.engine.messages.deleteMessagesInteractively(messageIds: [item.message.id], type: .forEveryone).start() } else { messageMediaFileCancelInteractiveFetch(context: item.context, messageId: item.message.id, file: file) } diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift index 03c2c838a2..e149905b3f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift @@ -307,9 +307,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio switch fetchStatus { case .Fetching: if let context = self.context, let message = self.message, message.flags.isSending { - let _ = context.account.postbox.transaction({ transaction -> Void in - context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id]) - }).start() + let _ = context.engine.messages.deleteMessagesInteractively(messageIds: [message.id], type: .forEveryone).start() } else if let media = media, let context = self.context, let message = message { if let media = media as? TelegramMediaFile { messageMediaFileCancelInteractiveFetch(context: context, messageId: message.id, file: media) diff --git a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift index 043b01a656..754c1371d9 100644 --- a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift @@ -38,7 +38,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { } self.canDeleteMessagesDisposable.set(nil) } else if let context = self.context { - self.canDeleteMessagesDisposable.set((context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: self.selectedMessages) + self.canDeleteMessagesDisposable.set((context.sharedContext.chatAvailableMessageActions(engine: context.engine, accountPeerId: context.account.peerId, messageIds: self.selectedMessages) |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self { strongSelf.actions = actions diff --git a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift index 705c0cccd9..c33e3c8353 100644 --- a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift +++ b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift @@ -117,11 +117,10 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } }) - self.limitsConfigurationDisposable = (context.account.postbox.transaction { transaction -> LimitsConfiguration in - return currentLimitsConfiguration(transaction: transaction) - } |> deliverOnMainQueue).start(next: { [weak self] value in + self.limitsConfigurationDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.Limits()) + |> deliverOnMainQueue).start(next: { [weak self] value in if let strongSelf = self { - strongSelf.limitsConfiguration = value + strongSelf.limitsConfiguration = value._asLimits() strongSelf.updateTitle() strongSelf._limitsReady.set(.single(true)) } diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 38c9dd66a8..cc0a0dbc80 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -326,9 +326,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { var items: [ActionSheetItem] = [] items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (context.account.postbox.transaction { transaction in - clearRecentlyUsedStickers(transaction: transaction) - }).start() + let _ = context.engine.stickers.clearRecentlyUsedStickers().start() })) actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in @@ -441,9 +439,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { var items: [ActionSheetItem] = [] items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (context.account.postbox.transaction { transaction in - clearRecentlyUsedStickers(transaction: transaction) - }).start() + let _ = context.engine.stickers.clearRecentlyUsedStickers().start() })) actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in diff --git a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index fe0d0ea42b..c48057948c 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -476,9 +476,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { if let searchNode = strongSelf.searchNode, searchNode.isActive { if let (itemNode, item) = searchNode.itemAt(point: strongSelf.view.convert(point, to: searchNode.view)) { if let item = item as? StickerPreviewPeekItem { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self { @@ -563,9 +561,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { let itemNodeAndItem: (ASDisplayNode, StickerPackItem)? = strongSelf.itemAt(point: point) if let (itemNode, item) = itemNodeAndItem { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self { diff --git a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift index de1701f8d2..dc2993be47 100644 --- a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift @@ -25,11 +25,9 @@ class PaneGifSearchForQueryResult { } func paneGifSearchForQuery(context: AccountContext, query: String, offset: String?, incompleteResults: Bool = false, staleCachedResults: Bool = false, delayRequest: Bool = true, updateActivity: ((Bool) -> Void)?) -> Signal { - let contextBot = context.account.postbox.transaction { transaction -> String in - let configuration = currentSearchBotsConfiguration(transaction: transaction) - return configuration.gifBotUsername ?? "gif" - } - |> mapToSignal { botName -> Signal in + let contextBot = context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.SearchBots()) + |> mapToSignal { searchBots -> Signal in + let botName = searchBots.gifBotUsername ?? "gif" return context.engine.peers.resolvePeerByName(name: botName) } |> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?, Bool, Bool), NoError> in diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index f2feececc8..f08f1c60b8 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -171,9 +171,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } if let itemNode = strongSelf.gridNode.itemNodeAtPoint(strongSelf.view.convert(point, to: strongSelf.gridNode.view)) as? HorizontalStickerGridItemNode, let item = itemNode.stickerItem { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 99c332cfad..785701e5d7 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -99,9 +99,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie } if let itemNode = selectedNode, let item = itemNode.stickerItem { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() { diff --git a/submodules/TelegramUI/Sources/MediaManager.swift b/submodules/TelegramUI/Sources/MediaManager.swift index 428b2d411f..d44ce03b6e 100644 --- a/submodules/TelegramUI/Sources/MediaManager.swift +++ b/submodules/TelegramUI/Sources/MediaManager.swift @@ -434,7 +434,7 @@ public final class MediaManagerImpl: NSObject, MediaManager { if state.status.timestamp > 5.0 && state.status.timestamp < state.status.duration - 5.0 { storedState = MediaPlaybackStoredState(timestamp: state.status.timestamp, playbackRate: state.status.baseRate > 1.0 ? .x2 : .x1) } - let _ = updateMediaPlaybackStoredStateInteractively(postbox: account.postbox, messageId: item.message.id, state: storedState).start() + let _ = updateMediaPlaybackStoredStateInteractively(engine: TelegramEngine(account: account), messageId: item.message.id, state: storedState).start() } } } @@ -487,7 +487,7 @@ public final class MediaManagerImpl: NSObject, MediaManager { let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.musicPlaybackSettings]?.get(MusicPlaybackSettings.self) ?? MusicPlaybackSettings.defaultSettings if let location = playlist.location as? PeerMessagesPlaylistLocation, let messageId = location.messageId { - return mediaPlaybackStoredState(postbox: account.postbox, messageId: messageId) + return mediaPlaybackStoredState(engine: TelegramEngine(account: account), messageId: messageId) |> map { storedState in return (account, playlist, settings, storedState) } diff --git a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift index c6022062fd..3a8f17e9da 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift @@ -1849,7 +1849,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro guard let strongSelf = self else { return } - let _ = updateVisualMediaStoredState(postbox: strongSelf.context.account.postbox, peerId: strongSelf.peerId, messageTag: strongSelf.stateTag, state: VisualMediaStoredState(zoomLevel: Int32(zoomLevel.rawValue))).start() + let _ = updateVisualMediaStoredState(engine: strongSelf.context.engine, peerId: strongSelf.peerId, messageTag: strongSelf.stateTag, state: VisualMediaStoredState(zoomLevel: Int32(zoomLevel.rawValue))).start() } self._itemInteraction = VisualMediaItemInteraction( @@ -1946,7 +1946,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro strongSelf.itemGrid.cancelGestures() } - self.storedStateDisposable = (visualMediaStoredState(postbox: context.account.postbox, peerId: peerId, messageTag: self.stateTag) + self.storedStateDisposable = (visualMediaStoredState(engine: context.engine, peerId: peerId, messageTag: self.stateTag) |> deliverOnMainQueue).start(next: { [weak self] value in guard let strongSelf = self else { return @@ -2200,7 +2200,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro func updateZoomLevel(level: ZoomLevel) { self.itemGrid.setZoomLevel(level: level.value) - let _ = updateVisualMediaStoredState(postbox: self.context.account.postbox, peerId: self.peerId, messageTag: self.stateTag, state: VisualMediaStoredState(zoomLevel: level.rawValue)).start() + let _ = updateVisualMediaStoredState(engine: self.context.engine, peerId: self.peerId, messageTag: self.stateTag, state: VisualMediaStoredState(zoomLevel: level.rawValue)).start() } func ensureMessageIsVisible(id: MessageId) { @@ -2575,32 +2575,25 @@ final class VisualMediaStoredState: Codable { } } -func visualMediaStoredState(postbox: Postbox, peerId: PeerId, messageTag: MessageTags) -> Signal { - return postbox.transaction { transaction -> VisualMediaStoredState? in - let key = ValueBoxKey(length: 8 + 4) - key.setInt64(0, value: peerId.toInt64()) - key.setUInt32(8, value: messageTag.rawValue) - if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, key: key))?.get(VisualMediaStoredState.self) { - return entry - } else { - return nil - } +func visualMediaStoredState(engine: TelegramEngine, peerId: PeerId, messageTag: MessageTags) -> Signal { + let key = ValueBoxKey(length: 8 + 4) + key.setInt64(0, value: peerId.toInt64()) + key.setUInt32(8, value: messageTag.rawValue) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key)) + |> map { entry -> VisualMediaStoredState? in + return entry?.get(VisualMediaStoredState.self) } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 25, highWaterItemCount: 50) - -func updateVisualMediaStoredState(postbox: Postbox, peerId: PeerId, messageTag: MessageTags, state: VisualMediaStoredState?) -> Signal { - return postbox.transaction { transaction -> Void in - let key = ValueBoxKey(length: 8 + 4) - key.setInt64(0, value: peerId.toInt64()) - key.setUInt32(8, value: messageTag.rawValue) - - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, key: key) - if let state = state, let entry = CodableEntry(state) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } else { - transaction.removeItemCacheEntry(id: id) - } +func updateVisualMediaStoredState(engine: TelegramEngine, peerId: PeerId, messageTag: MessageTags, state: VisualMediaStoredState?) -> Signal { + let key = ValueBoxKey(length: 8 + 4) + key.setInt64(0, value: peerId.toInt64()) + key.setUInt32(8, value: messageTag.rawValue) + + if let state = state { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key, item: state) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.visualMediaStoredState, id: key) } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 07a5bccf7d..5ccfad7f4e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1861,7 +1861,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } let gesture: ContextGesture? = anyRecognizer as? ContextGesture - let _ = (chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) + let _ = (chatAvailableMessageActionsImpl(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) |> deliverOnMainQueue).start(next: { actions in guard let strongSelf = self else { return @@ -2016,7 +2016,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if let previewData = previewData { let context = strongSelf.context let strings = strongSelf.presentationData.strings - let items = chatAvailableMessageActionsImpl(postbox: strongSelf.context.account.postbox, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) + let items = chatAvailableMessageActionsImpl(engine: strongSelf.context.engine, accountPeerId: strongSelf.context.account.peerId, messageIds: [message.id]) |> map { actions -> [ContextMenuItem] in var items: [ContextMenuItem] = [] @@ -3285,7 +3285,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if let timestamp = timestamp { storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate)) } - let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start() + let _ = updateMediaPlaybackStoredStateInteractively(engine: strongSelf.context.engine, messageId: messageId, state: storedState).start() }, editMedia: { [weak self] messageId, snapshots, transitionCompletion in guard let strongSelf = self else { return @@ -6379,14 +6379,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate private func accountContextMenuItems(context: AccountContext, logout: @escaping () -> Void) -> Signal<[ContextMenuItem], NoError> { let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings - return context.account.postbox.transaction { transaction -> [ContextMenuItem] in + return context.engine.messages.unreadChatListPeerIds(groupId: .root, filterPredicate: nil) + |> map { unreadChatListPeerIds -> [ContextMenuItem] in var items: [ContextMenuItem] = [] - if !transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: nil).isEmpty { + if !unreadChatListPeerIds.isEmpty { items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = (context.account.postbox.transaction { transaction in - markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: .root, filterPredicate: nil) - } + let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: .root, filterPredicate: nil)]) |> deliverOnMainQueue).start(completed: { f(.default) }) @@ -6436,7 +6435,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate private func deleteMessages(messageIds: Set?) { if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty { - self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(postbox: self.context.account.postbox, accountPeerId: self.context.account.peerId, messageIds: messageIds) + self.activeActionDisposable.set((self.context.sharedContext.chatAvailableMessageActions(engine: self.context.engine, accountPeerId: self.context.account.peerId, messageIds: messageIds) |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self, let peer = strongSelf.data?.peer, !actions.options.isEmpty { let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) diff --git a/submodules/TelegramUI/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Sources/ShareExtensionContext.swift index 92b1b84c23..c7bac62bfb 100644 --- a/submodules/TelegramUI/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Sources/ShareExtensionContext.swift @@ -299,20 +299,19 @@ public class ShareRootControllerImpl { let applicationInterface = account |> mapToSignal { sharedContext, account, otherAccounts -> Signal<(AccountContext, PostboxAccessChallengeData, [AccountWithInfo]), ShareAuthorizationError> in - let limitsConfigurationAndContentSettings = account.postbox.transaction { transaction -> (LimitsConfiguration, ContentSettings, AppConfiguration) in - return ( - transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue, - getContentSettings(transaction: transaction), - getAppConfiguration(transaction: transaction) - ) - } + let limitsConfigurationAndContentSettings = TelegramEngine(account: account).data.get( + TelegramEngine.EngineData.Item.Configuration.Limits(), + TelegramEngine.EngineData.Item.Configuration.ContentSettings(), + TelegramEngine.EngineData.Item.Configuration.App() + ) + return combineLatest(sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), limitsConfigurationAndContentSettings, sharedContext.accountManager.accessChallengeData()) |> take(1) |> deliverOnMainQueue |> castError(ShareAuthorizationError.self) |> map { sharedData, limitsConfigurationAndContentSettings, data -> (AccountContext, PostboxAccessChallengeData, [AccountWithInfo]) in updateLegacyLocalization(strings: sharedContext.currentPresentationData.with({ $0 }).strings) - let context = AccountContextImpl(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfigurationAndContentSettings.0, contentSettings: limitsConfigurationAndContentSettings.1, appConfiguration: limitsConfigurationAndContentSettings.2) + let context = AccountContextImpl(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfigurationAndContentSettings.0._asLimits(), contentSettings: limitsConfigurationAndContentSettings.1, appConfiguration: limitsConfigurationAndContentSettings.2) return (context, data.data, otherAccounts) } } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 2d1611a787..f1a59f8b28 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -412,11 +412,13 @@ public final class SharedAccountContextImpl: SharedAccountContext { switch result { case let .authorized(account): setupAccount(account, fetchCachedResourceRepresentation: fetchCachedResourceRepresentation, transformOutgoingMessageMedia: transformOutgoingMessageMedia) - return account.postbox.transaction { transaction -> AddedAccountResult in - let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) ?? LimitsConfiguration.defaultValue - let contentSettings = getContentSettings(transaction: transaction) - let appConfiguration = getAppConfiguration(transaction: transaction) - return .ready(id, account, attributes.sortIndex, limitsConfiguration, contentSettings, appConfiguration) + return TelegramEngine(account: account).data.get( + TelegramEngine.EngineData.Item.Configuration.Limits(), + TelegramEngine.EngineData.Item.Configuration.ContentSettings(), + TelegramEngine.EngineData.Item.Configuration.App() + ) + |> map { limitsConfiguration, contentSettings, appConfiguration -> AddedAccountResult in + return .ready(id, account, attributes.sortIndex, limitsConfiguration._asLimits(), contentSettings, appConfiguration) } case let .upgrading(progress): return .single(.upgrading(progress)) @@ -1140,12 +1142,12 @@ public final class SharedAccountContextImpl: SharedAccountContext { openExternalUrlImpl(context: context, urlContext: urlContext, url: url, forceExternal: forceExternal, presentationData: presentationData, navigationController: navigationController, dismissInput: dismissInput) } - public func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set) -> Signal { - return chatAvailableMessageActionsImpl(postbox: postbox, accountPeerId: accountPeerId, messageIds: messageIds) + public func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set) -> Signal { + return chatAvailableMessageActionsImpl(engine: engine, accountPeerId: accountPeerId, messageIds: messageIds) } - public func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage] = [:], peers: [EnginePeer.Id: EnginePeer] = [:]) -> Signal { - return chatAvailableMessageActionsImpl(postbox: postbox, accountPeerId: accountPeerId, messageIds: messageIds, messages: messages.mapValues({ $0._asMessage() }), peers: peers.mapValues({ $0._asPeer() })) + public func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage] = [:], peers: [EnginePeer.Id: EnginePeer] = [:]) -> Signal { + return chatAvailableMessageActionsImpl(engine: engine, accountPeerId: accountPeerId, messageIds: messageIds, messages: messages.mapValues({ $0._asMessage() }), peers: peers.mapValues({ $0._asPeer() })) } public func navigateToChatController(_ params: NavigateToChatControllerParams) { diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index ecaba454e8..0ddddb2182 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -127,9 +127,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { if let stickersNode = stickersNode { let point = strongSelf.listView.view.convert(point, to: stickersNode.view) if let (item, itemNode) = stickersNode.stickerItem(at: point) { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - return getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) - } + return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { diff --git a/submodules/TelegramUI/Sources/WalletContextImpl.swift b/submodules/TelegramUI/Sources/WalletContextImpl.swift deleted file mode 100644 index 4f813b2775..0000000000 --- a/submodules/TelegramUI/Sources/WalletContextImpl.swift +++ /dev/null @@ -1,283 +0,0 @@ -#if ENABLE_WALLET - -import Foundation -import UIKit -import Display -import WalletUI -import Postbox -import TelegramCore -import AccountContext -import SwiftSignalKit -import TelegramPresentationData -import ShareController -import DeviceAccess -import PresentationDataUtils -import WalletCore - -extension WalletConfiguration { - static func with(appConfiguration: AppConfiguration) -> WalletConfiguration { - if let data = appConfiguration.data, let config = data["wallet_config"] as? String, let blockchainName = data["wallet_blockchain_name"] as? String { - var disableProxy = false - if let value = data["wallet_disable_proxy"] as? String { - disableProxy = value != "0" - } else if let value = data["wallet_disable_proxy"] as? Int { - disableProxy = value != 0 - } - return WalletConfiguration(config: config, blockchainName: blockchainName, disableProxy: disableProxy) - } else { - return .defaultValue - } - } -} - -final class WalletStorageInterfaceImpl: WalletStorageInterface { - private let postbox: Postbox - - init(postbox: Postbox) { - self.postbox = postbox - } - - func watchWalletRecords() -> Signal<[WalletStateRecord], NoError> { - return self.postbox.preferencesView(keys: [PreferencesKeys.walletCollection]) - |> map { view -> [WalletStateRecord] in - guard let walletCollection = view.values[PreferencesKeys.walletCollection] as? WalletCollection else { - return [] - } - return walletCollection.wallets.flatMap { item -> WalletStateRecord? in - do { - return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) }) - } catch { - return nil - } - } - } - } - - func getWalletRecords() -> Signal<[WalletStateRecord], NoError> { - return self.postbox.transaction { transaction -> [WalletStateRecord] in - guard let walletCollection = transaction.getPreferencesEntry(key: PreferencesKeys.walletCollection) as? WalletCollection else { - return [] - } - return walletCollection.wallets.flatMap { item -> WalletStateRecord? in - do { - return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) }) - } catch { - return nil - } - } - } - } - - func updateWalletRecords(_ f: @escaping ([WalletStateRecord]) -> [WalletStateRecord]) -> Signal<[WalletStateRecord], NoError> { - return self.postbox.transaction { transaction -> [WalletStateRecord] in - var updatedRecords: [WalletStateRecord] = [] - transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in - var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: []) - let updatedItems = f(walletCollection.wallets.flatMap { item -> WalletStateRecord? in - do { - return WalletStateRecord(info: try JSONDecoder().decode(WalletInfo.self, from: item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { try? JSONDecoder().decode(CombinedWalletState.self, from: $0) }) - } catch { - return nil - } - }) - walletCollection.wallets = updatedItems.flatMap { item in - do { - return WalletCollectionItem(info: try JSONEncoder().encode(item.info), exportCompleted: item.exportCompleted, state: item.state.flatMap { - try? JSONEncoder().encode($0) - }) - } catch { - return nil - } - } - return walletCollection - }) - return updatedRecords - } - } - - func localWalletConfiguration() -> Signal { - return .single(LocalWalletConfiguration(source: .string(""), blockchainName: "")) - } - - func updateLocalWalletConfiguration(_ f: @escaping (LocalWalletConfiguration) -> LocalWalletConfiguration) -> Signal { - return .complete() - } -} - -final class WalletContextImpl: WalletContext { - private let context: AccountContext - - let storage: WalletStorageInterface - let tonInstance: TonInstance - let keychain: TonKeychain - let strings: PresentationStrings - let presentationData: WalletPresentationData - - let supportsCustomConfigurations: Bool = false - var termsUrl: String? { - return self.strings.TelegramWallet_Intro_TermsUrl - } - var feeInfoUrl: String? { - return self.strings.AppWallet_TransactionInfo_FeeInfoURL - } - - var inForeground: Signal { - return self.context.sharedContext.applicationBindings.applicationInForeground - } - - func downloadFile(url: URL) -> Signal { - return .fail(.generic) - } - - func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal { - return .complete() - } - - init(context: AccountContext, tonContext: TonContext) { - self.context = context - - self.storage = WalletStorageInterfaceImpl(postbox: self.context.account.postbox) - - self.tonInstance = tonContext.instance - self.keychain = tonContext.keychain - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - self.strings = presentationData.strings - let theme = presentationData.theme - let strings = presentationData.strings - let timeFormat: WalletTimeFormat - switch presentationData.dateTimeFormat.timeFormat { - case .military: - timeFormat = .military - case .regular: - timeFormat = .regular - } - let dateFormat: WalletDateFormat - switch presentationData.dateTimeFormat.dateFormat { - case .dayFirst: - dateFormat = .dayFirst - case .monthFirst: - dateFormat = .monthFirst - } - - let navigationBarData = NavigationBarPresentationData(presentationData: presentationData) - - self.presentationData = WalletPresentationData( - theme: WalletTheme( - info: WalletInfoTheme( - buttonBackgroundColor: UIColor(rgb: 0x32aafe), - buttonTextColor: .white, - incomingFundsTitleColor: theme.chatList.secretTitleColor, - outgoingFundsTitleColor: theme.list.itemDestructiveColor - ), transaction: WalletTransactionTheme( - descriptionBackgroundColor: theme.chat.message.incoming.bubble.withoutWallpaper.fill, - descriptionTextColor: theme.chat.message.incoming.primaryTextColor - ), setup: WalletSetupTheme( - buttonFillColor: theme.list.itemCheckColors.fillColor, - buttonForegroundColor: theme.list.itemCheckColors.foregroundColor, - inputBackgroundColor: theme.actionSheet.inputBackgroundColor, - inputPlaceholderColor: theme.actionSheet.inputPlaceholderColor, - inputTextColor: theme.actionSheet.inputTextColor, - inputClearButtonColor: theme.actionSheet.inputClearButtonColor.withAlphaComponent(0.8) - ), - list: WalletListTheme( - itemPrimaryTextColor: theme.list.itemPrimaryTextColor, - itemSecondaryTextColor: theme.list.itemSecondaryTextColor, - itemPlaceholderTextColor: theme.list.itemPlaceholderTextColor, - itemDestructiveColor: theme.list.itemDestructiveColor, - itemAccentColor: theme.list.itemAccentColor, - itemDisabledTextColor: theme.list.itemDisabledTextColor, - plainBackgroundColor: theme.list.plainBackgroundColor, - blocksBackgroundColor: theme.list.blocksBackgroundColor, - itemPlainSeparatorColor: theme.list.itemPlainSeparatorColor, - itemBlocksBackgroundColor: theme.list.itemBlocksBackgroundColor, - itemBlocksSeparatorColor: theme.list.itemBlocksSeparatorColor, - itemHighlightedBackgroundColor: theme.list.itemHighlightedBackgroundColor, - sectionHeaderTextColor: theme.list.sectionHeaderTextColor, - freeTextColor: theme.list.freeTextColor, - freeTextErrorColor: theme.list.freeTextErrorColor, - inputClearButtonColor: theme.list.inputClearButtonColor - ), - statusBarStyle: theme.rootController.statusBarStyle.style, - navigationBar: navigationBarData.theme, - keyboardAppearance: theme.rootController.keyboardColor.keyboardAppearance, - alert: AlertControllerTheme(presentationData: presentationData), - actionSheet: ActionSheetControllerTheme(presentationData: presentationData) - ), strings: WalletStrings( - primaryComponent: WalletStringsComponent( - languageCode: strings.primaryComponent.languageCode, - localizedName: strings.primaryComponent.localizedName, - pluralizationRulesCode: strings.primaryComponent.pluralizationRulesCode, - dict: strings.primaryComponent.dict - ), - secondaryComponent: strings.secondaryComponent.flatMap { component in - return WalletStringsComponent( - languageCode: component.languageCode, - localizedName: component.localizedName, - pluralizationRulesCode: component.pluralizationRulesCode, - dict: component.dict - ) - }, - groupingSeparator: strings.groupingSeparator - ), dateTimeFormat: WalletPresentationDateTimeFormat( - timeFormat: timeFormat, - dateFormat: dateFormat, - dateSeparator: presentationData.dateTimeFormat.dateSeparator, - decimalSeparator: presentationData.dateTimeFormat.decimalSeparator, - groupingSeparator: presentationData.dateTimeFormat.groupingSeparator - ) - ) - } - - func getServerSalt() -> Signal { - return getServerWalletSalt(network: self.context.account.network) - |> mapError { _ -> WalletContextGetServerSaltError in - return .generic - } - } - - func presentNativeController(_ controller: UIViewController) { - self.context.sharedContext.mainWindow?.presentNative(controller) - } - - func idleTimerExtension() -> Disposable { - return self.context.sharedContext.applicationBindings.pushIdleTimerExtension() - } - - func openUrl(_ url: String) { - return self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: url, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {}) - } - - func shareUrl(_ url: String) { - let controller = ShareController(context: self.context, subject: .url(url)) - self.context.sharedContext.mainWindow?.present(controller, on: .root) - } - - func openPlatformSettings() { - self.context.sharedContext.applicationBindings.openSettings() - } - - func authorizeAccessToCamera(completion: @escaping () -> Void) { - let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - DeviceAccess.authorizeAccess(to: .camera(.video), presentationData: presentationData, present: { c, a in - c.presentationArguments = a - self.context.sharedContext.mainWindow?.present(c, on: .root) - }, openSettings: { [weak self] in - self?.openPlatformSettings() - }, { granted in - guard granted else { - return - } - completion() - }) - } - - func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void) { - self.context.sharedContext.openImagePicker(context: self.context, completion: { image in - completion(image) - }, present: { [weak self] controller in - present(controller) - }) - } -} - -#endif diff --git a/submodules/TelegramUIPreferences/Sources/VoipDerivedState.swift b/submodules/TelegramUIPreferences/Sources/VoipDerivedState.swift deleted file mode 100644 index cf75372566..0000000000 --- a/submodules/TelegramUIPreferences/Sources/VoipDerivedState.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Foundation -import Postbox -import TelegramCore -import SwiftSignalKit - -public struct VoipDerivedState: Codable, Equatable { - public var data: Data - - public static var `default`: VoipDerivedState { - return VoipDerivedState(data: Data()) - } - - public init(data: Data) { - self.data = data - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: StringCodingKey.self) - - self.data = try container.decode(Data.self, forKey: "data") - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: StringCodingKey.self) - - try container.encode(self.data, forKey: "data") - } -} - -public func updateVoipDerivedStateInteractively(postbox: Postbox, _ f: @escaping (VoipDerivedState) -> VoipDerivedState) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.voipDerivedState, { entry in - let currentSettings: VoipDerivedState - if let entry = entry?.get(VoipDerivedState.self) { - currentSettings = entry - } else { - currentSettings = .default - } - return PreferencesEntry(f(currentSettings)) - }) - } -} diff --git a/submodules/TelegramVoip/Sources/OngoingCallContext.swift b/submodules/TelegramVoip/Sources/OngoingCallContext.swift index 8447aebce1..c4593693bc 100644 --- a/submodules/TelegramVoip/Sources/OngoingCallContext.swift +++ b/submodules/TelegramVoip/Sources/OngoingCallContext.swift @@ -755,7 +755,7 @@ public final class OngoingCallContext { } } - public init(account: Account, callSessionManager: CallSessionManager, callId: CallId, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, initialNetworkType: NetworkType, updatedNetworkType: Signal, serializedData: String?, dataSaving: VoiceCallDataSaving, derivedState: VoipDerivedState, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, enableTCP: Bool, enableStunMarking: Bool, audioSessionActive: Signal, logName: String, preferredVideoCodec: String?) { + public init(account: Account, callSessionManager: CallSessionManager, callId: CallId, internalId: CallSessionInternalId, proxyServer: ProxyServerSettings?, initialNetworkType: NetworkType, updatedNetworkType: Signal, serializedData: String?, dataSaving: VoiceCallDataSaving, key: Data, isOutgoing: Bool, video: OngoingCallVideoCapturer?, connections: CallSessionConnectionSet, maxLayer: Int32, version: String, allowP2P: Bool, enableTCP: Bool, enableStunMarking: Bool, audioSessionActive: Signal, logName: String, preferredVideoCodec: String?) { let _ = setupLogs OngoingCallThreadLocalContext.applyServerConfig(serializedData) @@ -871,7 +871,7 @@ public final class OngoingCallContext { } } - let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: tempLogPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in + let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: tempLogPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in queue.async { guard let strongSelf = self else { return @@ -966,7 +966,7 @@ public final class OngoingCallContext { break } } - let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary)!, alternativeConnections: connections.alternatives.compactMap(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath) + let context = OngoingCallThreadLocalContext(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForType(initialNetworkType), dataSaving: ongoingDataSavingForType(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescription(connections.primary)!, alternativeConnections: connections.alternatives.compactMap(callConnectionDescription), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath) strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context)) context.stateChanged = { state in @@ -1089,10 +1089,6 @@ public final class OngoingCallContext { }) } } - let derivedState = context.nativeGetDerivedState() - let _ = updateVoipDerivedStateInteractively(postbox: self.account.postbox, { _ in - return VoipDerivedState(data: derivedState) - }).start() } } diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/CachedChannelAdmins.swift b/submodules/TemporaryCachedPeerDataManager/Sources/CachedChannelAdmins.swift index 0ac1453f04..86fe3f054a 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/CachedChannelAdmins.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/CachedChannelAdmins.swift @@ -94,16 +94,10 @@ public final class CachedChannelAdminRanks: Codable { } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 100, highWaterItemCount: 200) - public func cachedChannelAdminRanksEntryId(peerId: PeerId) -> ItemCacheEntryId { return ItemCacheEntryId(collectionId: 100, key: CachedChannelAdminRanks.cacheKey(peerId: peerId)) } -func updateCachedChannelAdminRanks(postbox: Postbox, peerId: PeerId, ranks: Dictionary) -> Signal { - return postbox.transaction { transaction -> Void in - if let entry = CodableEntry(CachedChannelAdminRanks(ranks: ranks)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: 100, key: CachedChannelAdminRanks.cacheKey(peerId: peerId)), entry: entry, collectionSpec: collectionSpec) - } - } +func updateCachedChannelAdminRanks(engine: TelegramEngine, peerId: PeerId, ranks: Dictionary) -> Signal { + return engine.itemCache.put(collectionId: 100, id: CachedChannelAdminRanks.cacheKey(peerId: peerId), item: CachedChannelAdminRanks(ranks: ranks)) } diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift b/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift index 938705a95f..4dc5937de0 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift @@ -132,7 +132,7 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor return ranks } if ranks != previousRanks { - let _ = updateCachedChannelAdminRanks(postbox: self.postbox, peerId: self.peerId, ranks: ranks).start() + let _ = updateCachedChannelAdminRanks(engine: self.engine, peerId: self.peerId, ranks: ranks).start() } } } diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index 9e95a9779b..79f5ec7066 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -727,8 +727,8 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String return ApplicationSpecificNotice.getSecretChatLinkPreviews(accountManager: context.sharedContext.accountManager) |> mapToSignal { linkPreviews -> Signal in - return context.account.postbox.transaction { transaction -> Signal in - let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue + return context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.App()) + |> mapToSignal { appConfiguration -> Signal in let urlHandlingConfiguration = UrlHandlingConfiguration.with(appConfiguration: appConfiguration) var skipUrlAuth = skipUrlAuth @@ -786,7 +786,7 @@ public func resolveUrlImpl(context: AccountContext, peerId: PeerId?, url: String } } return .single(.externalUrl(url)) - } |> switchToLatest + } } } diff --git a/submodules/WallpaperResources/Sources/WallpaperCache.swift b/submodules/WallpaperResources/Sources/WallpaperCache.swift index 29f42cdbe4..3c293626f9 100644 --- a/submodules/WallpaperResources/Sources/WallpaperCache.swift +++ b/submodules/WallpaperResources/Sources/WallpaperCache.swift @@ -27,8 +27,6 @@ public final class CachedWallpaper: Codable { } } -private let collectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10000, highWaterItemCount: 20000) - public func cachedWallpaper(account: Account, slug: String, settings: WallpaperSettings?, update: Bool = false) -> Signal { return account.postbox.transaction { transaction -> Signal in let key = ValueBoxKey(length: 8) @@ -58,7 +56,7 @@ public func cachedWallpaper(account: Account, slug: String, settings: WallpaperS break } if let entry = CodableEntry(CachedWallpaper(wallpaper: wallpaper)) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) + transaction.putItemCacheEntry(id: id, entry: entry) } if let settings = settings { return CachedWallpaper(wallpaper: wallpaper.withUpdatedSettings(settings)) @@ -75,16 +73,12 @@ public func cachedWallpaper(account: Account, slug: String, settings: WallpaperS } |> switchToLatest } -public func updateCachedWallpaper(account: Account, wallpaper: TelegramWallpaper) { +public func updateCachedWallpaper(engine: TelegramEngine, wallpaper: TelegramWallpaper) { guard case let .file(file) = wallpaper, file.id != 0 else { return } - let _ = (account.postbox.transaction { transaction in - let key = ValueBoxKey(length: 8) - key.setInt64(0, value: Int64(bitPattern: file.slug.persistentHashValue)) - let id = ItemCacheEntryId(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, key: key) - if let entry = CodableEntry(CachedWallpaper(wallpaper: wallpaper)) { - transaction.putItemCacheEntry(id: id, entry: entry, collectionSpec: collectionSpec) - } - }).start() + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: Int64(bitPattern: file.slug.persistentHashValue)) + + let _ = engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, id: key, item: CachedWallpaper(wallpaper: wallpaper)).start() } diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index 6784bd9d49..45f9b4697e 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -280,7 +280,7 @@ public final class WebSearchController: ViewController { } }, deleteRecentQuery: { [weak self] query in if let strongSelf = self { - _ = removeRecentWebSearchQuery(postbox: strongSelf.context.account.postbox, string: query).start() + let _ = removeRecentWebSearchQuery(engine: strongSelf.context.engine, string: query).start() } }, toggleSelection: { [weak self] result, value in if let strongSelf = self { @@ -415,7 +415,7 @@ public final class WebSearchController: ViewController { private func updateSearchQuery(_ query: String) { if !query.isEmpty { - let _ = addRecentWebSearchQuery(postbox: self.context.account.postbox, string: query).start() + let _ = addRecentWebSearchQuery(engine: self.context.engine, string: query).start() } let scope: Signal diff --git a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift index 503b287671..f8efce790b 100644 --- a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift @@ -291,7 +291,7 @@ class WebSearchControllerNode: ASDisplayNode { } let header = ChatListSearchItemHeader(type: .recentPeers, theme: interfaceState.presentationData.theme, strings: interfaceState.presentationData.strings, actionTitle: interfaceState.presentationData.strings.WebSearch_RecentSectionClear, action: { - _ = clearRecentWebSearchQueries(postbox: strongSelf.context.account.postbox).start() + let _ = clearRecentWebSearchQueries(engine: strongSelf.context.engine).start() }) let previousEntries = previousRecentItems.swap(entries) diff --git a/submodules/WebSearchUI/Sources/WebSearchRecentQueries.swift b/submodules/WebSearchUI/Sources/WebSearchRecentQueries.swift index 184f592585..cff5e1c155 100644 --- a/submodules/WebSearchUI/Sources/WebSearchRecentQueries.swift +++ b/submodules/WebSearchUI/Sources/WebSearchRecentQueries.swift @@ -1,6 +1,7 @@ import Foundation import UIKit import Postbox +import TelegramCore import SwiftSignalKit import TelegramUIPreferences @@ -35,42 +36,36 @@ public final class RecentWebSearchQueryItem: Codable { } } -func addRecentWebSearchQuery(postbox: Postbox, string: String) -> Signal { - return postbox.transaction { transaction in - if let itemId = WebSearchRecentQueryItemId(string) { - if let entry = CodableEntry(RecentWebSearchQueryItem()) { - transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, item: OrderedItemListEntry(id: itemId.rawValue, contents: entry), removeTailIfCountExceeds: 100) - } - } +func addRecentWebSearchQuery(engine: TelegramEngine, string: String) -> Signal { + if let itemId = WebSearchRecentQueryItemId(string) { + return engine.orderedLists.addOrMoveToFirstPosition(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, id: itemId.rawValue, item: RecentWebSearchQueryItem(), removeTailIfCountExceeds: 100) + } else { + return .complete() } } -func removeRecentWebSearchQuery(postbox: Postbox, string: String) -> Signal { - return postbox.transaction { transaction -> Void in - if let itemId = WebSearchRecentQueryItemId(string) { - transaction.removeOrderedItemListItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, itemId: itemId.rawValue) - } +func removeRecentWebSearchQuery(engine: TelegramEngine, string: String) -> Signal { + if let itemId = WebSearchRecentQueryItemId(string) { + return engine.orderedLists.removeItem(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, id: itemId.rawValue) + } else { + return .complete() } } -func clearRecentWebSearchQueries(postbox: Postbox) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.replaceOrderedItemListItems(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries, items: []) - } +func clearRecentWebSearchQueries(engine: TelegramEngine) -> Signal { + return engine.orderedLists.clear(collectionId: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries) } func webSearchRecentQueries(postbox: Postbox) -> Signal<[String], NoError> { return postbox.combinedView(keys: [.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)]) - |> mapToSignal { view -> Signal<[String], NoError> in - return postbox.transaction { transaction -> [String] in - var result: [String] = [] - if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)] as? OrderedItemListView { - for item in view.items { - let value = WebSearchRecentQueryItemId(item.id).value - result.append(value) - } - } - return result + |> mapToSignal { view -> Signal<[String], NoError> in + var result: [String] = [] + if let view = view.views[.orderedItemList(id: ApplicationSpecificOrderedItemListCollectionId.webSearchRecentQueries)] as? OrderedItemListView { + for item in view.items { + let value = WebSearchRecentQueryItemId(item.id).value + result.append(value) } + } + return .single(result) } }