diff --git a/submodules/AccountContext/Sources/GalleryController.swift b/submodules/AccountContext/Sources/GalleryController.swift index 376252b271..fbfab81a96 100644 --- a/submodules/AccountContext/Sources/GalleryController.swift +++ b/submodules/AccountContext/Sources/GalleryController.swift @@ -18,10 +18,10 @@ public final class GalleryControllerActionInteraction { public let openHashtag: (String?, String) -> Void public let openBotCommand: (String) -> Void public let addContact: (String) -> Void - public let storeMediaPlaybackState: (MessageId, Double?) -> Void + public let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void public let editMedia: (MessageId, [UIView], @escaping () -> Void) -> Void - public init(openUrl: @escaping (String, Bool) -> Void, openUrlIn: @escaping (String) -> Void, openPeerMention: @escaping (String) -> Void, openPeer: @escaping (PeerId) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, addContact: @escaping (String) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?) -> Void, editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void) { + public init(openUrl: @escaping (String, Bool) -> Void, openUrlIn: @escaping (String) -> Void, openPeerMention: @escaping (String) -> Void, openPeer: @escaping (PeerId) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, addContact: @escaping (String) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void, editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void) { self.openUrl = openUrl self.openUrlIn = openUrlIn self.openPeerMention = openPeerMention diff --git a/submodules/CallListUI/Sources/CallListControllerNode.swift b/submodules/CallListUI/Sources/CallListControllerNode.swift index 0640d5ed22..88354bfed8 100644 --- a/submodules/CallListUI/Sources/CallListControllerNode.swift +++ b/submodules/CallListUI/Sources/CallListControllerNode.swift @@ -384,6 +384,7 @@ final class CallListControllerNode: ASDisplayNode { let disposable = strongSelf.openGroupCallDisposable let account = strongSelf.context.account + let engine = strongSelf.context.engine var signal: Signal = strongSelf.context.account.postbox.transaction { transaction -> CachedChannelData.ActiveCall? in let cachedData = transaction.getPeerCachedData(peerId: peerId) if let cachedData = cachedData as? CachedChannelData { @@ -397,7 +398,7 @@ final class CallListControllerNode: ASDisplayNode { if let activeCall = activeCall { return .single(activeCall) } else { - return updatedCurrentPeerGroupCall(account: account, peerId: peerId) + return engine.calls.updatedCurrentPeerGroupCall(peerId: peerId) } } diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index 9c97c1d8bc..8c353d57e2 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -49,141 +49,162 @@ enum ChatContextMenuSource { func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: ChatListNodeEntryPromoInfo?, source: ChatContextMenuSource, chatListController: ChatListControllerImpl?, joined: Bool) -> Signal<[ContextMenuItem], NoError> { let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) let strings = presentationData.strings - return context.account.postbox.transaction { [weak chatListController] transaction -> [ContextMenuItem] in - if promoInfo != nil { - return [] - } - - 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: - break - } - } - - 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) + + return context.account.postbox.transaction { transaction -> (PeerGroupId, ChatListIndex)? in + transaction.getPeerChatListIndex(peerId) + } + |> mapToSignal { groupAndIndex -> Signal<[ContextMenuItem], NoError> in + let location: TogglePeerChatPinnedLocation + var chatListFilter: ChatListFilter? + if case let .chatList(filter) = source, let chatFilter = filter { + chatListFilter = chatFilter + location = .filter(chatFilter.id) + } else { + if let (group, _) = groupAndIndex { + location = .group(group) } 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 + location = .group(.root) } } - 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 { - 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.account.postbox.transaction { transaction -> Void in - updateChatListFiltersInteractively(transaction: transaction, { filters in - var filters = filters - for i in 0 ..< filters.count { - if filters[i].id == currentFilter.id { - let _ = filters[i].data.addExcludePeer(peerId: peer.id) - break + return combineLatest( + context.engine.peers.updatedChatListFilters() + |> take(1), + context.engine.peers.getPinnedItemIds(location: location) + ) + |> 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 [] + } + + 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: + break + } + } + + 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 { + 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 { + let _ = filters[i].data.addExcludePeer(peerId: peer.id) + 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: currentFilter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in + return false + }), in: .current) + }) + }) + }))) + } else { + var hasFolders = false + + for filter in filters { + let predicate = chatListFilterPredicate(filter: filter.data) + if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { + continue + } + + var data = filter.data + if data.addIncludePeer(peerId: peer.id) { + hasFolders = true + 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: currentFilter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in - return false - }), in: .current) - }) - }) - }))) - } else { - var hasFolders = false - updateChatListFiltersInteractively(transaction: transaction, { filters in - for filter in filters { - let predicate = chatListFilterPredicate(filter: filter.data) - if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { - continue } - - var data = filter.data - if data.addIncludePeer(peerId: peer.id) { - hasFolders = true - break - } - } - return filters - }) - - 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 - let _ = (context.account.postbox.transaction { transaction -> [ContextMenuItem] in - var updatedItems: [ContextMenuItem] = [] - updateChatListFiltersInteractively(transaction: transaction, { filters in + + 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 { let predicate = chatListFilterPredicate(filter: filter.data) if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) { continue } - + var data = filter.data if !data.addIncludePeer(peerId: peer.id) { continue } - + let filterType = chatListFilterType(filter) updatedItems.append(.action(ContextMenuActionItem(text: filter.title, icon: { theme in let imageName: String @@ -208,7 +229,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor) }, action: { c, f in c.dismiss(completion: { - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var filters = filters for i in 0 ..< filters.count { if filters[i].id == filter.id { @@ -217,180 +238,160 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch } } return filters - })).start() - + }).start() + chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: filter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) }) }))) } - - return filters - }) - - 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)) + + 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)) + }))) + + c.setItems(.single(updatedItems)) }))) - - return updatedItems } - |> deliverOnMainQueue).start(next: { updatedItems in - c.setItems(.single(updatedItems)) - }) + } + } + + 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) }))) } - } - } - - 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 groupAndIndex = transaction.getPeerChatListIndex(peerId) - - let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt32Value(777000)) && peerId == context.account.peerId - if let (group, index) = groupAndIndex { - if archiveEnabled { - let isArchived = group == Namespaces.PeerGroup.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) + + let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt32Value(777000)) && peerId == context.account.peerId + if let (group, index) = groupAndIndex { + if archiveEnabled { + let isArchived = group == Namespaces.PeerGroup.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) + } + |> 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: { _, f in + let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: .peer(peerId)) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .done: + break + case .limitExceeded: + break + } + f(.default) + }) + }))) + } + + 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 as? TelegramChannel { + items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_JoinChannel, 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 + if let navigationController = (chatListController?.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) + } + }, 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)) + } + })) + f(.default) + }))) } } - }))) - } - -// if { - let location: TogglePeerChatPinnedLocation - var chatListFilter: ChatListFilter? - if case let .chatList(filter) = source, let chatFilter = filter { - chatListFilter = chatFilter - location = .filter(chatFilter.id) - } else { - location = .group(group) } - - let isPinned = getPinnedItemIds(transaction: transaction, location: location).contains(.peer(peerId)) - - 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: { _, f in - let _ = (toggleItemPinned(postbox: context.account.postbox, location: location, itemId: .peer(peerId)) - |> deliverOnMainQueue).start(next: { result in - switch result { - case .done: - break - case .limitExceeded: - break - } - f(.default) - }) - }))) - } -// } - - 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 as? TelegramChannel { - items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_JoinChannel, 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() - } - } + + if case .chatList = source, groupAndIndex != 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) } - |> 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 - if let navigationController = (chatListController?.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) - } - }, 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)) - } - })) f(.default) }))) } + + if let item = items.last, case .separator = item { + items.removeLast() + } + + return items } } - - if case .chatList = source, groupAndIndex != 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 c8d8132a0e..6baa6ea005 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -892,7 +892,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController }) |> mapToSignal { selectedPeerIdsAndFilterId -> Signal<(ChatListSelectionOptions, Set)?, NoError> in if let (selectedPeerIds, filterId) = selectedPeerIdsAndFilterId { - return chatListSelectionOptions(postbox: context.account.postbox, peerIds: selectedPeerIds, filterId: filterId) + return chatListSelectionOptions(context: context, peerIds: selectedPeerIds, filterId: filterId) |> map { options -> (ChatListSelectionOptions, Set)? in return (options, selectedPeerIds) } @@ -982,7 +982,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard let strongSelf = self else { return } - let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox) + let _ = (strongSelf.context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { [weak self] filters in guard let strongSelf = self else { return @@ -996,7 +996,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard let strongSelf = self else { return } - let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox) + let _ = (strongSelf.context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { presetList in guard let strongSelf = self else { return @@ -1024,7 +1024,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard let strongSelf = self else { return } - let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox) + let _ = (strongSelf.context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { presetList in guard let strongSelf = self else { return @@ -1032,7 +1032,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController var found = false for filter in presetList { if filter.id == id { - let _ = (currentChatListFilters(postbox: strongSelf.context.account.postbox) + let _ = (strongSelf.context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { filters in guard let strongSelf = self else { return @@ -1300,7 +1300,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } |> take(1) - let initializedFilters = updatedChatListFiltersInfo(postbox: self.context.account.postbox) + let initializedFilters = self.context.engine.peers.updatedChatListFiltersInfo() |> mapToSignal { (filters, isInitialized) -> Signal in if isInitialized { return .single(!filters.isEmpty) @@ -1336,7 +1336,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let text: String if hasFilters { text = strongSelf.presentationData.strings.ChatList_TabIconFoldersTooltipNonEmptyFolders - let _ = markChatListFeaturedFiltersAsSeen(postbox: strongSelf.context.account.postbox).start() + let _ = strongSelf.context.engine.peers.markChatListFeaturedFiltersAsSeen().start() return } else { text = strongSelf.presentationData.strings.ChatList_TabIconFoldersTooltipEmptyFolders @@ -1495,7 +1495,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } if let reorderedFilterIds = reorderedFilterIdsValue { - let _ = (updateChatListFiltersInteractively(postbox: self.context.account.postbox, { stateFilters in + let _ = (self.context.engine.peers.updateChatListFiltersInteractively { stateFilters in var updatedFilters: [ChatListFilter] = [] for id in reorderedFilterIds { if let index = stateFilters.firstIndex(where: { $0.id == id }) { @@ -1510,7 +1510,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } }) return updatedFilters - }) + } |> deliverOnMainQueue).start(completed: { [weak self] in guard let strongSelf = self else { return @@ -1543,7 +1543,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } |> distinctUntilChanged - let filterItems = chatListFilterItems(postbox: self.context.account.postbox) + let filterItems = chatListFilterItems(context: self.context) var notifiedFirstUpdate = false self.filterDisposable.set((combineLatest(queue: .mainQueue(), context.account.postbox.combinedView(keys: [ @@ -1652,7 +1652,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } - let _ = (currentChatListFilters(postbox: self.context.account.postbox) + let _ = (self.context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { [weak self] filters in guard let strongSelf = self else { return @@ -1709,7 +1709,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } - let _ = updateChatListFiltersInteractively(postbox: strongSelf.context.account.postbox, { filters in + let _ = (strongSelf.context.engine.peers.updateChatListFiltersInteractively { filters in return filters.filter({ $0.id != id }) }).start() } @@ -2765,8 +2765,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController override public func tabBarItemContextAction(sourceNode: ContextExtractedContentContainingNode, gesture: ContextGesture) { let _ = (combineLatest(queue: .mainQueue(), - currentChatListFilters(postbox: self.context.account.postbox), - chatListFilterItems(postbox: self.context.account.postbox) + self.context.engine.peers.currentChatListFilters(), + chatListFilterItems(context: self.context) |> take(1) ) |> deliverOnMainQueue).start(next: { [weak self] presetList, filterItemsAndTotalCount in @@ -2774,7 +2774,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return } - let _ = markChatListFeaturedFiltersAsSeen(postbox: strongSelf.context.account.postbox).start() + let _ = strongSelf.context.engine.peers.markChatListFeaturedFiltersAsSeen().start() let (_, filterItems) = filterItemsAndTotalCount diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 1a4932dd6b..aedd7d3f15 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -624,7 +624,7 @@ private func internalChatListFilterAddChatsController(context: AccountContext, f } if applyAutomatically { - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var filters = filters for i in 0 ..< filters.count { if filters[i].id == filter.id { @@ -634,7 +634,7 @@ private func internalChatListFilterAddChatsController(context: AccountContext, f } } return filters - }) + } |> deliverOnMainQueue).start(next: { _ in controller?.dismiss() }) @@ -702,7 +702,7 @@ private func internalChatListFilterExcludeChatsController(context: AccountContex excludePeers.sort() if applyAutomatically { - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var filters = filters for i in 0 ..< filters.count { if filters[i].id == filter.id { @@ -714,7 +714,7 @@ private func internalChatListFilterExcludeChatsController(context: AccountContex } } return filters - }) + } |> deliverOnMainQueue).start(next: { _ in controller?.dismiss() }) @@ -835,7 +835,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat includePeers.setPeers(state.additionallyIncludePeers) let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) - let _ = (currentChatListFilters(postbox: context.account.postbox) + let _ = (context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { filters in let controller = internalChatListFilterAddChatsController(context: context, filter: filter, allFilters: filters, applyAutomatically: false, updated: { filter in skipStateAnimation = true @@ -856,7 +856,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat includePeers.setPeers(state.additionallyIncludePeers) let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) - let _ = (currentChatListFilters(postbox: context.account.postbox) + let _ = (context.engine.peers.currentChatListFilters() |> deliverOnMainQueue).start(next: { filters in let controller = internalChatListFilterExcludeChatsController(context: context, filter: filter, allFilters: filters, applyAutomatically: false, updated: { filter in skipStateAnimation = true @@ -985,12 +985,12 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat var attemptNavigationImpl: (() -> Bool)? let applyImpl: (() -> Void)? = { let state = stateValue.with { $0 } - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var includePeers = ChatListFilterIncludePeers() includePeers.setPeers(state.additionallyIncludePeers) var updatedFilter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) if currentPreset == nil { - updatedFilter.id = generateNewChatListFilterId(filters: filters) + updatedFilter.id = context.engine.peers.generateNewChatListFilterId(filters: filters) } var filters = filters if let _ = currentPreset { @@ -1017,7 +1017,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat filters.append(updatedFilter) } return filters - }) + } |> deliverOnMainQueue).start(next: { filters in updated(filters) dismissImpl?() diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index 9142a50166..75cb00bd1f 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -249,12 +249,12 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch let arguments = ChatListFilterPresetListControllerArguments(context: context, addSuggestedPresed: { title, data in - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var filters = filters - let id = generateNewChatListFilterId(filters: filters) + let id = context.engine.peers.generateNewChatListFilterId(filters: filters) filters.insert(ChatListFilter(id: id, title: title, emoticon: nil, data: data), at: 0) return filters - }) + } |> deliverOnMainQueue).start(next: { _ in }) }, openPreset: { preset in @@ -279,13 +279,13 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch ActionSheetButtonItem(title: presentationData.strings.ChatList_RemoveFolderAction, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var filters = filters if let index = filters.firstIndex(where: { $0.id == id }) { filters.remove(at: index) } return filters - }) + } |> deliverOnMainQueue).start() }) ]), @@ -300,30 +300,12 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch let chatCountCache = Atomic<[ChatListFilterData: Int]>(value: [:]) - let filtersWithCountsSignal = updatedChatListFilters(postbox: context.account.postbox) + let filtersWithCountsSignal = context.engine.peers.updatedChatListFilters() |> distinctUntilChanged |> mapToSignal { filters -> Signal<[(ChatListFilter, Int)], NoError> in return .single(filters.map { filter -> (ChatListFilter, Int) in return (filter, 0) }) - /*return context.account.postbox.transaction { transaction -> [(ChatListFilter, Int)] in - return filters.map { filter -> (ChatListFilter, Int) in - let count: Int - if let cachedValue = chatCountCache.with({ dict -> Int? in - return dict[filter.data] - }) { - count = cachedValue - } else { - count = transaction.getChatCountMatchingPredicate(chatListFilterPredicate(filter: filter.data)) - let _ = chatCountCache.modify { dict in - var dict = dict - dict[filter.data] = count - return dict - } - } - return (filter, count) - } - }*/ } let featuredFilters = context.account.postbox.preferencesView(keys: [PreferencesKeys.chatListFiltersFeaturedState]) @@ -368,7 +350,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch |> take(1) |> deliverOnMainQueue).start(next: { [weak updatedFilterOrder] updatedFilterOrderValue in if let updatedFilterOrderValue = updatedFilterOrderValue { - let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in + let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in var updatedFilters: [ChatListFilter] = [] for id in updatedFilterOrderValue { if let index = filters.firstIndex(where: { $0.id == id }) { @@ -382,7 +364,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch } return updatedFilters - }) + } |> deliverOnMainQueue).start(next: { _ in filtersWithCounts.set(filtersWithCountsSignal) let _ = (filtersWithCounts.get() diff --git a/submodules/ChatListUI/Sources/ChatListSelection.swift b/submodules/ChatListUI/Sources/ChatListSelection.swift index 869a2fae27..3c0c533c59 100644 --- a/submodules/ChatListUI/Sources/ChatListSelection.swift +++ b/submodules/ChatListUI/Sources/ChatListSelection.swift @@ -4,6 +4,7 @@ import SwiftSignalKit import Postbox import TelegramCore import SyncCore +import AccountContext enum ChatListSelectionReadOption: Equatable { case all(enabled: Bool) @@ -15,10 +16,10 @@ struct ChatListSelectionOptions: Equatable { let delete: Bool } -func chatListSelectionOptions(postbox: Postbox, peerIds: Set, filterId: Int32?) -> Signal { +func chatListSelectionOptions(context: AccountContext, peerIds: Set, filterId: Int32?) -> Signal { if peerIds.isEmpty { if let filterId = filterId { - return chatListFilterItems(postbox: postbox) + return chatListFilterItems(context: context) |> map { filterItems -> ChatListSelectionOptions in for (filter, unreadCount, _) in filterItems.1 { if filter.id == filterId { @@ -30,7 +31,7 @@ func chatListSelectionOptions(postbox: Postbox, peerIds: Set, filterId: |> distinctUntilChanged } else { let key = PostboxViewKey.unreadCounts(items: [.total(nil)]) - return postbox.combinedView(keys: [key]) + return context.account.postbox.combinedView(keys: [key]) |> map { view -> ChatListSelectionOptions in var hasUnread = false if let unreadCounts = view.views[key] as? UnreadMessageCountsView, let total = unreadCounts.total() { @@ -48,7 +49,7 @@ func chatListSelectionOptions(postbox: Postbox, peerIds: Set, filterId: } else { let items: [UnreadMessageCountsItem] = peerIds.map(UnreadMessageCountsItem.peer) let key = PostboxViewKey.unreadCounts(items: items) - return postbox.combinedView(keys: [key]) + return context.account.postbox.combinedView(keys: [key]) |> map { view -> ChatListSelectionOptions in var hasUnread = false if let unreadCounts = view.views[key] as? UnreadMessageCountsView { diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index c4abbc84fb..8f430c32b2 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -703,7 +703,7 @@ public final class ChatListNode: ListView { } else { location = .group(groupId) } - let _ = (toggleItemPinned(postbox: context.account.postbox, location: location, itemId: itemId) + let _ = (context.engine.peers.toggleItemPinned(location: location, itemId: itemId) |> deliverOnMainQueue).start(next: { result in if let strongSelf = self { switch result { @@ -1204,16 +1204,18 @@ public final class ChatListNode: ListView { } if case let .index(index) = fromEntry.sortIndex, let _ = index.pinningIndex { - return strongSelf.context.account.postbox.transaction { transaction -> Bool in - let location: TogglePeerChatPinnedLocation - if let chatListFilter = chatListFilter { - location = .filter(chatListFilter.id) - } else { - location = .group(groupId) - } - - var itemIds = getPinnedItemIds(transaction: transaction, location: location) - + let location: TogglePeerChatPinnedLocation + if let chatListFilter = chatListFilter { + location = .filter(chatListFilter.id) + } else { + location = .group(groupId) + } + + let engine = strongSelf.context.engine + return engine.peers.getPinnedItemIds(location: location) + |> mapToSignal { itemIds -> Signal in + var itemIds = itemIds + var itemId: PinnedItemId? switch fromEntry { case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): @@ -1221,7 +1223,7 @@ public final class ChatListNode: ListView { default: break } - + if let itemId = itemId { itemIds = itemIds.filter({ $0 != itemId }) if let referenceId = referenceId { @@ -1245,9 +1247,9 @@ public final class ChatListNode: ListView { } else { itemIds.append(itemId) } - return reorderPinnedItemIds(transaction: transaction, location: location, itemIds: itemIds) + return engine.peers.reorderPinnedItemIds(location: location, itemIds: itemIds) } else { - return false + return .single(false) } } } @@ -1378,7 +1380,7 @@ public final class ChatListNode: ListView { private func resetFilter() { if let chatListFilter = self.chatListFilter { - self.updatedFilterDisposable.set((updatedChatListFilters(postbox: self.context.account.postbox) + self.updatedFilterDisposable.set((self.context.engine.peers.updatedChatListFilters() |> map { filters -> ChatListFilter? in for filter in filters { if filter.id == chatListFilter.id { diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index ab390011a9..e930adb883 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -10,8 +10,8 @@ import Postbox import TelegramUIPreferences import TelegramCore -func chatListFilterItems(postbox: Postbox) -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> { - return updatedChatListFilters(postbox: postbox) +func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> { + return context.engine.peers.updatedChatListFilters() |> distinctUntilChanged |> mapToSignal { filters -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> in var unreadCountItems: [UnreadMessageCountsItem] = [] @@ -40,8 +40,8 @@ func chatListFilterItems(postbox: Postbox) -> Signal<(Int, [(ChatListFilter, Int keys.append(.basicPeer(peerId)) } - return combineLatest(queue: postbox.queue, - postbox.combinedView(keys: keys), + return combineLatest(queue: context.account.postbox.queue, + context.account.postbox.combinedView(keys: keys), Signal.single(true) ) |> map { view, _ -> (Int, [(ChatListFilter, Int, Bool)]) in @@ -63,7 +63,7 @@ func chatListFilterItems(postbox: Postbox) -> Signal<(Int, [(ChatListFilter, Int case let .peer(peerId, state): if let state = state, state.isUnread { if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer { - let tag = postbox.seedConfiguration.peerSummaryCounterTags(peer, peerView.isContact) + let tag = context.account.postbox.seedConfiguration.peerSummaryCounterTags(peer, peerView.isContact) var peerCount = Int(state.count) if state.isUnread { diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 2e2c6c20ee..8a796df36a 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -574,10 +574,11 @@ private enum DebugControllerEntry: ItemListNodeEntry { if let context = arguments.context { let _ = (context.account.postbox.transaction { transaction -> Void in transaction.clearItemCacheCollection(collectionId: Namespaces.CachedItemCollection.cachedPollResults) - unmarkChatListFeaturedFiltersAsSeen(transaction: transaction) transaction.clearItemCacheCollection(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks) }).start() + + let _ = context.engine.peers.unmarkChatListFeaturedFiltersAsSeen() } }) case .crash: diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 8f677e6c73..11f2cf8a17 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -239,7 +239,7 @@ open class NavigationBar: ASDisplayNode { var presentationData: NavigationBarPresentationData - private var validLayout: (size: CGSize, defaultHeight: CGFloat, additionalTopHeight: CGFloat, additionalContentHeight: CGFloat, additionalBackgroundHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, appearsHidden: Bool)? + private var validLayout: (size: CGSize, defaultHeight: CGFloat, additionalTopHeight: CGFloat, additionalContentHeight: CGFloat, additionalBackgroundHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, appearsHidden: Bool, isLandscape: Bool)? private var requestedLayout: Bool = false var requestContainerLayout: (ContainedViewLayoutTransition) -> Void = { _ in } @@ -940,16 +940,16 @@ open class NavigationBar: ASDisplayNode { if let validLayout = self.validLayout, self.requestedLayout { self.requestedLayout = false - self.updateLayout(size: validLayout.size, defaultHeight: validLayout.defaultHeight, additionalTopHeight: validLayout.additionalTopHeight, additionalContentHeight: validLayout.additionalContentHeight, additionalBackgroundHeight: validLayout.additionalBackgroundHeight, leftInset: validLayout.leftInset, rightInset: validLayout.rightInset, appearsHidden: validLayout.appearsHidden, transition: .immediate) + self.updateLayout(size: validLayout.size, defaultHeight: validLayout.defaultHeight, additionalTopHeight: validLayout.additionalTopHeight, additionalContentHeight: validLayout.additionalContentHeight, additionalBackgroundHeight: validLayout.additionalBackgroundHeight, leftInset: validLayout.leftInset, rightInset: validLayout.rightInset, appearsHidden: validLayout.appearsHidden, isLandscape: validLayout.isLandscape, transition: .immediate) } } - func updateLayout(size: CGSize, defaultHeight: CGFloat, additionalTopHeight: CGFloat, additionalContentHeight: CGFloat, additionalBackgroundHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, appearsHidden: Bool, transition: ContainedViewLayoutTransition) { + func updateLayout(size: CGSize, defaultHeight: CGFloat, additionalTopHeight: CGFloat, additionalContentHeight: CGFloat, additionalBackgroundHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, appearsHidden: Bool, isLandscape: Bool, transition: ContainedViewLayoutTransition) { if self.layoutSuspended { return } - self.validLayout = (size, defaultHeight, additionalTopHeight, additionalContentHeight, additionalBackgroundHeight, leftInset, rightInset, appearsHidden) + self.validLayout = (size, defaultHeight, additionalTopHeight, additionalContentHeight, additionalBackgroundHeight, leftInset, rightInset, appearsHidden, isLandscape) let backgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height + additionalBackgroundHeight)) if self.backgroundNode.frame != backgroundFrame { @@ -995,7 +995,7 @@ open class NavigationBar: ASDisplayNode { var leftTitleInset: CGFloat = leftInset + 1.0 var rightTitleInset: CGFloat = rightInset + 1.0 if self.backButtonNode.supernode != nil { - let backButtonSize = self.backButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight)) + let backButtonSize = self.backButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape) leftTitleInset += backButtonSize.width + backButtonInset + 1.0 let topHitTestSlop = (nominalHeight - backButtonSize.height) * 0.5 @@ -1047,7 +1047,7 @@ open class NavigationBar: ASDisplayNode { self.badgeNode.alpha = 1.0 } } else if self.leftButtonNode.supernode != nil { - let leftButtonSize = self.leftButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight)) + let leftButtonSize = self.leftButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape) leftTitleInset += leftButtonSize.width + leftButtonInset + 1.0 self.leftButtonNode.alpha = 1.0 @@ -1059,7 +1059,7 @@ open class NavigationBar: ASDisplayNode { transition.updateFrame(node: self.badgeNode, frame: CGRect(origin: backButtonArrowFrame.origin.offsetBy(dx: 7.0, dy: -9.0), size: badgeSize)) if self.rightButtonNode.supernode != nil { - let rightButtonSize = self.rightButtonNode.updateLayout(constrainedSize: (CGSize(width: size.width, height: nominalHeight))) + let rightButtonSize = self.rightButtonNode.updateLayout(constrainedSize: (CGSize(width: size.width, height: nominalHeight)), isLandscape: isLandscape) rightTitleInset += rightButtonSize.width + leftButtonInset + 1.0 self.rightButtonNode.alpha = 1.0 transition.updateFrame(node: self.rightButtonNode, frame: CGRect(origin: CGPoint(x: size.width - leftButtonInset - rightButtonSize.width, y: contentVerticalOrigin + floor((nominalHeight - rightButtonSize.height) / 2.0)), size: rightButtonSize)) @@ -1073,7 +1073,7 @@ open class NavigationBar: ASDisplayNode { break case .bottom: if let transitionBackButtonNode = self.transitionBackButtonNode { - let transitionBackButtonSize = transitionBackButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight)) + let transitionBackButtonSize = transitionBackButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape) let initialX: CGFloat = backButtonInset + size.width * 0.3 let finalX: CGFloat = floor((size.width - transitionBackButtonSize.width) / 2.0) @@ -1204,7 +1204,7 @@ open class NavigationBar: ASDisplayNode { node.updateManualText(self.backButtonNode.manualText) node.color = accentColor if let validLayout = self.validLayout { - let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight)) + let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape) node.frame = self.backButtonNode.frame } return node @@ -1227,7 +1227,7 @@ open class NavigationBar: ASDisplayNode { node.updateItems(items) node.color = accentColor if let validLayout = self.validLayout { - let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight)) + let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape) node.frame = self.backButtonNode.frame } return node diff --git a/submodules/Display/Source/NavigationButtonNode.swift b/submodules/Display/Source/NavigationButtonNode.swift index 4ad1cd4318..8cb826e190 100644 --- a/submodules/Display/Source/NavigationButtonNode.swift +++ b/submodules/Display/Source/NavigationButtonNode.swift @@ -255,8 +255,6 @@ private final class NavigationButtonItemNode: ImmediateTextNode { public override func touchesMoved(_ touches: Set, with event: UIEvent?) { super.touchesMoved(touches, with: event) - - //self.updateHighlightedState(self.touchInsideApparentBounds(touches.first!), animated: true) } public override func touchesEnded(_ touches: Set, with event: UIEvent?) { @@ -274,6 +272,15 @@ private final class NavigationButtonItemNode: ImmediateTextNode { self.pressed() } } + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if let node = self.node as? HighlightableButtonNode { + let result = node.view.hitTest(self.view.convert(point, to: node.view), with: event) + return result + } else { + return super.hitTest(point, with: event) + } + } public override func touchesCancelled(_ touches: Set?, with event: UIEvent?) { super.touchesCancelled(touches, with: event) @@ -453,7 +460,7 @@ public final class NavigationButtonNode: ASDisplayNode { } } - public func updateLayout(constrainedSize: CGSize) -> CGSize { + public func updateLayout(constrainedSize: CGSize, isLandscape: Bool) -> CGSize { var nodeOrigin = CGPoint() var totalSize = CGSize() for node in self.nodes { @@ -468,6 +475,9 @@ public final class NavigationButtonNode: ASDisplayNode { totalSize.height = max(totalSize.height, nodeSize.height) node.frame = CGRect(origin: CGPoint(x: nodeOrigin.x, y: floor((totalSize.height - nodeSize.height) / 2.0)), size: nodeSize) nodeOrigin.x += node.bounds.width + if isLandscape { + nodeOrigin.x += 16.0 + } } return totalSize } diff --git a/submodules/Display/Source/ViewController.swift b/submodules/Display/Source/ViewController.swift index 924cd07fe6..b5b9e7cac5 100644 --- a/submodules/Display/Source/ViewController.swift +++ b/submodules/Display/Source/ViewController.swift @@ -381,6 +381,8 @@ public enum TabBarItemContextActionType { } self.navigationBarOrigin = navigationBarFrame.origin.y + + let isLandscape = layout.size.width > layout.size.height if let navigationBar = self.navigationBar { if let contentNode = navigationBar.contentNode, case .expansion = contentNode.mode, !self.displayNavigationBar { @@ -392,7 +394,7 @@ public enum TabBarItemContextActionType { navigationBarFrame.size.height += NavigationBar.defaultSecondaryContentHeight //navigationBarFrame.origin.y += NavigationBar.defaultSecondaryContentHeight } - navigationBar.updateLayout(size: navigationBarFrame.size, defaultHeight: navigationLayout.defaultContentHeight, additionalTopHeight: statusBarHeight, additionalContentHeight: self.additionalNavigationBarHeight, additionalBackgroundHeight: additionalBackgroundHeight, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, appearsHidden: !self.displayNavigationBar, transition: transition) + navigationBar.updateLayout(size: navigationBarFrame.size, defaultHeight: navigationLayout.defaultContentHeight, additionalTopHeight: statusBarHeight, additionalContentHeight: self.additionalNavigationBarHeight, additionalBackgroundHeight: additionalBackgroundHeight, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, appearsHidden: !self.displayNavigationBar, isLandscape: isLandscape, transition: transition) if !transition.isAnimated { navigationBar.layer.cancelAnimationsRecursive(key: "bounds") navigationBar.layer.cancelAnimationsRecursive(key: "position") diff --git a/submodules/FFMpegBinding/Sources/FFMpegSWResample.m b/submodules/FFMpegBinding/Sources/FFMpegSWResample.m index 16c2a888dc..f8e68d51b0 100644 --- a/submodules/FFMpegBinding/Sources/FFMpegSWResample.m +++ b/submodules/FFMpegBinding/Sources/FFMpegSWResample.m @@ -6,11 +6,16 @@ #import "libswresample/swresample.h" @interface FFMpegSWResample () { - int _sourceChannelCount; + int _sourceSampleRate; + FFMpegAVSampleFormat _sourceSampleFormat; + int _destinationChannelCount; + int _destinationSampleRate; + FFMpegAVSampleFormat _destinationSampleFormat; + + int _currentSourceChannelCount; + SwrContext *_context; NSUInteger _ratio; - NSInteger _destinationChannelCount; - enum FFMpegAVSampleFormat _destinationSampleFormat; void *_buffer; int _bufferSize; } @@ -22,36 +27,57 @@ - (instancetype)initWithSourceChannelCount:(NSInteger)sourceChannelCount sourceSampleRate:(NSInteger)sourceSampleRate sourceSampleFormat:(enum FFMpegAVSampleFormat)sourceSampleFormat destinationChannelCount:(NSInteger)destinationChannelCount destinationSampleRate:(NSInteger)destinationSampleRate destinationSampleFormat:(enum FFMpegAVSampleFormat)destinationSampleFormat { self = [super init]; if (self != nil) { - _sourceChannelCount = sourceChannelCount; - _destinationChannelCount = destinationChannelCount; + _sourceSampleRate = (int)sourceSampleRate; + _sourceSampleFormat = sourceSampleFormat; + _destinationChannelCount = (int)destinationChannelCount; + _destinationSampleRate = (int)destinationSampleRate; _destinationSampleFormat = destinationSampleFormat; - _context = swr_alloc_set_opts(NULL, - av_get_default_channel_layout((int)destinationChannelCount), - (enum AVSampleFormat)destinationSampleFormat, - (int)destinationSampleRate, - av_get_default_channel_layout((int)sourceChannelCount), - (enum AVSampleFormat)sourceSampleFormat, - (int)sourceSampleRate, - 0, - NULL); - _ratio = MAX(1, destinationSampleRate / MAX(sourceSampleRate, 1)) * MAX(1, destinationChannelCount / sourceChannelCount) * 2; - swr_init(_context); + + _currentSourceChannelCount = -1; } return self; } - (void)dealloc { - swr_free(&_context); + if (_context) { + swr_free(&_context); + } if (_buffer) { free(_buffer); } } +- (void)resetContextForChannelCount:(int)channelCount { + if (_context) { + swr_free(&_context); + _context = NULL; + } + + _context = swr_alloc_set_opts(NULL, + av_get_default_channel_layout((int)_destinationChannelCount), + (enum AVSampleFormat)_destinationSampleFormat, + (int)_destinationSampleRate, + av_get_default_channel_layout(channelCount), + (enum AVSampleFormat)_sourceSampleFormat, + (int)_sourceSampleRate, + 0, + NULL); + _currentSourceChannelCount = channelCount; + _ratio = MAX(1, _destinationSampleRate / MAX(_sourceSampleRate, 1)) * MAX(1, _destinationChannelCount / channelCount) * 2; + if (_context) { + swr_init(_context); + } +} + - (NSData * _Nullable)resample:(FFMpegAVFrame *)frame { AVFrame *frameImpl = (AVFrame *)[frame impl]; int numChannels = frameImpl->channels; - if (numChannels != _sourceChannelCount) { + if (numChannels != _currentSourceChannelCount) { + [self resetContextForChannelCount:numChannels]; + } + + if (!_context) { return nil; } diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index b3482de298..ba873e0d3c 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -230,20 +230,20 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati let gallery = SecretMediaPreviewController(context: context, messageId: message.id) return .secretGallery(gallery) } else { - let startTimecode: Signal + let startState: Signal<(timecode: Double?, rate: Double), NoError> if let timecode = timecode { - startTimecode = .single(timecode) + startState = .single((timecode: timecode, rate: 1.0)) } else { - startTimecode = mediaPlaybackStoredState(postbox: context.account.postbox, messageId: message.id) + startState = mediaPlaybackStoredState(postbox: context.account.postbox, messageId: message.id) |> map { state in - return state?.timestamp + return (state?.timestamp, state?.playbackRate.doubleValue ?? 1.0) } } - return .gallery(startTimecode + return .gallery(startState |> deliverOnMainQueue - |> map { timecode in - let gallery = GalleryController(context: context, source: source ?? (standalone ? .standaloneMessage(message) : .peerMessagesAtId(messageId: message.id, chatLocation: chatLocation ?? .peer(message.id.peerId), chatLocationContextHolder: chatLocationContextHolder ?? Atomic(value: nil))), invertItemOrder: reverseMessageGalleryOrder, streamSingleVideo: stream, fromPlayingVideo: autoplayingVideo, landscape: landscape, timecode: timecode, synchronousLoad: synchronousLoad, replaceRootController: { [weak navigationController] controller, ready in + |> map { startState in + let gallery = GalleryController(context: context, source: source ?? (standalone ? .standaloneMessage(message) : .peerMessagesAtId(messageId: message.id, chatLocation: chatLocation ?? .peer(message.id.peerId), chatLocationContextHolder: chatLocationContextHolder ?? Atomic(value: nil))), invertItemOrder: reverseMessageGalleryOrder, streamSingleVideo: stream, fromPlayingVideo: autoplayingVideo, landscape: landscape, timecode: startState.timecode, playbackRate: startState.rate, synchronousLoad: synchronousLoad, replaceRootController: { [weak navigationController] controller, ready in navigationController?.replaceTopController(controller, animated: false, ready: ready) }, baseNavigationController: navigationController, actionInteraction: actionInteraction) gallery.temporaryDoNotWaitForReady = autoplayingVideo diff --git a/submodules/GalleryUI/BUILD b/submodules/GalleryUI/BUILD index 6a06062b21..59860c2bf8 100644 --- a/submodules/GalleryUI/BUILD +++ b/submodules/GalleryUI/BUILD @@ -28,7 +28,10 @@ swift_library( "//submodules/OverlayStatusController:OverlayStatusController", "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/UrlEscaping:UrlEscaping", - "//submodules/ManagedAnimationNode:ManagedAnimationNode" + "//submodules/ManagedAnimationNode:ManagedAnimationNode", + "//submodules/ContextUI:ContextUI", + "//submodules/SaveToCameraRoll:SaveToCameraRoll", + "//submodules/TelegramUIPreferences:TelegramUIPreferences", ], visibility = [ "//visibility:public", diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index d099fe3d7b..d7ae82a8aa 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -31,6 +31,9 @@ private let forwardImage = generateTintedImage(image: UIImage(bundleImageName: " private let cloudFetchIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/FileCloudFetch"), color: UIColor.white) +private let fullscreenOnImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Expand"), color: .white) +private let fullscreenOffImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Collapse"), color: .white) + private let captionMaskImage = generateImage(CGSize(width: 1.0, height: 17.0), opaque: false, rotatedContext: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) context.clear(bounds) @@ -119,6 +122,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll private let contentNode: ASDisplayNode private let deleteButton: UIButton + private let fullscreenButton: UIButton private let actionButton: UIButton private let editButton: UIButton private let maskNode: ASDisplayNode @@ -152,6 +156,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll var seekBackward: ((Double) -> Void)? var seekForward: ((Double) -> Void)? var setPlayRate: ((Double) -> Void)? + var toggleFullscreen: (() -> Void)? var fetchControl: (() -> Void)? var interacting: ((Bool) -> Void)? @@ -286,6 +291,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.contentNode = ASDisplayNode() self.deleteButton = UIButton() + self.fullscreenButton = UIButton() self.actionButton = UIButton() self.editButton = UIButton() @@ -363,6 +369,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } self.contentNode.view.addSubview(self.deleteButton) + self.contentNode.view.addSubview(self.fullscreenButton) self.contentNode.view.addSubview(self.actionButton) self.contentNode.view.addSubview(self.editButton) self.contentNode.addSubnode(self.scrollWrapperNode) @@ -381,6 +388,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.contentNode.addSubnode(self.statusButtonNode) self.deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), for: [.touchUpInside]) + self.fullscreenButton.addTarget(self, action: #selector(self.fullscreenButtonPressed), for: [.touchUpInside]) self.actionButton.addTarget(self, action: #selector(self.actionButtonPressed), for: [.touchUpInside]) self.editButton.addTarget(self, action: #selector(self.editButtonPressed), for: [.touchUpInside]) @@ -559,6 +567,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll if origin == nil { self.editButton.isHidden = true self.deleteButton.isHidden = true + self.fullscreenButton.isHidden = true self.editButton.isHidden = true } } @@ -568,12 +577,22 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll let canDelete: Bool var canShare = !message.containsSecretMedia + + var canFullscreen = false var canEdit = false for media in message.media { if media is TelegramMediaImage { canEdit = true - break + } else if let media = media as? TelegramMediaFile, !media.isAnimated { + for attribute in media.attributes { + switch attribute { + case .Video: + canFullscreen = true + default: + break + } + } } } @@ -637,7 +656,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities) } - if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { + if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canFullscreen != !self.fullscreenButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { self.currentMessageText = messageText if messageText.length == 0 { @@ -654,8 +673,15 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.authorNameNode.attributedText = nil } self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white) - - self.deleteButton.isHidden = !canDelete + + if canFullscreen { + self.fullscreenButton.isHidden = false + self.deleteButton.isHidden = true + } else { + self.deleteButton.isHidden = !canDelete + self.fullscreenButton.isHidden = true + } + self.actionButton.isHidden = !canShare self.editButton.isHidden = !canEdit @@ -683,6 +709,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll panelHeight += contentInset let isLandscape = size.width > size.height + + self.fullscreenButton.setImage(isLandscape ? fullscreenOffImage : fullscreenOnImage, for: [.normal]) + let displayCaption: Bool if case .compact = metrics.widthClass { displayCaption = !self.textNode.isHidden && !isLandscape @@ -776,10 +805,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll let deleteFrame = CGRect(origin: CGPoint(x: width - 44.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) var editFrame = CGRect(origin: CGPoint(x: width - 44.0 - 50.0 - rightInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) - if self.deleteButton.isHidden { + if self.deleteButton.isHidden && self.fullscreenButton.isHidden { editFrame = deleteFrame } self.deleteButton.frame = deleteFrame + self.fullscreenButton.frame = deleteFrame self.editButton.frame = editFrame if let image = self.backwardButton.backgroundIconNode.image { @@ -789,7 +819,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.forwardButton.frame = CGRect(origin: CGPoint(x: floor((width - image.size.width) / 2.0) + 66.0, y: panelHeight - bottomInset - 44.0 + 7.0), size: image.size) } - self.playbackControlButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0), y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0)) + self.playbackControlButton.frame = CGRect(origin: CGPoint(x: floor((width - 44.0) / 2.0), y: panelHeight - bottomInset - 44.0 - 2.0), size: CGSize(width: 44.0, height: 44.0)) self.playPauseIconNode.frame = self.playbackControlButton.bounds.offsetBy(dx: 2.0, dy: 2.0) let statusSize = CGSize(width: 28.0, height: 28.0) @@ -855,6 +885,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.dateNode.alpha = 1.0 self.authorNameNode.alpha = 1.0 self.deleteButton.alpha = 1.0 + self.fullscreenButton.alpha = 1.0 self.actionButton.alpha = 1.0 self.editButton.alpha = 1.0 self.backwardButton.alpha = 1.0 @@ -878,6 +909,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.dateNode.alpha = 0.0 self.authorNameNode.alpha = 0.0 self.deleteButton.alpha = 0.0 + self.fullscreenButton.alpha = 0.0 self.actionButton.alpha = 0.0 self.editButton.alpha = 0.0 self.backwardButton.alpha = 0.0 @@ -888,6 +920,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll completion() }) } + + @objc func fullscreenButtonPressed() { + self.toggleFullscreen?() + } @objc func deleteButtonPressed() { if let currentMessage = self.currentMessage { diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index d55e5ff53f..3d32dc868e 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -145,7 +145,7 @@ private func galleryMessageCaptionText(_ message: Message) -> String { return message.text } -public func galleryItemForEntry(context: AccountContext, presentationData: PresentationData, entry: MessageHistoryEntry, isCentral: Bool = false, streamVideos: Bool, loopVideos: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, landscape: Bool = false, timecode: Double? = nil, displayInfoOnTop: Bool = false, configuration: GalleryConfiguration? = nil, tempFilePath: String? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, openActionOptions: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, storeMediaPlaybackState: @escaping (MessageId, Double?) -> Void = { _, _ in }, present: @escaping (ViewController, Any?) -> Void) -> GalleryItem? { +public func galleryItemForEntry(context: AccountContext, presentationData: PresentationData, entry: MessageHistoryEntry, isCentral: Bool = false, streamVideos: Bool, loopVideos: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, isSecret: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: Double = 1.0, displayInfoOnTop: Bool = false, configuration: GalleryConfiguration? = nil, tempFilePath: String? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, openActionOptions: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void = { _, _, _ in }, present: @escaping (ViewController, Any?) -> Void) -> GalleryItem? { let message = entry.message let location = entry.location if let (media, mediaImage) = mediaForMessage(message: message) { @@ -178,7 +178,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese } let caption = galleryCaptionStringWithAppliedEntities(text, entities: entities) - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: caption, displayInfoOnTop: displayInfoOnTop, hideControls: hideControls, fromPlayingVideo: fromPlayingVideo, landscape: landscape, timecode: timecode, configuration: configuration, playbackCompleted: playbackCompleted, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: caption, displayInfoOnTop: displayInfoOnTop, hideControls: hideControls, fromPlayingVideo: fromPlayingVideo, isSecret: isSecret, landscape: landscape, timecode: timecode, playbackRate: playbackRate, configuration: configuration, playbackCompleted: playbackCompleted, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) } else { if let fileName = file.fileName, (fileName as NSString).pathExtension.lowercased() == "json" { return ChatAnimationGalleryItem(context: context, presentationData: presentationData, message: message, location: location) @@ -188,7 +188,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese if let dimensions = file.dimensions { pixelsCount = Int(dimensions.width) * Int(dimensions.height) } - if (file.size == nil || file.size! < 4 * 1024 * 1024) && pixelsCount < 4096 * 4096 { + if pixelsCount < 10000 * 10000 { return ChatImageGalleryItem(context: context, presentationData: presentationData, message: message, location: location, displayInfoOnTop: displayInfoOnTop, performAction: performAction, openActionOptions: openActionOptions, present: present) } else { return ChatDocumentGalleryItem(context: context, presentationData: presentationData, message: message, location: location) @@ -219,7 +219,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese } } if let content = content { - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: NSAttributedString(string: ""), displayInfoOnTop: displayInfoOnTop, fromPlayingVideo: fromPlayingVideo, landscape: landscape, timecode: timecode, configuration: configuration, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: NSAttributedString(string: ""), displayInfoOnTop: displayInfoOnTop, fromPlayingVideo: fromPlayingVideo, isSecret: isSecret, landscape: landscape, timecode: timecode, playbackRate: playbackRate, configuration: configuration, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) } else { return nil } @@ -349,6 +349,7 @@ public class GalleryController: ViewController, StandalonePresentableController private let fromPlayingVideo: Bool private let landscape: Bool private let timecode: Double? + private let playbackRate: Double private let accountInUseDisposable = MetaDisposable() private let disposable = MetaDisposable() @@ -388,7 +389,7 @@ public class GalleryController: ViewController, StandalonePresentableController private var initialOrientation: UIInterfaceOrientation? - public init(context: AccountContext, source: GalleryControllerItemSource, invertItemOrder: Bool = false, streamSingleVideo: Bool = false, fromPlayingVideo: Bool = false, landscape: Bool = false, timecode: Double? = nil, synchronousLoad: Bool = false, replaceRootController: @escaping (ViewController, Promise?) -> Void, baseNavigationController: NavigationController?, actionInteraction: GalleryControllerActionInteraction? = nil) { + public init(context: AccountContext, source: GalleryControllerItemSource, invertItemOrder: Bool = false, streamSingleVideo: Bool = false, fromPlayingVideo: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: Double = 1.0, synchronousLoad: Bool = false, replaceRootController: @escaping (ViewController, Promise?) -> Void, baseNavigationController: NavigationController?, actionInteraction: GalleryControllerActionInteraction? = nil) { self.context = context self.source = source self.invertItemOrder = invertItemOrder @@ -399,6 +400,7 @@ public class GalleryController: ViewController, StandalonePresentableController self.fromPlayingVideo = fromPlayingVideo self.landscape = landscape self.timecode = timecode + self.playbackRate = playbackRate self.presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -537,7 +539,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == strongSelf.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, playbackRate: isCentral ? playbackRate : 1.0, displayInfoOnTop: displayInfoOnTop, configuration: configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } @@ -1040,6 +1042,9 @@ public class GalleryController: ViewController, StandalonePresentableController self.galleryNode.baseNavigationController = { [weak baseNavigationController] in return baseNavigationController } + self.galleryNode.galleryController = { [weak self] in + return self + } var displayInfoOnTop = false if case .custom = source { @@ -1053,7 +1058,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == self.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: entry, streamVideos: self.streamVideos, fromPlayingVideo: isCentral && self.fromPlayingVideo, landscape: isCentral && self.landscape, timecode: isCentral ? self.timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: self.configuration, performAction: self.performAction, openActionOptions: self.openActionOptions, storeMediaPlaybackState: self.actionInteraction?.storeMediaPlaybackState ?? { _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: entry, streamVideos: self.streamVideos, fromPlayingVideo: isCentral && self.fromPlayingVideo, landscape: isCentral && self.landscape, timecode: isCentral ? self.timecode : nil, playbackRate: isCentral ? self.playbackRate : 1.0, displayInfoOnTop: displayInfoOnTop, configuration: self.configuration, performAction: self.performAction, openActionOptions: self.openActionOptions, storeMediaPlaybackState: self.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } @@ -1133,7 +1138,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == strongSelf.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: strongSelf.context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: false, fromPlayingVideo: isCentral && strongSelf.fromPlayingVideo, landscape: isCentral && strongSelf.landscape, timecode: isCentral ? strongSelf.timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: strongSelf.configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: strongSelf.context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: false, fromPlayingVideo: isCentral && strongSelf.fromPlayingVideo, landscape: isCentral && strongSelf.landscape, timecode: isCentral ? strongSelf.timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: strongSelf.configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } @@ -1185,7 +1190,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == strongSelf.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: strongSelf.context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: false, fromPlayingVideo: isCentral && strongSelf.fromPlayingVideo, landscape: isCentral && strongSelf.landscape, timecode: isCentral ? strongSelf.timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: strongSelf.configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: strongSelf.context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: false, fromPlayingVideo: isCentral && strongSelf.fromPlayingVideo, landscape: isCentral && strongSelf.landscape, timecode: isCentral ? strongSelf.timecode : nil, displayInfoOnTop: displayInfoOnTop, configuration: strongSelf.configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } diff --git a/submodules/GalleryUI/Sources/GalleryControllerNode.swift b/submodules/GalleryUI/Sources/GalleryControllerNode.swift index 06780433d2..1ec92c83e3 100644 --- a/submodules/GalleryUI/Sources/GalleryControllerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryControllerNode.swift @@ -22,6 +22,7 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture public var beginCustomDismiss: () -> Void = { } public var completeCustomDismiss: () -> Void = { } public var baseNavigationController: () -> NavigationController? = { return nil } + public var galleryController: () -> ViewController? = { return nil } private var presentationState = GalleryControllerPresentationState() @@ -120,6 +121,9 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture self.pager.baseNavigationController = { [weak self] in return self?.baseNavigationController() } + self.pager.galleryController = { [weak self] in + return self?.galleryController() + } self.addSubnode(self.backgroundNode) diff --git a/submodules/GalleryUI/Sources/GalleryItemNode.swift b/submodules/GalleryUI/Sources/GalleryItemNode.swift index 6903789863..2dc6cf9672 100644 --- a/submodules/GalleryUI/Sources/GalleryItemNode.swift +++ b/submodules/GalleryUI/Sources/GalleryItemNode.swift @@ -27,6 +27,7 @@ open class GalleryItemNode: ASDisplayNode { public var beginCustomDismiss: () -> Void = { } public var completeCustomDismiss: () -> Void = { } public var baseNavigationController: () -> NavigationController? = { return nil } + public var galleryController: () -> ViewController? = { return nil } public var alternativeDismiss: () -> Bool = { return false } override public init() { diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index b6d9e6b6fa..80217fe39e 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -112,6 +112,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest public var beginCustomDismiss: () -> Void = { } public var completeCustomDismiss: () -> Void = { } public var baseNavigationController: () -> NavigationController? = { return nil } + public var galleryController: () -> ViewController? = { return nil } public init(pageGap: CGFloat, disableTapNavigation: Bool) { self.pageGap = pageGap @@ -480,6 +481,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest node.beginCustomDismiss = self.beginCustomDismiss node.completeCustomDismiss = self.completeCustomDismiss node.baseNavigationController = self.baseNavigationController + node.galleryController = self.galleryController node.index = index return node } diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 217fbbd6ee..cbb6aa948a 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -15,6 +15,11 @@ import PresentationDataUtils import OverlayStatusController import StickerPackPreviewUI import AppBundle +import AnimationUI +import ContextUI +import SaveToCameraRoll +import UndoUI +import TelegramUIPreferences public enum UniversalVideoGalleryItemContentInfo { case message(Message) @@ -37,16 +42,18 @@ public class UniversalVideoGalleryItem: GalleryItem { let displayInfoOnTop: Bool let hideControls: Bool let fromPlayingVideo: Bool + let isSecret: Bool let landscape: Bool let timecode: Double? + let playbackRate: Double let configuration: GalleryConfiguration? let playbackCompleted: () -> Void let performAction: (GalleryControllerInteractionTapAction) -> Void let openActionOptions: (GalleryControllerInteractionTapAction) -> Void - let storeMediaPlaybackState: (MessageId, Double?) -> Void + let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void let present: (ViewController, Any?) -> Void - public init(context: AccountContext, presentationData: PresentationData, content: UniversalVideoContent, originData: GalleryItemOriginData?, indexData: GalleryItemIndexData?, contentInfo: UniversalVideoGalleryItemContentInfo?, caption: NSAttributedString, credit: NSAttributedString? = nil, displayInfoOnTop: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, landscape: Bool = false, timecode: Double? = nil, configuration: GalleryConfiguration? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?) -> Void, present: @escaping (ViewController, Any?) -> Void) { + public init(context: AccountContext, presentationData: PresentationData, content: UniversalVideoContent, originData: GalleryItemOriginData?, indexData: GalleryItemIndexData?, contentInfo: UniversalVideoGalleryItemContentInfo?, caption: NSAttributedString, credit: NSAttributedString? = nil, displayInfoOnTop: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, isSecret: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: Double = 1.0, configuration: GalleryConfiguration? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void, present: @escaping (ViewController, Any?) -> Void) { self.context = context self.presentationData = presentationData self.content = content @@ -58,8 +65,10 @@ public class UniversalVideoGalleryItem: GalleryItem { self.displayInfoOnTop = displayInfoOnTop self.hideControls = hideControls self.fromPlayingVideo = fromPlayingVideo + self.isSecret = isSecret self.landscape = landscape self.timecode = timecode + self.playbackRate = playbackRate self.configuration = configuration self.playbackCompleted = playbackCompleted self.performAction = performAction @@ -129,6 +138,8 @@ public class UniversalVideoGalleryItem: GalleryItem { private let pictureInPictureImage = UIImage(bundleImageName: "Media Gallery/PictureInPictureIcon")?.precomposed() private let pictureInPictureButtonImage = generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/PictureInPictureButton"), color: .white) +private let moreButtonImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/More"), color: .white) + private let placeholderFont = Font.regular(16.0) private final class UniversalVideoGalleryItemPictureInPictureNode: ASDisplayNode { @@ -251,6 +262,196 @@ private struct FetchControls { let cancel: () -> Void } +func optionsBackgroundImage(dark: Bool) -> UIImage? { + return generateImage(CGSize(width: 28.0, height: 28.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + context.setFillColor(UIColor(rgb: dark ? 0x1c1c1e : 0x2c2c2e).cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) + })?.stretchableImage(withLeftCapWidth: 14, topCapHeight: 14) +} + +private func optionsCircleImage(dark: Bool) -> UIImage? { + return generateImage(CGSize(width: 22.0, height: 22.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + context.setStrokeColor(UIColor.white.cgColor) + let lineWidth: CGFloat = 1.3 + context.setLineWidth(lineWidth) + + context.strokeEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth, dy: lineWidth)) + }) +} + +private func optionsRateImage(rate: String, isLarge: Bool, color: UIColor = .white) -> UIImage? { + return generateImage(isLarge ? CGSize(width: 30.0, height: 30.0) : CGSize(width: 24.0, height: 24.0), rotatedContext: { size, context in + UIGraphicsPushContext(context) + + context.clear(CGRect(origin: CGPoint(), size: size)) + + if let image = generateTintedImage(image: UIImage(bundleImageName: isLarge ? "Chat/Context Menu/Playspeed30" : "Chat/Context Menu/Playspeed24"), color: .white) { + image.draw(at: CGPoint(x: 0.0, y: 0.0)) + } + + let string = NSMutableAttributedString(string: rate, font: Font.with(size: isLarge ? 11.0 : 10.0, design: .round, weight: .semibold), textColor: color) + + var offset = CGPoint(x: 1.0, y: 0.0) + if rate.count >= 3 { + if rate == "0.5x" { + string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string)) + offset.x += -0.5 + } else { + string.addAttribute(.kern, value: -0.5 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string)) + offset.x += -0.3 + } + } else { + offset.x += -0.3 + } + + if !isLarge { + offset.x *= 0.5 + offset.y *= 0.5 + } + + let boundingRect = string.boundingRect(with: size, options: [], context: nil) + string.draw(at: CGPoint(x: offset.x + floor((size.width - boundingRect.width) / 2.0), y: offset.y + floor((size.height - boundingRect.height) / 2.0))) + + UIGraphicsPopContext() + }) +} + +private final class MoreHeaderButton: HighlightableButtonNode { + enum Content { + case image(UIImage?) + case more(UIImage?) + } + + let referenceNode: ContextReferenceContentNode + let containerNode: ContextControllerSourceNode + private let iconNode: ASImageNode + private var animationNode: AnimationNode? + + var contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? + + private let wide: Bool + + init(wide: Bool = false) { + self.wide = wide + + self.referenceNode = ContextReferenceContentNode() + self.containerNode = ContextControllerSourceNode() + self.containerNode.animateScale = false + self.iconNode = ASImageNode() + self.iconNode.displaysAsynchronously = false + self.iconNode.displayWithoutProcessing = true + self.iconNode.contentMode = .scaleToFill + + super.init() + + self.containerNode.addSubnode(self.referenceNode) + self.referenceNode.addSubnode(self.iconNode) + self.addSubnode(self.containerNode) + + self.containerNode.shouldBegin = { [weak self] location in + guard let strongSelf = self, let _ = strongSelf.contextAction else { + return false + } + return true + } + self.containerNode.activated = { [weak self] gesture, _ in + guard let strongSelf = self else { + return + } + strongSelf.contextAction?(strongSelf.containerNode, gesture) + } + + self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: wide ? 32.0 : 22.0, height: 22.0)) + self.referenceNode.frame = self.containerNode.bounds + + self.iconNode.image = optionsCircleImage(dark: false) + if let image = self.iconNode.image { + self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size) + } + } + + private var content: Content? + func setContent(_ content: Content, animated: Bool = false) { + if case .more = content, self.animationNode == nil { + let iconColor = UIColor(rgb: 0xffffff) + let animationNode = AnimationNode(animation: "anim_profilemore", colors: ["Point 2.Group 1.Fill 1": iconColor, + "Point 3.Group 1.Fill 1": iconColor, + "Point 1.Group 1.Fill 1": iconColor], scale: 1.0) + animationNode.frame = self.containerNode.bounds + self.addSubnode(animationNode) + self.animationNode = animationNode + } + if animated { + if let snapshotView = self.referenceNode.view.snapshotContentTree() { + snapshotView.frame = self.referenceNode.frame + self.view.addSubview(snapshotView) + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + snapshotView.layer.animateScale(from: 1.0, to: 0.1, duration: 0.3, removeOnCompletion: false) + + self.iconNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) + self.iconNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.3) + + self.animationNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) + self.animationNode?.layer.animateScale(from: 0.1, to: 1.0, duration: 0.3) + } + + switch content { + case let .image(image): + if let image = image { + self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size) + } + + self.iconNode.image = image + self.iconNode.isHidden = false + self.animationNode?.isHidden = true + case let .more(image): + if let image = image { + self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size) + } + + self.iconNode.image = image + self.iconNode.isHidden = false + self.animationNode?.isHidden = false + } + } else { + self.content = content + switch content { + case let .image(image): + self.iconNode.image = image + self.iconNode.isHidden = false + self.animationNode?.isHidden = true + case let .more(image): + self.iconNode.image = image + self.iconNode.isHidden = false + self.animationNode?.isHidden = false + } + } + } + + override func didLoad() { + super.didLoad() + self.view.isOpaque = false + } + + override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { + return CGSize(width: wide ? 32.0 : 22.0, height: 22.0) + } + + func onLayout() { + } + + func play() { + self.animationNode?.playOnce() + } +} + final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private let context: AccountContext private let presentationData: PresentationData @@ -264,6 +465,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private let scrubberView: ChatVideoGalleryItemScrubberView private let footerContentNode: ChatItemGalleryFooterContentNode private let overlayContentNode: UniversalVideoGalleryItemOverlayNode + + private let moreBarButton: MoreHeaderButton + private var moreBarButtonRate: Double = 1.0 + private var moreBarButtonRateTimestamp: Double? private var videoNode: UniversalVideoNode? private var videoNodeUserInteractionEnabled: Bool = false @@ -292,6 +497,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private var item: UniversalVideoGalleryItem? private let statusDisposable = MetaDisposable() + private let moreButtonStateDisposable = MetaDisposable() private let mediaPlaybackStateDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() @@ -305,6 +511,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private let isPlayingPromise = ValuePromise(false, ignoreRepeated: true) private let isInteractingPromise = ValuePromise(false, ignoreRepeated: true) private let controlsVisiblePromise = ValuePromise(true, ignoreRepeated: true) + private let isShowingContextMenuPromise = ValuePromise(false, ignoreRepeated: true) private var hideControlsDisposable: Disposable? var playbackCompleted: (() -> Void)? @@ -328,8 +535,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.statusNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 50.0, height: 50.0)) self._title.set(.single("")) + + self.moreBarButton = MoreHeaderButton() + self.moreBarButton.isUserInteractionEnabled = true + self.moreBarButton.setContent(.more(optionsCircleImage(dark: false))) super.init() + + self.moreBarButton.addTarget(self, action: #selector(self.moreButtonPressed), forControlEvents: .touchUpInside) self.footerContentNode.interacting = { [weak self] value in self?.isInteractingPromise.set(value) @@ -426,6 +639,19 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { break } } + + self.footerContentNode.toggleFullscreen = { [weak self] in + guard let strongSelf = self else { + return + } + var toLandscape = false + let size = strongSelf.bounds.size + if size.width < size.height { + toLandscape = true + } + strongSelf.updateControlsVisibility(!toLandscape) + strongSelf.updateOrientation(toLandscape ? .landscapeRight : .portrait) + } self.scrubbingFrameDisposable = (self.scrubbingFrame.get() |> deliverOnMainQueue).start(next: { [weak self] result in @@ -451,12 +677,19 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { strongSelf.pictureInPictureButtonPressed() return true } + + self.moreBarButton.contextAction = { [weak self] sourceNode, gesture in + self?.openMoreMenu(sourceNode: sourceNode, gesture: gesture) + } self.titleContentView = GalleryTitleView(frame: CGRect()) self._titleView.set(.single(self.titleContentView)) - let shouldHideControlsSignal: Signal = combineLatest(self.isPlayingPromise.get(), self.isInteractingPromise.get(), self.controlsVisiblePromise.get()) - |> mapToSignal { isPlaying, isIntracting, controlsVisible -> Signal in + let shouldHideControlsSignal: Signal = combineLatest(self.isPlayingPromise.get(), self.isInteractingPromise.get(), self.controlsVisiblePromise.get(), self.isShowingContextMenuPromise.get()) + |> mapToSignal { isPlaying, isIntracting, controlsVisible, isShowingContextMenu -> Signal in + if isShowingContextMenu { + return .complete() + } if isPlaying && !isIntracting && controlsVisible { return .single(Void()) |> delay(4.0, queue: Queue.mainQueue()) @@ -475,6 +708,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { deinit { self.statusDisposable.dispose() + self.moreButtonStateDisposable.dispose() self.mediaPlaybackStateDisposable.dispose() self.scrubbingFrameDisposable?.dispose() self.hideControlsDisposable?.dispose() @@ -644,7 +878,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if status.timestamp > 5.0 && status.timestamp < status.duration - 5.0 { timestamp = status.timestamp } - item.storeMediaPlaybackState(message.id, timestamp) + item.storeMediaPlaybackState(message.id, timestamp, status.baseRate) } })) } @@ -685,6 +919,56 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } + self.moreButtonStateDisposable.set(combineLatest(queue: .mainQueue(), + videoNode.status, + self.isShowingContextMenuPromise.get() + ).start(next: { [weak self] status, isShowingContextMenu in + guard let strongSelf = self else { + return + } + guard let status = status else { + return + } + + let effectiveBaseRate: Double + if isShowingContextMenu { + effectiveBaseRate = 1.0 + } else { + effectiveBaseRate = status.baseRate + } + + if abs(effectiveBaseRate - strongSelf.moreBarButtonRate) > 0.01 { + strongSelf.moreBarButtonRate = effectiveBaseRate + let animated: Bool + if let moreBarButtonRateTimestamp = strongSelf.moreBarButtonRateTimestamp { + animated = CFAbsoluteTimeGetCurrent() > (moreBarButtonRateTimestamp + 0.2) + } else { + animated = false + } + strongSelf.moreBarButtonRateTimestamp = CFAbsoluteTimeGetCurrent() + + if abs(effectiveBaseRate - 1.0) > 0.01 { + let rateString: String + if abs(effectiveBaseRate - 0.5) < 0.01 { + rateString = "0.5x" + } else if abs(effectiveBaseRate - 1.5) < 0.01 { + rateString = "1.5x" + } else if abs(effectiveBaseRate - 2.0) < 0.01 { + rateString = "2x" + } else { + rateString = "x" + } + strongSelf.moreBarButton.setContent(.image(optionsRateImage(rate: rateString, isLarge: true)), animated: animated) + } else { + strongSelf.moreBarButton.setContent(.more(optionsCircleImage(dark: false)), animated: animated) + } + } else { + if strongSelf.moreBarButtonRateTimestamp == nil { + strongSelf.moreBarButtonRateTimestamp = CFAbsoluteTimeGetCurrent() + } + } + })) + self.statusDisposable.set((combineLatest(queue: .mainQueue(), videoNode.status, mediaFileStatus) |> deliverOnMainQueue).start(next: { [weak self] value, fetchStatus in if let strongSelf = self { @@ -823,6 +1107,27 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else { self.hasPictureInPicture = false } + + if let contentInfo = item.contentInfo, case let .message(message) = contentInfo { + var file: TelegramMediaFile? + var isWebpage = false + for m in message.media { + if let m = m as? TelegramMediaFile, m.isVideo { + file = m + break + } else if let m = m as? TelegramMediaWebpage, case let .Loaded(content) = m.content, let f = content.file, f.isVideo { + file = f + isWebpage = true + break + } + } + + if !isWebpage, let file = file, !file.isAnimated { + let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)! + barButtonItems.append(moreMenuItem) + } + } + self._rightBarButtonItems.set(.single(barButtonItems)) videoNode.playbackCompleted = { [weak self, weak videoNode] in @@ -999,18 +1304,21 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { var isAnimated = false var seek = MediaPlayerSeek.start + var playbackRate: Double = 1.0 if let item = self.item { if let content = item.content as? NativeVideoContent { isAnimated = content.fileReference.media.isAnimated if let time = item.timecode { seek = .timecode(time) } + playbackRate = item.playbackRate } else if let _ = item.content as? WebEmbedVideoContent { if let time = item.timecode { seek = .timecode(time) } } } + videoNode.setBaseRate(playbackRate) if isAnimated { videoNode.seek(0.0) videoNode.play() @@ -1024,7 +1332,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private var actionAtEnd: MediaPlayerPlayOnceWithSoundActionAtEnd { if let item = self.item { - if let content = item.content as? NativeVideoContent, content.duration <= 30 { + if !item.isSecret, let content = item.content as? NativeVideoContent, content.duration <= 30 { return .loop } } @@ -1613,7 +1921,208 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } } } - + + private func contentInfo() -> (message: Message, file: TelegramMediaFile, isWebpage: Bool)? { + guard let item = self.item else { + return nil + } + if let contentInfo = item.contentInfo, case let .message(message) = contentInfo { + var file: TelegramMediaFile? + var isWebpage = false + for m in message.media { + if let m = m as? TelegramMediaFile, m.isVideo { + file = m + break + } else if let m = m as? TelegramMediaWebpage, case let .Loaded(content) = m.content, let f = content.file, f.isVideo { + file = f + isWebpage = true + break + } + } + + if let file = file { + return (message, file, isWebpage) + } + } + return nil + } + + private func canDelete() -> Bool { + guard let (message, _, _) = self.contentInfo() else { + return false + } + + var canDelete = false + if let peer = message.peers[message.id.peerId] { + if peer is TelegramUser || peer is TelegramSecretChat { + canDelete = true + } else if let _ = peer as? TelegramGroup { + canDelete = true + } else if let channel = peer as? TelegramChannel { + if message.flags.contains(.Incoming) { + canDelete = channel.hasPermission(.deleteAllMessages) + } else { + canDelete = true + } + } else { + canDelete = false + } + } else { + canDelete = false + } + return canDelete + } + + @objc private func moreButtonPressed() { + self.moreBarButton.play() + self.moreBarButton.contextAction?(self.moreBarButton.containerNode, nil) + } + + private func openMoreMenu(sourceNode: ASDisplayNode, gesture: ContextGesture?) { + let items: Signal<[ContextMenuItem], NoError> = self.contextMenuMainItems() + guard let controller = self.baseNavigationController()?.topViewController as? ViewController else { + return + } + + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme), source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.moreBarButton.referenceNode)), items: items, reactionItems: [], gesture: gesture) + self.isShowingContextMenuPromise.set(true) + controller.presentInGlobalOverlay(contextController) + + contextController.dismissed = { [weak self] in + Queue.mainQueue().after(0.1, { + self?.isShowingContextMenuPromise.set(false) + }) + } + } + + private func speedList() -> [(String, String, Double)] { + let speedList: [(String, String, Double)] = [ + ("0.5x", "0.5x", 0.5), + ("Normal", "1x", 1.0), + ("1.5x", "1.5x", 1.5), + ("2x", "2x", 2.0) + ] + + return speedList + } + + private func contextMenuMainItems() -> Signal<[ContextMenuItem], NoError> { + guard let videoNode = self.videoNode else { + return .single([]) + } + + return videoNode.status + |> take(1) + |> deliverOnMainQueue + |> map { [weak self] status -> [ContextMenuItem] in + guard let status = status, let strongSelf = self else { + return [] + } + + var items: [ContextMenuItem] = [] + + var speedValue: String = "Normal" + var speedIconText: String = "1x" + for (text, iconText, speed) in strongSelf.speedList() { + if abs(speed - status.baseRate) < 0.01 { + speedValue = text + speedIconText = iconText + break + } + } + + items.append(.action(ContextMenuActionItem(text: "Playback Speed", textLayout: .secondLineWithValue(speedValue), icon: { theme in + return optionsRateImage(rate: speedIconText, isLarge: false, color: theme.contextMenu.primaryColor) + }, action: { c, _ in + guard let strongSelf = self else { + c.dismiss(completion: nil) + return + } + + c.setItems(strongSelf.contextMenuSpeedItems()) + }))) + if let (message, file, isWebpage) = strongSelf.contentInfo(), !isWebpage { + items.append(.action(ContextMenuActionItem(text: "Save to Gallery", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Download"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in + f(.default) + + if let strongSelf = self { + let _ = (SaveToCameraRoll.saveToCameraRoll(context: strongSelf.context, postbox: strongSelf.context.account.postbox, mediaReference: .message(message: MessageReference(message), media: file)) + |> deliverOnMainQueue).start(completed: { + guard let strongSelf = self else { + return + } + guard let controller = strongSelf.galleryController() else { + return + } + //TODO:localize + controller.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .mediaSaved(text: "Video Saved"), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) + }) + } + }))) + } + if strongSelf.canDelete() { + items.append(.action(ContextMenuActionItem(text: "Delete", textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in + f(.default) + + if let strongSelf = self { + strongSelf.footerContentNode.deleteButtonPressed() + } + }))) + } + + return items + } + } + + private func contextMenuSpeedItems() -> Signal<[ContextMenuItem], NoError> { + guard let videoNode = self.videoNode else { + return .single([]) + } + + return videoNode.status + |> take(1) + |> deliverOnMainQueue + |> map { [weak self] status -> [ContextMenuItem] in + guard let status = status, let strongSelf = self else { + return [] + } + + var items: [ContextMenuItem] = [] + + for (text, _, rate) in strongSelf.speedList() { + let isSelected = abs(status.baseRate - rate) < 0.01 + items.append(.action(ContextMenuActionItem(text: text, icon: { theme in + if isSelected { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } else { + return nil + } + }, action: { _, f in + f(.default) + + guard let strongSelf = self, let videoNode = strongSelf.videoNode else { + return + } + + videoNode.setBaseRate(rate) + }))) + } + + items.append(.separator) + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Back, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) + }, action: { c, _ in + guard let strongSelf = self else { + c.dismiss(completion: nil) + return + } + c.setItems(strongSelf.contextMenuMainItems()) + }))) + + return items + } + } + @objc func openStickersButtonPressed() { if let content = self.item?.content as? NativeVideoContent { let media = content.fileReference.abstract @@ -1665,6 +2174,20 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } override func footerContent() -> Signal<(GalleryFooterContentNode?, GalleryOverlayContentNode?), NoError> { - return .single((self.footerContentNode, self.overlayContentNode)) + return .single((self.footerContentNode, nil)) + } +} + +private final class HeaderContextReferenceContentSource: ContextReferenceContentSource { + private let controller: ViewController + private let sourceNode: ContextReferenceContentNode + + init(controller: ViewController, sourceNode: ContextReferenceContentNode) { + self.controller = controller + self.sourceNode = sourceNode + } + + func transitionInfo() -> ContextControllerReferenceViewInfo? { + return ContextControllerReferenceViewInfo(referenceNode: self.sourceNode, contentAreaInScreenSpace: UIScreen.main.bounds) } } diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index ba498852d8..2c13ac340f 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -438,7 +438,7 @@ public final class SecretMediaPreviewController: ViewController { } } - guard let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: MessageHistoryEntry(message: message, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)), streamVideos: false, hideControls: true, tempFilePath: tempFilePath, playbackCompleted: { [weak self] in + guard let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: MessageHistoryEntry(message: message, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)), streamVideos: false, hideControls: true, isSecret: true, tempFilePath: tempFilePath, playbackCompleted: { [weak self] in self?.dismiss(forceAway: false) }, present: { _, _ in }) else { self._ready.set(.single(true)) diff --git a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift index fa8909089b..a0732db93e 100644 --- a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift +++ b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift @@ -113,7 +113,7 @@ public struct InstantPageGalleryEntry: Equatable { nativeId = .instantPage(self.pageId, file.fileId) } - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: NativeVideoContent(id: nativeId, fileReference: .webPage(webPage: WebpageReference(webPage), media: file), streamVideo: isMediaStreamable(media: file) ? .conservative : .none), originData: nil, indexData: indexData, contentInfo: .webPage(webPage, file, nil), caption: caption, credit: credit, fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in }) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: NativeVideoContent(id: nativeId, fileReference: .webPage(webPage: WebpageReference(webPage), media: file), streamVideo: isMediaStreamable(media: file) ? .conservative : .none), originData: nil, indexData: indexData, contentInfo: .webPage(webPage, file, nil), caption: caption, credit: credit, fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _, _ in }, present: { _, _ in }) } else { var representations: [TelegramMediaImageRepresentation] = [] representations.append(contentsOf: file.previewRepresentations) @@ -135,12 +135,12 @@ public struct InstantPageGalleryEntry: Equatable { present(gallery, InstantPageGalleryControllerPresentationArguments(transitionArguments: { entry -> GalleryTransitionArguments? in return makeArguments() })) - }), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in }) + }), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _, _ in }, present: { _, _ in }) } else { if let content = WebEmbedVideoContent(webPage: embedWebpage, webpageContent: webpageContent, openUrl: { url in }) { - return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage, nil), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _ in }, present: { _, _ in }) + return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: nil, indexData: nil, contentInfo: .webPage(webPage, embedWebpage, nil), caption: NSAttributedString(string: ""), fromPlayingVideo: fromPlayingVideo, landscape: landscape, performAction: { _ in }, openActionOptions: { _ in }, storeMediaPlaybackState: { _, _, _ in }, present: { _, _ in }) } else { preconditionFailure() } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift index 08e410893a..2502a6a12c 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift @@ -387,7 +387,7 @@ public func inviteLinkEditController(context: AccountContext, peerId: PeerId, in dismissAction() dismissImpl?() - let _ = (revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) + let _ = (context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: invite.link) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) |> deliverOnMainQueue).start(next: { invite in switch invite { @@ -444,7 +444,7 @@ public func inviteLinkEditController(context: AccountContext, peerId: PeerId, in let usageLimit = state.usage.value if invite == nil { - let _ = (createPeerExportedInvitation(account: context.account, peerId: peerId, expireDate: expireDate, usageLimit: usageLimit) + let _ = (context.engine.peers.createPeerExportedInvitation(peerId: peerId, expireDate: expireDate, usageLimit: usageLimit) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) |> deliverOnMainQueue).start(next: { invite in completion?(invite) @@ -458,7 +458,7 @@ public func inviteLinkEditController(context: AccountContext, peerId: PeerId, in presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) }) } else if let invite = invite { - let _ = (editPeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link, expireDate: expireDate, usageLimit: usageLimit) + let _ = (context.engine.peers.editPeerExportedInvitation(peerId: peerId, link: invite.link, expireDate: expireDate, usageLimit: usageLimit) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) |> deliverOnMainQueue).start(next: { invite in completion?(invite) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift index 68d2764e4b..02985f64fe 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift @@ -285,7 +285,7 @@ public final class InviteLinkInviteController: ViewController { self.presentationDataPromise = Promise(self.presentationData) self.controller = controller - self.invitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: nil, revoked: false, forceUpdate: false) + self.invitesContext = context.engine.peers.peerExportedInvitations(peerId: peerId, adminId: nil, revoked: false, forceUpdate: false) self.dimNode = ASDisplayNode() self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5) @@ -396,7 +396,7 @@ public final class InviteLinkInviteController: ViewController { dismissAction() if let invite = invite { - let _ = (revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in + let _ = (context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in if let result = result, case let .replace(_, invite) = result { mainInvitePromise.set(invite) } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift index 9314f186b7..973d154cd1 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift @@ -418,12 +418,12 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad var getControllerImpl: (() -> ViewController?)? let adminId = admin?.peer.peer?.id - let invitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: false, forceUpdate: true) - let revokedInvitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: adminId, revoked: true, forceUpdate: true) + let invitesContext = context.engine.peers.peerExportedInvitations(peerId: peerId, adminId: adminId, revoked: false, forceUpdate: true) + let revokedInvitesContext = context.engine.peers.peerExportedInvitations(peerId: peerId, adminId: adminId, revoked: true, forceUpdate: true) let creators: Signal<[ExportedInvitationCreator], NoError> if adminId == nil { - creators = .single([]) |> then(peerExportedInvitationsCreators(account: context.account, peerId: peerId)) + creators = .single([]) |> then(context.engine.peers.peerExportedInvitationsCreators(peerId: peerId)) } else { creators = .single([]) } @@ -520,7 +520,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad } } if revoke { - revokeLinkDisposable.set((revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in + revokeLinkDisposable.set((context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in updateState { state in var updatedState = state updatedState.revokingPrivateLink = false @@ -661,7 +661,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad ActionSheetButtonItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Action, color: .destructive, action: { dismissAction() - revokeLinkDisposable.set((deletePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: { + revokeLinkDisposable.set((context.engine.peers.deletePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: { })) revokedInvitesContext.remove(invite) @@ -695,7 +695,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad ActionSheetButtonItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeLink, color: .destructive, action: { dismissAction() - revokeLinkDisposable.set((revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in + revokeLinkDisposable.set((context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in if case let .replace(_, newInvite) = result { invitesContext.add(newInvite) } @@ -732,7 +732,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad ActionSheetButtonItem(title: presentationData.strings.InviteLink_DeleteAllRevokedLinksAlert_Action, color: .destructive, action: { dismissAction() - deleteAllRevokedLinksDisposable.set((deleteAllRevokedPeerExportedInvitations(account: context.account, peerId: peerId, adminId: adminId ?? context.account.peerId) |> deliverOnMainQueue).start(completed: { + deleteAllRevokedLinksDisposable.set((context.engine.peers.deleteAllRevokedPeerExportedInvitations(peerId: peerId, adminId: adminId ?? context.account.peerId) |> deliverOnMainQueue).start(completed: { })) revokedInvitesContext.clear() @@ -770,7 +770,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId, ad |> distinctUntilChanged |> deliverOnMainQueue |> map { invite -> PeerInvitationImportersContext? in - return invite.flatMap { PeerInvitationImportersContext(account: context.account, peerId: peerId, invite: $0) } + return invite.flatMap { context.engine.peers.peerInvitationImporters(peerId: peerId, invite: $0) } } |> afterNext { context in if let context = context { importersState.set(context.state |> map(Optional.init)) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index 9b75fc2fc0..db9cef882d 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -374,7 +374,7 @@ public final class InviteLinkViewController: ViewController { self.presentationDataPromise = Promise(self.presentationData) self.controller = controller - self.importersContext = importersContext ?? PeerInvitationImportersContext(account: context.account, peerId: peerId, invite: invite) + self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, invite: invite) self.dimNode = ASDisplayNode() self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5) @@ -483,7 +483,7 @@ public final class InviteLinkViewController: ViewController { dismissAction() self?.controller?.dismiss() - let _ = (deletePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: { + let _ = (context.engine.peers.deletePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: { }) self?.controller?.revokedInvitationsContext?.remove(invite) @@ -537,7 +537,7 @@ public final class InviteLinkViewController: ViewController { dismissAction() self?.controller?.dismiss() - let _ = (revokePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in + let _ = (context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(next: { result in if case let .replace(_, newInvite) = result { self?.controller?.invitationsContext?.add(newInvite) } diff --git a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewController.swift b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewController.swift index e44ea25125..d7cbb6817b 100644 --- a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewController.swift +++ b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewController.swift @@ -70,7 +70,7 @@ public final class JoinLinkPreviewController: ViewController { if let resolvedState = self.resolvedState { signal = .single(resolvedState) } else { - signal = joinLinkInformation(self.link, account: self.context.account) + signal = self.context.engine.peers.joinLinkInformation(self.link) } self.disposable.set((signal @@ -121,7 +121,7 @@ public final class JoinLinkPreviewController: ViewController { } private func join() { - self.disposable.set((joinChatInteractively(with: self.link, account: self.context.account) |> deliverOnMainQueue).start(next: { [weak self] peerId in + self.disposable.set((self.context.engine.peers.joinChatInteractively(with: self.link) |> deliverOnMainQueue).start(next: { [weak self] peerId in if let strongSelf = self { if let peerId = peerId { strongSelf.navigateToPeer(peerId, nil) diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyLiveUploadInterface.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyLiveUploadInterface.swift index 59af73ea1a..dd9295eceb 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyLiveUploadInterface.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyLiveUploadInterface.swift @@ -5,6 +5,7 @@ import TelegramCore import SyncCore import LegacyComponents import SwiftSignalKit +import AccountContext public class VideoConversionWatcher: TGMediaVideoFileWatcher { private let update: (String, Int) -> Void @@ -44,7 +45,7 @@ public final class LegacyLiveUploadInterfaceResult: NSObject { } public final class LegacyLiveUploadInterface: VideoConversionWatcher, TGLiveUploadInterface { - private let account: Account + private let context: AccountContext private let id: Int64 private var path: String? private var size: Int? @@ -52,8 +53,8 @@ public final class LegacyLiveUploadInterface: VideoConversionWatcher, TGLiveUplo private let data = Promise() private let dataValue = Atomic(value: nil) - public init(account: Account) { - self.account = account + public init(context: AccountContext) { + self.context = context self.id = Int64.random(in: Int64.min ... Int64.max) var updateImpl: ((String, Int) -> Void)? @@ -65,7 +66,7 @@ public final class LegacyLiveUploadInterface: VideoConversionWatcher, TGLiveUplo if let strongSelf = self { if strongSelf.path == nil { strongSelf.path = path - strongSelf.account.messageMediaPreuploadManager.add(network: strongSelf.account.network, postbox: strongSelf.account.postbox, id: strongSelf.id, encrypt: false, tag: nil, source: strongSelf.data.get()) + strongSelf.context.engine.resources.preUpload(id: strongSelf.id, encrypt: false, tag: nil, source: strongSelf.data.get()) } strongSelf.size = size diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift b/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift index 22386c4bd0..0f247d9fd5 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacySuggestionContext.swift @@ -46,7 +46,7 @@ public func legacySuggestionContext(context: AccountContext, peerId: PeerId, cha } suggestionContext.hashtagListSignal = { query in return SSignal { subscriber in - let disposable = (recentlyUsedHashtags(postbox: context.account.postbox) |> map { hashtags -> [String] in + let disposable = (context.engine.messages.recentlyUsedHashtags() |> map { hashtags -> [String] in let normalizedQuery = query?.lowercased() var result: [String] = [] if let normalizedQuery = normalizedQuery { diff --git a/submodules/LiveLocationManager/Sources/LiveLocationManager.swift b/submodules/LiveLocationManager/Sources/LiveLocationManager.swift index d407c26456..14e1fa6448 100644 --- a/submodules/LiveLocationManager/Sources/LiveLocationManager.swift +++ b/submodules/LiveLocationManager/Sources/LiveLocationManager.swift @@ -44,11 +44,11 @@ public final class LiveLocationManagerImpl: LiveLocationManager { private var invalidationTimer: (SwiftSignalKit.Timer, Int32)? - public init(account: Account, locationManager: DeviceLocationManager, inForeground: Signal) { + public init(engine: TelegramEngine, account: Account, locationManager: DeviceLocationManager, inForeground: Signal) { self.account = account self.locationManager = locationManager - self.summaryManagerImpl = LiveLocationSummaryManagerImpl(queue: self.queue, postbox: account.postbox, accountPeerId: account.peerId, viewTracker: account.viewTracker) + self.summaryManagerImpl = LiveLocationSummaryManagerImpl(queue: self.queue, engine: engine, postbox: account.postbox, accountPeerId: account.peerId, viewTracker: account.viewTracker) let viewKey: PostboxViewKey = .localMessageTag(.OutgoingLiveLocation) self.messagesDisposable = (account.postbox.combinedView(keys: [viewKey]) diff --git a/submodules/LiveLocationManager/Sources/LiveLocationSummaryManager.swift b/submodules/LiveLocationManager/Sources/LiveLocationSummaryManager.swift index 93440b5d88..db91916199 100644 --- a/submodules/LiveLocationManager/Sources/LiveLocationSummaryManager.swift +++ b/submodules/LiveLocationManager/Sources/LiveLocationSummaryManager.swift @@ -79,6 +79,7 @@ private final class LiveLocationSummaryContext { private final class LiveLocationPeerSummaryContext { private let queue: Queue + private let engine: TelegramEngine private let accountPeerId: PeerId private let viewTracker: AccountViewTracker private let peerId: PeerId @@ -116,8 +117,9 @@ private final class LiveLocationPeerSummaryContext { private let peerDisposable = MetaDisposable() - init(queue: Queue, accountPeerId: PeerId, viewTracker: AccountViewTracker, peerId: PeerId, becameEmpty: @escaping () -> Void) { + init(queue: Queue, engine: TelegramEngine, accountPeerId: PeerId, viewTracker: AccountViewTracker, peerId: PeerId, becameEmpty: @escaping () -> Void) { self.queue = queue + self.engine = engine self.accountPeerId = accountPeerId self.viewTracker = viewTracker self.peerId = peerId @@ -160,7 +162,7 @@ private final class LiveLocationPeerSummaryContext { private func updateSubscription() { if self.isActive || !self.subscribers.isEmpty { - self.peerDisposable.set((topPeerActiveLiveLocationMessages(viewTracker: self.viewTracker, accountPeerId: self.accountPeerId, peerId: self.peerId) + self.peerDisposable.set((self.engine.messages.topPeerActiveLiveLocationMessages(peerId: self.peerId) |> deliverOn(self.queue)).start(next: { [weak self] accountPeer, messages in if let strongSelf = self { var peersAndMessages: [(Peer, Message)] = [] @@ -187,6 +189,7 @@ private final class LiveLocationPeerSummaryContext { public final class LiveLocationSummaryManagerImpl: LiveLocationSummaryManager { private let queue: Queue + private let engine: TelegramEngine private let postbox: Postbox private let accountPeerId: PeerId private let viewTracker: AccountViewTracker @@ -194,9 +197,10 @@ public final class LiveLocationSummaryManagerImpl: LiveLocationSummaryManager { private let globalContext: LiveLocationSummaryContext private var peerContexts: [PeerId: LiveLocationPeerSummaryContext] = [:] - init(queue: Queue, postbox: Postbox, accountPeerId: PeerId, viewTracker: AccountViewTracker) { + init(queue: Queue, engine: TelegramEngine, postbox: Postbox, accountPeerId: PeerId, viewTracker: AccountViewTracker) { assert(queue.isCurrent()) self.queue = queue + self.engine = engine self.postbox = postbox self.accountPeerId = accountPeerId self.viewTracker = viewTracker @@ -212,7 +216,7 @@ public final class LiveLocationSummaryManagerImpl: LiveLocationSummaryManager { for peerId in peerIds { if self.peerContexts[peerId] == nil { - let context = LiveLocationPeerSummaryContext(queue: self.queue, accountPeerId: self.accountPeerId, viewTracker: self.viewTracker, peerId: peerId, becameEmpty: { [weak self] in + let context = LiveLocationPeerSummaryContext(queue: self.queue, engine: self.engine, accountPeerId: self.accountPeerId, viewTracker: self.viewTracker, peerId: peerId, becameEmpty: { [weak self] in if let strongSelf = self, let context = strongSelf.peerContexts[peerId], context.isEmpty { strongSelf.peerContexts.removeValue(forKey: peerId) } @@ -242,7 +246,7 @@ public final class LiveLocationSummaryManagerImpl: LiveLocationSummaryManager { if let current = strongSelf.peerContexts[peerId] { context = current } else { - context = LiveLocationPeerSummaryContext(queue: strongSelf.queue, accountPeerId: strongSelf.accountPeerId, viewTracker: strongSelf.viewTracker, peerId: peerId, becameEmpty: { + context = LiveLocationPeerSummaryContext(queue: strongSelf.queue, engine: strongSelf.engine, accountPeerId: strongSelf.accountPeerId, viewTracker: strongSelf.viewTracker, peerId: peerId, becameEmpty: { if let strongSelf = self, let context = strongSelf.peerContexts[peerId], context.isEmpty { strongSelf.peerContexts.removeValue(forKey: peerId) } diff --git a/submodules/LocationUI/Sources/LocationUtils.swift b/submodules/LocationUI/Sources/LocationUtils.swift index 31d343c199..604c803418 100644 --- a/submodules/LocationUI/Sources/LocationUtils.swift +++ b/submodules/LocationUI/Sources/LocationUtils.swift @@ -43,7 +43,7 @@ public func nearbyVenues(context: AccountContext, latitude: Double, longitude: D guard let peerId = peerId else { return .single(nil) } - return requestChatContextResults(account: context.account, botId: peerId, peerId: context.account.peerId, query: query ?? "", location: .single((latitude, longitude)), offset: "") + return context.engine.messages.requestChatContextResults(botId: peerId, peerId: context.account.peerId, query: query ?? "", location: .single((latitude, longitude)), offset: "") |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/LocationUI/Sources/LocationViewControllerNode.swift b/submodules/LocationUI/Sources/LocationViewControllerNode.swift index 0bd8ad9564..179270366f 100644 --- a/submodules/LocationUI/Sources/LocationViewControllerNode.swift +++ b/submodules/LocationUI/Sources/LocationViewControllerNode.swift @@ -279,7 +279,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan } } - let liveLocations = topPeerActiveLiveLocationMessages(viewTracker: context.account.viewTracker, accountPeerId: context.account.peerId, peerId: subject.id.peerId) + let liveLocations = context.engine.messages.topPeerActiveLiveLocationMessages(peerId: subject.id.peerId) |> map { _, messages -> [Message] in return messages } diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h index 761ed3029e..99d24a9b7c 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTMessageService.h @@ -8,6 +8,7 @@ @class MTMessageTransaction; @class MTApiEnvironment; @class MTSessionInfo; +@class MTTransportScheme; @protocol MTMessageService @@ -17,7 +18,7 @@ - (void)mtProtoDidAddService:(MTProto *)mtProto; - (void)mtProtoDidRemoveService:(MTProto *)mtProto; - (void)mtProtoPublicKeysUpdated:(MTProto *)mtProto datacenterId:(NSInteger)datacenterId publicKeys:(NSArray *)publicKeys; -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo; +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme; - (void)mtProtoDidChangeSession:(MTProto *)mtProto; - (void)mtProtoServerDidChangeSession:(MTProto *)mtProto firstValidMessageId:(int64_t)firstValidMessageId otherValidMessageIds:(NSArray *)otherValidMessageIds; - (void)mtProto:(MTProto *)mtProto receivedMessage:(MTIncomingMessage *)message authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector; diff --git a/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m b/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m index 6a9b69723b..96d723d844 100644 --- a/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m +++ b/submodules/MtProtoKit/Sources/MTBindKeyMessageService.m @@ -42,7 +42,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme { if (_currentTransactionId != nil) { return nil; diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m index ac200f686b..271707bf12 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthMessageService.m @@ -207,8 +207,12 @@ typedef enum { } } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme { + if (MTLogEnabled()) { + MTLog(@"[MTDatacenterAuthMessageService#%p mtProto#%p (media: %s) mtProtoMessageTransaction scheme:%@]", self, mtProto, mtProto.media ? "true" : "false", scheme); + } + if (_currentStageTransactionId == nil) { switch (_stage) diff --git a/submodules/MtProtoKit/Sources/MTProto.m b/submodules/MtProtoKit/Sources/MTProto.m index fd0dc1ce8e..2de22dc22d 100644 --- a/submodules/MtProtoKit/Sources/MTProto.m +++ b/submodules/MtProtoKit/Sources/MTProto.m @@ -952,9 +952,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; NSMutableArray *messageServiceTransactions = [[NSMutableArray alloc] init]; for (id messageService in _messageServices) { - if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:authInfoSelector:sessionInfo:)]) + if ([messageService respondsToSelector:@selector(mtProtoMessageTransaction:authInfoSelector:sessionInfo:scheme:)]) { - MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self authInfoSelector:authInfoSelector sessionInfo:transactionSessionInfo]; + MTMessageTransaction *messageTransaction = [messageService mtProtoMessageTransaction:self authInfoSelector:authInfoSelector sessionInfo:transactionSessionInfo scheme:scheme]; if (messageTransaction != nil) { for (MTOutgoingMessage *message in messageTransaction.messagePayload) diff --git a/submodules/MtProtoKit/Sources/MTRequestMessageService.m b/submodules/MtProtoKit/Sources/MTRequestMessageService.m index 0b91e6d40e..ac402c9c84 100644 --- a/submodules/MtProtoKit/Sources/MTRequestMessageService.m +++ b/submodules/MtProtoKit/Sources/MTRequestMessageService.m @@ -405,7 +405,7 @@ return currentData; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme { NSMutableArray *messages = nil; NSMutableDictionary *requestInternalIdToMessageInternalId = nil; diff --git a/submodules/MtProtoKit/Sources/MTResendMessageService.m b/submodules/MtProtoKit/Sources/MTResendMessageService.m index 585ec29599..468e30eec6 100644 --- a/submodules/MtProtoKit/Sources/MTResendMessageService.m +++ b/submodules/MtProtoKit/Sources/MTResendMessageService.m @@ -41,7 +41,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme { if (_currentRequestMessageId == 0 || _currentRequestTransactionId == nil) { diff --git a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m index 8672ed541d..30f1fe2f15 100644 --- a/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m +++ b/submodules/MtProtoKit/Sources/MTTimeSyncMessageService.m @@ -45,7 +45,7 @@ [mtProto requestTransportTransaction]; } -- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo +- (MTMessageTransaction *)mtProtoMessageTransaction:(MTProto *)mtProto authInfoSelector:(MTDatacenterAuthInfoSelector)authInfoSelector sessionInfo:(MTSessionInfo *)sessionInfo scheme:(MTTransportScheme *)scheme { if (_currentTransactionId == nil) { diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index eb88e7475f..89171cffca 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -43,7 +43,7 @@ public func peerInfoProfilePhotos(context: AccountContext, peerId: PeerId) -> Si return .single((true, [])) } } else { - return fetchAndUpdateCachedPeerData(accountPeerId: context.account.peerId, peerId: peerId, network: context.account.network, postbox: context.account.postbox) + return context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peerId) |> map { _ -> (Bool, [AvatarGalleryEntry])? in return nil } @@ -748,7 +748,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr case let .image(_, reference, _, _, _, _, _, _, _, _): if self.peer.id == self.context.account.peerId, let peerReference = PeerReference(self.peer) { if let reference = reference { - let _ = (updatePeerPhotoExisting(network: self.context.account.network, reference: reference) + let _ = (self.context.engine.accountData.updatePeerPhotoExisting(reference: reference) |> deliverOnMainQueue).start(next: { [weak self] photo in if let strongSelf = self, let photo = photo, let firstEntry = strongSelf.entries.first, case let .image(image) = firstEntry { let updatedEntry = AvatarGalleryEntry.image(photo.imageId, photo.reference, photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), strongSelf.peer, image.5, image.6, image.7, photo.immediateThumbnailData, image.9) @@ -860,7 +860,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr if self.peer.id == self.context.account.peerId { } else { if entry == self.entries.first { - let _ = updatePeerPhoto(postbox: self.context.account.postbox, network: self.context.account.network, stateManager: self.context.account.stateManager, accountPeerId: self.context.account.peerId, peerId: self.peer.id, photo: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() + let _ = self.context.engine.peers.updatePeerPhoto(peerId: self.peer.id, photo: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() dismiss = true } else { if let index = self.entries.firstIndex(of: entry) { @@ -872,7 +872,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr case let .image(_, reference, _, _, _, _, _, messageId, _, _): if self.peer.id == self.context.account.peerId { if let reference = reference { - let _ = removeAccountPhoto(network: self.context.account.network, reference: reference).start() + let _ = self.context.engine.accountData.removeAccountPhoto(reference: reference).start() } if entry == self.entries.first { dismiss = true @@ -889,7 +889,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr } if entry == self.entries.first { - let _ = updatePeerPhoto(postbox: self.context.account.postbox, network: self.context.account.network, stateManager: self.context.account.stateManager, accountPeerId: self.context.account.peerId, peerId: self.peer.id, photo: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() + let _ = self.context.engine.peers.updatePeerPhoto(peerId: self.peer.id, photo: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() dismiss = true } else { if let index = self.entries.firstIndex(of: entry) { diff --git a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift index 85b62dcaf9..ce61260895 100644 --- a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift @@ -738,7 +738,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi updateState { $0.withUpdatedUpdatingAvatar(.image(representation, true)) } - updateAvatarDisposable.set((updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in + updateAvatarDisposable.set((context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: resource), mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }) |> deliverOnMainQueue).start(next: { result in @@ -777,7 +777,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi return $0.withUpdatedUpdatingAvatar(ItemListAvatarAndNameInfoItemUpdatingAvatar.none) } } - updateAvatarDisposable.set((updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in + updateAvatarDisposable.set((context.engine.peers.updatePeerPhoto(peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }) |> deliverOnMainQueue).start(next: { result in switch result { @@ -993,7 +993,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi let updateTitle: Signal if let titleValue = updateValues.title { - updateTitle = updatePeerTitle(account: context.account, peerId: peerId, title: titleValue) + updateTitle = context.engine.peers.updatePeerTitle(peerId: peerId, title: titleValue) |> mapError { _ in return Void() } } else { updateTitle = .complete() @@ -1001,7 +1001,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi let updateDescription: Signal if let descriptionValue = updateValues.description { - updateDescription = updatePeerDescription(account: context.account, peerId: peerId, description: descriptionValue.isEmpty ? nil : descriptionValue) + updateDescription = context.engine.peers.updatePeerDescription(peerId: peerId, description: descriptionValue.isEmpty ? nil : descriptionValue) |> mapError { _ in return Void() } } else { updateDescription = .complete() diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index d00f4c957e..d73f4ef204 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -1027,7 +1027,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId, } } if revoke { - revokeLinkDisposable.set((revokePeerExportedInvitation(account: context.account, peerId: peerId, link: link) |> deliverOnMainQueue).start(completed: { + revokeLinkDisposable.set((context.engine.peers.revokePeerExportedInvitation(peerId: peerId, link: link) |> deliverOnMainQueue).start(completed: { updateState { $0.withUpdatedRevokingPrivateLink(false) } diff --git a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageController.swift b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageController.swift index 145568ebd9..2b63878ba5 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/StorageUsageController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/StorageUsageController.swift @@ -394,7 +394,7 @@ func cacheUsageStats(context: AccountContext) -> Signal then(collectCacheUsageStats(account: context.account, additionalCachePaths: additionalPaths, logFilesPath: context.sharedContext.applicationBindings.containerPath + "/telegram-data/logs") + |> then(context.engine.resources.collectCacheUsageStats(additionalCachePaths: additionalPaths, logFilesPath: context.sharedContext.applicationBindings.containerPath + "/telegram-data/logs") |> map(Optional.init)) } @@ -581,7 +581,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P var updatedTempPaths = stats.tempPaths var updatedTempSize = stats.tempSize - var signal: Signal = clearCachedMediaResources(account: context.account, mediaResourceIds: clearResourceIds) + var signal: Signal = context.engine.resources.clearCachedMediaResources(mediaResourceIds: clearResourceIds) if otherSize.0 { let removeTempFiles: Signal = Signal { subscriber in let fileManager = FileManager.default @@ -784,7 +784,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P } } - var signal = clearCachedMediaResources(account: context.account, mediaResourceIds: clearResourceIds) + var signal = context.engine.resources.clearCachedMediaResources(mediaResourceIds: clearResourceIds) let resultStats = CacheUsageStats(media: media, mediaResourceIds: stats.mediaResourceIds, peers: stats.peers, otherSize: stats.otherSize, otherPaths: stats.otherPaths, cacheSize: stats.cacheSize, tempPaths: stats.tempPaths, tempSize: stats.tempSize, immutableSize: stats.immutableSize) @@ -911,7 +911,7 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P } } - var signal = clearCachedMediaResources(account: context.account, mediaResourceIds: clearResourceIds) + var signal = context.engine.resources.clearCachedMediaResources(mediaResourceIds: clearResourceIds) let resultStats = CacheUsageStats(media: media, mediaResourceIds: stats.mediaResourceIds, peers: stats.peers, otherSize: stats.otherSize, otherPaths: stats.otherPaths, cacheSize: stats.cacheSize, tempPaths: stats.tempPaths, tempSize: stats.tempSize, immutableSize: stats.immutableSize) diff --git a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift index b34263b70d..545d26e11e 100644 --- a/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift +++ b/submodules/SettingsUI/Sources/Notifications/NotificationsAndSounds.swift @@ -1008,7 +1008,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.inAppNotificationSettings]) let preferences = context.account.postbox.preferencesView(keys: [PreferencesKeys.globalNotifications]) - let exceptionsSignal = Signal.single(exceptionsList) |> then(notificationExceptionsList(postbox: context.account.postbox, network: context.account.network) |> map(Optional.init)) + let exceptionsSignal = Signal.single(exceptionsList) |> then(context.engine.peers.notificationExceptionsList() |> map(Optional.init)) notificationExceptions.set(exceptionsSignal |> map { list -> (NotificationExceptionMode, NotificationExceptionMode, NotificationExceptionMode) in var users:[PeerId : NotificationExceptionWrapper] = [:] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift index 1f7ef63018..0862763d18 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift @@ -520,7 +520,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { let geoPoint = collection.geoPoint.flatMap { geoPoint -> (Double, Double) in return (geoPoint.latitude, geoPoint.longitude) } - return requestChatContextResults(account: self.context.account, botId: collection.botId, peerId: collection.peerId, query: searchContext.result.query, location: .single(geoPoint), offset: nextOffset) + return self.context.engine.messages.requestChatContextResults(botId: collection.botId, peerId: collection.peerId, query: searchContext.result.query, location: .single(geoPoint), offset: nextOffset) |> map { results -> ChatContextResultCollection? in return results?.results } @@ -572,7 +572,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { return (.complete() |> delay(0.1, queue: Queue.concurrentDefaultQueue())) |> then( - requestContextResults(account: context.account, botId: user.id, query: wallpaperQuery, peerId: context.account.peerId, limit: 16) + requestContextResults(context: context, botId: user.id, query: wallpaperQuery, peerId: context.account.peerId, limit: 16) |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/TelegramBaseController/Sources/TelegramBaseController.swift b/submodules/TelegramBaseController/Sources/TelegramBaseController.swift index ce3e450ffc..16e3e6bd81 100644 --- a/submodules/TelegramBaseController/Sources/TelegramBaseController.swift +++ b/submodules/TelegramBaseController/Sources/TelegramBaseController.swift @@ -289,7 +289,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder { let disposable = MetaDisposable() callContextCache.impl.syncWith { impl in - let callContext = impl.get(account: context.account, peerId: peerId, call: activeCall) + let callContext = impl.get(account: context.account, engine: context.engine, peerId: peerId, call: activeCall) disposable.set((callContext.context.panelData |> deliverOnMainQueue).start(next: { panelData in callContext.keep() @@ -863,7 +863,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder { return transaction.getPeerCachedData(peerId: peerId) } - let _ = (combineLatest(currentAccountPeer, cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: peerId), cachedData) + let _ = (combineLatest(currentAccountPeer, context.engine.calls.cachedGroupCallDisplayAsAvailablePeers(peerId: peerId), cachedData) |> map { currentAccountPeer, availablePeers, cachedData -> ([FoundPeer], CachedPeerData?) in var result = currentAccountPeer result.append(contentsOf: availablePeers) diff --git a/submodules/TelegramCallsUI/Sources/MetalVideoRenderingView.swift b/submodules/TelegramCallsUI/Sources/MetalVideoRenderingView.swift index 0114b6cc0f..54545769af 100644 --- a/submodules/TelegramCallsUI/Sources/MetalVideoRenderingView.swift +++ b/submodules/TelegramCallsUI/Sources/MetalVideoRenderingView.swift @@ -1,3 +1,6 @@ +#if targetEnvironment(simulator) +#else + import Foundation import UIKit import AsyncDisplayKit @@ -650,3 +653,5 @@ class MetalVideoRenderingContext { commandBuffer.commit() } } + +#endif diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 3a032427e9..36a3c47ba1 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -92,7 +92,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { return self.panelDataPromise.get() } - public init(account: Account, peerId: PeerId, call: CachedChannelData.ActiveCall) { + public init(account: Account, engine: TelegramEngine, peerId: PeerId, call: CachedChannelData.ActiveCall) { self.panelDataPromise.set(.single(GroupCallPanelData( peerId: peerId, info: GroupCallInfo( @@ -115,7 +115,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { groupCall: nil ))) - self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: nil) + self.disposable = (engine.calls.getGroupCallParticipants(callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: nil) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) @@ -124,8 +124,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { guard let strongSelf = self, let state = state else { return } - let context = GroupCallParticipantsContext( - account: account, + let context = engine.calls.groupCall( peerId: peerId, myPeerId: account.peerId, id: call.id, @@ -185,12 +184,12 @@ public final class AccountGroupCallContextCacheImpl: AccountGroupCallContextCach self.queue = queue } - public func get(account: Account, peerId: PeerId, call: CachedChannelData.ActiveCall) -> AccountGroupCallContextImpl.Proxy { + public func get(account: Account, engine: TelegramEngine, peerId: PeerId, call: CachedChannelData.ActiveCall) -> AccountGroupCallContextImpl.Proxy { let result: Record if let current = self.contexts[call.id] { result = current } else { - let context = AccountGroupCallContextImpl(account: account, peerId: peerId, call: call) + let context = AccountGroupCallContextImpl(account: account, engine: engine, peerId: peerId, call: call) result = Record(context: context) self.contexts[call.id] = result } @@ -216,8 +215,8 @@ public final class AccountGroupCallContextCacheImpl: AccountGroupCallContextCach }) } - public func leaveInBackground(account: Account, id: Int64, accessHash: Int64, source: UInt32) { - let disposable = leaveGroupCall(account: account, callId: id, accessHash: accessHash, source: source).start() + public func leaveInBackground(engine: TelegramEngine, id: Int64, accessHash: Int64, source: UInt32) { + let disposable = engine.calls.leaveGroupCall(callId: id, accessHash: accessHash, source: source).start() self.leaveDisposables.add(disposable) } } @@ -823,7 +822,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { }) if let initialCall = initialCall, let temporaryParticipantsContext = (self.accountContext.cachedGroupCallContexts as? AccountGroupCallContextCacheImpl)?.impl.syncWith({ impl in - impl.get(account: accountContext.account, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash, title: initialCall.title, scheduleTimestamp: initialCall.scheduleTimestamp, subscribedToScheduled: initialCall.subscribedToScheduled)) + impl.get(account: accountContext.account, engine: accountContext.engine, peerId: peerId, call: CachedChannelData.ActiveCall(id: initialCall.id, accessHash: initialCall.accessHash, title: initialCall.title, scheduleTimestamp: initialCall.scheduleTimestamp, subscribedToScheduled: initialCall.subscribedToScheduled)) }) { self.switchToTemporaryParticipantsContext(sourceContext: temporaryParticipantsContext.context.participantsContext, oldMyPeerId: self.joinAsPeerId) } else { @@ -966,11 +965,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } |> beforeNext { view in if let view = view, view.1 == nil { - let _ = fetchAndUpdateCachedPeerData(accountPeerId: accountContext.account.peerId, peerId: myPeerId, network: accountContext.account.network, postbox: accountContext.account.postbox).start() + let _ = accountContext.engine.peers.fetchAndUpdateCachedPeerData(peerId: myPeerId).start() } } if let sourceContext = sourceContext, let initialState = sourceContext.immediateState { - let temporaryParticipantsContext = GroupCallParticipantsContext(account: self.account, peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, accessHash: sourceContext.accessHash, state: initialState, previousServiceState: sourceContext.serviceState) + let temporaryParticipantsContext = self.accountContext.engine.calls.groupCall(peerId: self.peerId, myPeerId: myPeerId, id: sourceContext.id, accessHash: sourceContext.accessHash, state: initialState, previousServiceState: sourceContext.serviceState) self.temporaryParticipantsContext = temporaryParticipantsContext self.participantsContextStateDisposable.set((combineLatest(queue: .mainQueue(), myPeer, @@ -1192,8 +1191,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } |> distinctUntilChanged - let participantsContext = GroupCallParticipantsContext( - account: self.accountContext.account, + let participantsContext = self.accountContext.engine.calls.groupCall( peerId: self.peerId, myPeerId: self.joinAsPeerId, id: callInfo.id, @@ -1229,7 +1227,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } |> beforeNext { view in if let view = view, view.1 == nil { - let _ = fetchAndUpdateCachedPeerData(accountPeerId: accountContext.account.peerId, peerId: myPeerId, network: accountContext.account.network, postbox: accountContext.account.postbox).start() + let _ = accountContext.engine.peers.fetchAndUpdateCachedPeerData(peerId: myPeerId).start() } } self.participantsContextStateDisposable.set(combineLatest(queue: .mainQueue(), @@ -1399,7 +1397,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { disposable.set(strongSelf.requestMediaChannelDescriptions(ssrcs: ssrcs, completion: completion)) } return disposable - }, audioStreamData: OngoingGroupCallContext.AudioStreamData(account: self.accountContext.account, callId: callInfo.id, accessHash: callInfo.accessHash), rejoinNeeded: { [weak self] in + }, audioStreamData: OngoingGroupCallContext.AudioStreamData(engine: self.accountContext.engine, callId: callInfo.id, accessHash: callInfo.accessHash), rejoinNeeded: { [weak self] in Queue.mainQueue().async { guard let strongSelf = self else { return @@ -1464,8 +1462,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } strongSelf.currentLocalSsrc = ssrc - strongSelf.requestDisposable.set((joinGroupCall( - account: strongSelf.account, + strongSelf.requestDisposable.set((strongSelf.accountContext.engine.calls.joinGroupCall( peerId: strongSelf.peerId, joinAs: strongSelf.joinAsPeerId, callId: callInfo.id, @@ -1525,7 +1522,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { ]), on: .root, blockInteraction: false, completion: {}) } else if case .invalidJoinAsPeer = error { let peerId = strongSelf.peerId - let _ = clearCachedGroupCallDisplayAsAvailablePeers(account: strongSelf.accountContext.account, peerId: peerId).start() + 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 { @@ -1749,8 +1746,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { serviceState = participantsContext.serviceState } - let participantsContext = GroupCallParticipantsContext( - account: self.accountContext.account, + let participantsContext = self.accountContext.engine.calls.groupCall( peerId: self.peerId, myPeerId: self.joinAsPeerId, id: callInfo.id, @@ -1770,7 +1766,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } |> beforeNext { view in if let view = view, view.1 == nil { - let _ = fetchAndUpdateCachedPeerData(accountPeerId: accountContext.account.peerId, peerId: myPeerId, network: accountContext.account.network, postbox: accountContext.account.postbox).start() + let _ = accountContext.engine.peers.fetchAndUpdateCachedPeerData(peerId: myPeerId).start() } } @@ -2105,7 +2101,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } if !remainingSsrcs.isEmpty, let callInfo = self.internalState.callInfo { - return (getGroupCallParticipants(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, offset: "", ssrcs: Array(remainingSsrcs), limit: 100, sortAscending: callInfo.sortAscending) + return (self.accountContext.engine.calls.getGroupCallParticipants(callId: callInfo.id, accessHash: callInfo.accessHash, offset: "", ssrcs: Array(remainingSsrcs), limit: 100, sortAscending: callInfo.sortAscending) |> deliverOnMainQueue).start(next: { state in extractMediaChannelDescriptions(remainingSsrcs: &remainingSsrcs, participants: state.participants, into: &result) @@ -2122,7 +2118,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return } if case let .established(callInfo, connectionMode, _, ssrc, _) = self.internalState, case .rtc = connectionMode { - let checkSignal = checkGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, ssrcs: [ssrc]) + let checkSignal = self.accountContext.engine.calls.checkGroupCall(callId: callInfo.id, accessHash: callInfo.accessHash, ssrcs: [ssrc]) self.checkCallDisposable = (( checkSignal @@ -2288,7 +2284,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.leaving = true if let callInfo = self.internalState.callInfo { if terminateIfPossible { - self.leaveDisposable.set((stopGroupCall(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash) + self.leaveDisposable.set((self.accountContext.engine.calls.stopGroupCall(peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash) |> deliverOnMainQueue).start(completed: { [weak self] in guard let strongSelf = self else { return @@ -2297,12 +2293,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { })) } else if let localSsrc = self.currentLocalSsrc { if let contexts = self.accountContext.cachedGroupCallContexts as? AccountGroupCallContextCacheImpl { - let account = self.account + let engine = self.accountContext.engine let id = callInfo.id let accessHash = callInfo.accessHash let source = localSsrc contexts.impl.with { impl in - impl.leaveInBackground(account: account, id: id, accessHash: accessHash, source: source) + impl.leaveInBackground(engine: engine, id: id, accessHash: accessHash, source: source) } } self.markAsCanBeRemoved() @@ -2365,7 +2361,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.stateValue.subscribedToScheduled = subscribe - self.subscribeDisposable.set((toggleScheduledGroupCallSubscription(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash, subscribe: subscribe) + self.subscribeDisposable.set((self.accountContext.engine.calls.toggleScheduledGroupCallSubscription(peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash, subscribe: subscribe) |> deliverOnMainQueue).start()) } @@ -2383,7 +2379,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { activeSpeakers: Set() ))) - self.startDisposable.set((createGroupCall(account: self.account, peerId: self.peerId, title: nil, scheduleDate: timestamp) + self.startDisposable.set((self.accountContext.engine.calls.createGroupCall(peerId: self.peerId, title: nil, scheduleDate: timestamp) |> deliverOnMainQueue).start(next: { [weak self] callInfo in guard let strongSelf = self else { return @@ -2405,7 +2401,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.isScheduledStarted = true self.stateValue.scheduleTimestamp = nil - self.startDisposable.set((startScheduledGroupCall(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash) + self.startDisposable.set((self.accountContext.engine.calls.startScheduledGroupCall(peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash) |> deliverOnMainQueue).start(next: { [weak self] callInfo in guard let strongSelf = self else { return @@ -2661,8 +2657,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return } - strongSelf.requestDisposable.set((joinGroupCallAsScreencast( - account: strongSelf.account, + strongSelf.requestDisposable.set((strongSelf.accountContext.engine.calls.joinGroupCallAsScreencast( peerId: strongSelf.peerId, callId: callInfo.id, accessHash: callInfo.accessHash, @@ -2693,8 +2688,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { let maybeCallInfo: GroupCallInfo? = self.internalState.callInfo if let callInfo = maybeCallInfo { - self.screencastJoinDisposable.set(leaveGroupCallAsScreencast( - account: self.account, + self.screencastJoinDisposable.set(self.accountContext.engine.calls.leaveGroupCallAsScreencast( callId: callInfo.id, accessHash: callInfo.accessHash ).start()) @@ -2702,19 +2696,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.screencastBufferServerContext?.stopScreencast() } - /*if let _ = self.screencastIpcContext { - self.screencastIpcContext = nil - - let maybeCallInfo: GroupCallInfo? = self.internalState.callInfo - - if let callInfo = maybeCallInfo { - self.screencastJoinDisposable.set(leaveGroupCallAsScreencast( - account: self.account, - callId: callInfo.id, - accessHash: callInfo.accessHash - ).start()) - } - }*/ } public func setVolume(peerId: PeerId, volume: Int32, sync: Bool) { @@ -2894,9 +2875,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } let account = self.account + let context = self.accountContext let currentCall: Signal if let initialCall = self.initialCall { - currentCall = getCurrentGroupCall(account: account, callId: initialCall.id, accessHash: initialCall.accessHash) + currentCall = context.engine.calls.getCurrentGroupCall(callId: initialCall.id, accessHash: initialCall.accessHash) |> mapError { _ -> CallError in return .generic } @@ -2904,7 +2886,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return summary?.info } } else if case let .active(callInfo) = self.internalState { - currentCall = getCurrentGroupCall(account: account, callId: callInfo.id, accessHash: callInfo.accessHash) + currentCall = context.engine.calls.getCurrentGroupCall(callId: callInfo.id, accessHash: callInfo.accessHash) |> mapError { _ -> CallError in return .generic } @@ -2961,7 +2943,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { updatedInvitedPeers.insert(peerId, at: 0) self.invitedPeersValue = updatedInvitedPeers - let _ = inviteToGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, peerId: peerId).start() + let _ = self.accountContext.engine.calls.inviteToGroupCall(callId: callInfo.id, accessHash: callInfo.accessHash, peerId: peerId).start() return true } @@ -2977,10 +2959,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return } self.stateValue.title = title.isEmpty ? nil : title - let _ = editGroupCallTitle(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, title: title).start() + let _ = self.accountContext.engine.calls.editGroupCallTitle(callId: callInfo.id, accessHash: callInfo.accessHash, title: title).start() } public var inviteLinks: Signal { + let engine = self.accountContext.engine + return self.state |> map { state -> PeerId in return state.myPeerId @@ -2997,7 +2981,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } |> mapToSignal { state in if let callInfo = state.callInfo { - return groupCallInviteLinks(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash) + return engine.calls.groupCallInviteLinks(callId: callInfo.id, accessHash: callInfo.accessHash) } else { return .complete() } diff --git a/submodules/TelegramCallsUI/Sources/VideoRenderingContext.swift b/submodules/TelegramCallsUI/Sources/VideoRenderingContext.swift index e2648d83c9..e9bb3e13cd 100644 --- a/submodules/TelegramCallsUI/Sources/VideoRenderingContext.swift +++ b/submodules/TelegramCallsUI/Sources/VideoRenderingContext.swift @@ -19,6 +19,8 @@ protocol VideoRenderingView: UIView { class VideoRenderingContext { private var metalContextImpl: Any? + #if targetEnvironment(simulator) + #else @available(iOS 13.0, *) var metalContext: MetalVideoRenderingContext { if let value = self.metalContextImpl as? MetalVideoRenderingContext { @@ -29,19 +31,27 @@ class VideoRenderingContext { return value } } + #endif func makeView(input: Signal, blur: Bool) -> VideoRenderingView? { + #if targetEnvironment(simulator) + return SampleBufferVideoRenderingView(input: input) + #else if #available(iOS 13.0, *) { return MetalVideoRenderingView(renderingContext: self.metalContext, input: input, blur: blur) } else { return SampleBufferVideoRenderingView(input: input) } + #endif } func updateVisibility(isVisible: Bool) { + #if targetEnvironment(simulator) + #else if #available(iOS 13.0, *) { self.metalContext.updateVisibility(isVisible: isVisible) } + #endif } } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index ddb53a75b6..ad5129c780 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1167,7 +1167,7 @@ public final class VoiceChatController: ViewController { let displayAsPeers: Signal<[FoundPeer], NoError> = currentAccountPeer |> then( - combineLatest(currentAccountPeer, cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: call.peerId)) + combineLatest(currentAccountPeer, context.engine.calls.cachedGroupCallDisplayAsAvailablePeers(peerId: call.peerId)) |> map { currentAccountPeer, availablePeers -> [FoundPeer] in var result = currentAccountPeer result.append(contentsOf: availablePeers) @@ -1553,7 +1553,7 @@ public final class VoiceChatController: ViewController { return .complete() }).start() } else { - let _ = (updatePeerDescription(account: strongSelf.context.account, peerId: peer.id, description: bio) + let _ = (strongSelf.context.engine.peers.updatePeerDescription(peerId: peer.id, description: bio) |> `catch` { _ -> Signal in return .complete() }).start() @@ -5913,7 +5913,7 @@ public final class VoiceChatController: ViewController { let proceed = { let _ = strongSelf.currentAvatarMixin.swap(nil) let postbox = strongSelf.context.account.postbox - strongSelf.updateAvatarDisposable.set((updatePeerPhoto(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, stateManager: strongSelf.context.account.stateManager, accountPeerId: strongSelf.context.account.peerId, peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in + strongSelf.updateAvatarDisposable.set((strongSelf.context.engine.peers.updatePeerPhoto(peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) |> deliverOnMainQueue).start()) @@ -5966,9 +5966,9 @@ public final class VoiceChatController: ViewController { self.updateAvatarPromise.set(.single((representation, 0.0))) let postbox = self.call.account.postbox - let signal = peerId.namespace == Namespaces.Peer.CloudUser ? updateAccountPhoto(account: self.call.account, resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in + let signal = peerId.namespace == Namespaces.Peer.CloudUser ? self.call.accountContext.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) - }) : updatePeerPhoto(postbox: postbox, network: self.call.account.network, stateManager: self.call.account.stateManager, accountPeerId: self.context.account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: postbox, network: self.call.account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in + }) : self.call.accountContext.engine.peers.updatePeerPhoto(peerId: peerId, photo: self.call.accountContext.engine.peers.uploadedPeerPhoto(resource: resource), mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) @@ -6004,7 +6004,8 @@ public final class VoiceChatController: ViewController { if let adjustments = adjustments, adjustments.videoStartValue > 0.0 { videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue } - + + let context = self.context let account = self.context.account let signal = Signal { [weak self] subscriber in let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in @@ -6014,7 +6015,7 @@ public final class VoiceChatController: ViewController { return nil } } - let uploadInterface = LegacyLiveUploadInterface(account: account) + let uploadInterface = LegacyLiveUploadInterface(context: context) let signal: SSignal if let asset = asset as? AVAsset { signal = TGMediaVideoConverter.convert(asset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)! @@ -6085,11 +6086,11 @@ public final class VoiceChatController: ViewController { self.updateAvatarDisposable.set((signal |> mapToSignal { videoResource -> Signal in if peerId.namespace == Namespaces.Peer.CloudUser { - return updateAccountPhoto(account: account, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } else { - return updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: photoResource), video: uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: videoResource) |> map(Optional.init), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: context.engine.peers.uploadedPeerVideo(resource: videoResource) |> map(Optional.init), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift index 2d5655924d..2c1ecb5060 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift @@ -72,7 +72,7 @@ public final class VoiceChatJoinScreen: ViewController { let context = self.context let peerId = self.peerId let invite = self.invite - let signal = updatedCurrentPeerGroupCall(account: context.account, peerId: peerId) + let signal = context.engine.calls.updatedCurrentPeerGroupCall(peerId: peerId) |> castError(GetCurrentGroupCallError.self) |> mapToSignal { call -> Signal<(Peer, GroupCallSummary)?, GetCurrentGroupCallError> in if let call = call { @@ -80,7 +80,7 @@ public final class VoiceChatJoinScreen: ViewController { return transaction.getPeer(peerId) } |> castError(GetCurrentGroupCallError.self) - return combineLatest(peer, getCurrentGroupCall(account: context.account, callId: call.id, accessHash: call.accessHash)) + return combineLatest(peer, context.engine.calls.getCurrentGroupCall(callId: call.id, accessHash: call.accessHash)) |> map { peer, call -> (Peer, GroupCallSummary)? in if let peer = peer, let call = call { return (peer, call) @@ -125,7 +125,7 @@ public final class VoiceChatJoinScreen: ViewController { currentGroupCall = .single(nil) } - self.disposable.set(combineLatest(queue: Queue.mainQueue(), signal, cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: peerId) |> castError(GetCurrentGroupCallError.self), cachedData, currentGroupCall).start(next: { [weak self] peerAndCall, availablePeers, cachedData, currentGroupCallIdAndCanUnmute in + self.disposable.set(combineLatest(queue: Queue.mainQueue(), signal, context.engine.calls.cachedGroupCallDisplayAsAvailablePeers(peerId: peerId) |> castError(GetCurrentGroupCallError.self), cachedData, currentGroupCall).start(next: { [weak self] peerAndCall, availablePeers, cachedData, currentGroupCallIdAndCanUnmute in if let strongSelf = self { if let (peer, call) = peerAndCall { if let (currentGroupCall, currentGroupCallId, canUnmute) = currentGroupCallIdAndCanUnmute, call.info.id == currentGroupCallId { diff --git a/submodules/TelegramCore/Sources/Account/Account.swift b/submodules/TelegramCore/Sources/Account/Account.swift index cfe5c2e9f2..3c269a5ee9 100644 --- a/submodules/TelegramCore/Sources/Account/Account.swift +++ b/submodules/TelegramCore/Sources/Account/Account.swift @@ -852,7 +852,7 @@ public class Account { public private(set) var viewTracker: AccountViewTracker! public private(set) var pendingMessageManager: PendingMessageManager! public private(set) var pendingUpdateMessageManager: PendingUpdateMessageManager! - public private(set) var messageMediaPreuploadManager: MessageMediaPreuploadManager! + private(set) var messageMediaPreuploadManager: MessageMediaPreuploadManager! private(set) var mediaReferenceRevalidationContext: MediaReferenceRevalidationContext! private var peerInputActivityManager: PeerInputActivityManager! private var localInputActivityManager: PeerInputActivityManager! diff --git a/submodules/TelegramCore/Sources/ChatContextResult.swift b/submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift similarity index 100% rename from submodules/TelegramCore/Sources/ChatContextResult.swift rename to submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift diff --git a/submodules/TelegramCore/Sources/Authorization.swift b/submodules/TelegramCore/Sources/Authorization.swift index 6a402cc7d0..ce58de6028 100644 --- a/submodules/TelegramCore/Sources/Authorization.swift +++ b/submodules/TelegramCore/Sources/Authorization.swift @@ -533,7 +533,7 @@ public func signUpWithName(accountManager: AccountManager, account: Unauthorized let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) account.postbox.mediaBox.storeResourceData(resource.id, data: avatarData) - return updatePeerPhotoInternal(postbox: account.postbox, network: account.network, stateManager: nil, accountPeerId: user.id, peer: .single(user), photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource), video: avatarVideo, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { _, _ in .single([:]) }) + return _internal_updatePeerPhotoInternal(postbox: account.postbox, network: account.network, stateManager: nil, accountPeerId: user.id, peer: .single(user), photo: _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource), video: avatarVideo, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { _, _ in .single([:]) }) |> `catch` { _ -> Signal in return .complete() } diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 929893732b..8dd610993c 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1236,7 +1236,7 @@ public final class AccountViewTracker { return } let queue = self.queue - context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in + context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in queue.async { guard let strongSelf = self else { return @@ -1278,7 +1278,7 @@ public final class AccountViewTracker { return } let queue = self.queue - context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in + context.disposable.set(combineLatest(fetchAndUpdateSupplementalCachedPeerData(peerId: peerId, network: account.network, postbox: account.postbox), _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox)).start(next: { [weak self] supplementalStatus, cachedStatus in queue.async { guard let strongSelf = self else { return diff --git a/submodules/TelegramCore/Sources/ChatHistoryPreloadManager.swift b/submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/ChatHistoryPreloadManager.swift rename to submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift diff --git a/submodules/TelegramCore/Sources/MessageMediaPreuploadManager.swift b/submodules/TelegramCore/Sources/State/MessageMediaPreuploadManager.swift similarity index 95% rename from submodules/TelegramCore/Sources/MessageMediaPreuploadManager.swift rename to submodules/TelegramCore/Sources/State/MessageMediaPreuploadManager.swift index e53e9b0414..dedd571f41 100644 --- a/submodules/TelegramCore/Sources/MessageMediaPreuploadManager.swift +++ b/submodules/TelegramCore/Sources/State/MessageMediaPreuploadManager.swift @@ -33,7 +33,7 @@ private final class MessageMediaPreuploadManagerContext { assert(self.queue.isCurrent()) } - func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete:(()->Void)? = nil) { + func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete: (()->Void)? = nil) { let context = MessageMediaPreuploadManagerUploadContext() self.uploadContexts[id] = context let queue = self.queue @@ -103,7 +103,7 @@ private final class MessageMediaPreuploadManagerContext { } } -public final class MessageMediaPreuploadManager { +final class MessageMediaPreuploadManager { private let impl: QueueLocalObject init() { @@ -113,7 +113,7 @@ public final class MessageMediaPreuploadManager { }) } - public func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete:(()->Void)? = nil) { + func add(network: Network, postbox: Postbox, id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete:(()->Void)? = nil) { self.impl.with { context in context.add(network: network, postbox: postbox, id: id, encrypt: encrypt, tag: tag, source: source, onComplete: onComplete) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift index 8ea9a469ae..5fbab699aa 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift @@ -46,5 +46,17 @@ public extension TelegramEngine { public func registerNotificationToken(token: Data, type: NotificationTokenType, sandbox: Bool, otherAccountUserIds: [PeerId.Id], excludeMutedChats: Bool) -> Signal { return _internal_registerNotificationToken(account: self.account, token: token, type: type, sandbox: sandbox, otherAccountUserIds: otherAccountUserIds, excludeMutedChats: excludeMutedChats) } + + public func updateAccountPhoto(resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updateAccountPhoto(account: self.account, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + } + + public func updatePeerPhotoExisting(reference: TelegramMediaImageReference) -> Signal { + return _internal_updatePeerPhotoExisting(network: self.account.network, reference: reference) + } + + public func removeAccountPhoto(reference: TelegramMediaImageReference?) -> Signal { + return _internal_removeAccountPhoto(network: self.account.network, reference: reference) + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift index 2b1e5a2ae2..c0f69f9d95 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift @@ -39,6 +39,10 @@ public extension TelegramEngineUnauthorized { public func resendTwoStepRecoveryEmail() -> Signal { return _internal_resendTwoStepRecoveryEmail(network: self.account.network) } + + public func uploadedPeerVideo(resource: MediaResource) -> Signal { + return _internal_uploadedPeerVideo(postbox: self.account.postbox, network: self.account.network, messageMediaPreuploadManager: nil, resource: resource) + } } } diff --git a/submodules/TelegramCore/Sources/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift similarity index 95% rename from submodules/TelegramCore/Sources/GroupCalls.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index 031898f2c7..5bf3a438e2 100644 --- a/submodules/TelegramCore/Sources/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -80,7 +80,7 @@ public enum GetCurrentGroupCallError { case generic } -public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal { +func _internal_getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal { return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> mapError { _ -> GetCurrentGroupCallError in return .generic @@ -144,7 +144,7 @@ public enum CreateGroupCallError { case scheduledTooLate } -public func createGroupCall(account: Account, peerId: PeerId, title: String?, scheduleDate: Int32?) -> Signal { +func _internal_createGroupCall(account: Account, peerId: PeerId, title: String?, scheduleDate: Int32?) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in let callPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) return callPeer @@ -210,7 +210,7 @@ public enum StartScheduledGroupCallError { case generic } -public func startScheduledGroupCall(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { +func _internal_startScheduledGroupCall(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { return account.network.request(Api.functions.phone.startScheduledGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> mapError { error -> StartScheduledGroupCallError in return .generic @@ -254,7 +254,7 @@ public enum ToggleScheduledGroupCallSubscriptionError { case generic } -public func toggleScheduledGroupCallSubscription(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64, subscribe: Bool) -> Signal { +func _internal_toggleScheduledGroupCallSubscription(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64, subscribe: Bool) -> Signal { return account.network.request(Api.functions.phone.toggleGroupCallStartSubscription(call: .inputGroupCall(id: callId, accessHash: accessHash), subscribed: subscribe ? .boolTrue : .boolFalse)) |> mapError { error -> ToggleScheduledGroupCallSubscriptionError in return .generic @@ -296,7 +296,7 @@ public enum UpdateGroupCallJoinAsPeerError { case generic } -public func updateGroupCallJoinAsPeer(account: Account, peerId: PeerId, joinAs: PeerId) -> Signal { +func _internal_updateGroupCallJoinAsPeer(account: Account, peerId: PeerId, joinAs: PeerId) -> Signal { return account.postbox.transaction { transaction -> (Api.InputPeer, Api.InputPeer)? in if let peer = transaction.getPeer(peerId), let joinAsPeer = transaction.getPeer(joinAs), let inputPeer = apiInputPeer(peer), let joinInputPeer = apiInputPeer(joinAsPeer) { return (inputPeer, joinInputPeer) @@ -335,10 +335,10 @@ public enum GetGroupCallParticipantsError { case generic } -public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal { +func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal { let sortAscendingValue: Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int), GetGroupCallParticipantsError> - sortAscendingValue = getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash) + sortAscendingValue = _internal_getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash) |> mapError { _ -> GetGroupCallParticipantsError in return .generic } @@ -443,7 +443,7 @@ public struct JoinGroupCallResult { public var jsonParams: String } -public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal { +func _internal_joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in if let joinAs = joinAs { return transaction.getPeer(joinAs).flatMap(apiInputPeer) @@ -498,7 +498,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal } } - let getParticipantsRequest = getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: true) + let getParticipantsRequest = _internal_getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: true) |> mapError { _ -> JoinGroupCallError in return .generic } @@ -687,7 +687,7 @@ public struct JoinGroupCallAsScreencastResult { public var endpointId: String } -public func joinGroupCallAsScreencast(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64, joinPayload: String) -> Signal { +func _internal_joinGroupCallAsScreencast(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64, joinPayload: String) -> Signal { return account.network.request(Api.functions.phone.joinGroupCallPresentation(call: .inputGroupCall(id: callId, accessHash: accessHash), params: .dataJSON(data: joinPayload))) |> mapError { _ -> JoinGroupCallError in return .generic @@ -735,7 +735,7 @@ public enum LeaveGroupCallAsScreencastError { case generic } -public func leaveGroupCallAsScreencast(account: Account, callId: Int64, accessHash: Int64) -> Signal { +func _internal_leaveGroupCallAsScreencast(account: Account, callId: Int64, accessHash: Int64) -> Signal { return account.network.request(Api.functions.phone.leaveGroupCallPresentation(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> mapError { _ -> LeaveGroupCallAsScreencastError in return .generic @@ -751,7 +751,7 @@ public enum LeaveGroupCallError { case generic } -public func leaveGroupCall(account: Account, callId: Int64, accessHash: Int64, source: UInt32) -> Signal { +func _internal_leaveGroupCall(account: Account, callId: Int64, accessHash: Int64, source: UInt32) -> Signal { return account.network.request(Api.functions.phone.leaveGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), source: Int32(bitPattern: source))) |> mapError { _ -> LeaveGroupCallError in return .generic @@ -767,7 +767,7 @@ public enum StopGroupCallError { case generic } -public func stopGroupCall(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { +func _internal_stopGroupCall(account: Account, peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { return account.network.request(Api.functions.phone.discardGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> mapError { _ -> StopGroupCallError in return .generic @@ -809,7 +809,7 @@ public func stopGroupCall(account: Account, peerId: PeerId, callId: Int64, acces } } -public func checkGroupCall(account: Account, callId: Int64, accessHash: Int64, ssrcs: [UInt32]) -> Signal<[UInt32], NoError> { +func _internal_checkGroupCall(account: Account, callId: Int64, accessHash: Int64, ssrcs: [UInt32]) -> Signal<[UInt32], NoError> { return account.network.request(Api.functions.phone.checkGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), sources: ssrcs.map(Int32.init(bitPattern:)))) |> `catch` { _ -> Signal<[Int32], NoError> in return .single([]) @@ -1297,7 +1297,7 @@ public final class GroupCallParticipantsContext { public private(set) var serviceState: ServiceState - public init(account: Account, peerId: PeerId, myPeerId: PeerId, id: Int64, accessHash: Int64, state: State, previousServiceState: ServiceState?) { + init(account: Account, peerId: PeerId, myPeerId: PeerId, id: Int64, accessHash: Int64, state: State, previousServiceState: ServiceState?) { self.account = account self.myPeerId = myPeerId self.id = id @@ -1563,7 +1563,7 @@ public final class GroupCallParticipantsContext { Logger.shared.log("GroupCallParticipantsContext", "will request ssrcs=\(ssrcs)") - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: Array(ssrcs), limit: 100, sortAscending: true) + self.disposable.set((_internal_getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: Array(ssrcs), limit: 100, sortAscending: true) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -1775,7 +1775,7 @@ public final class GroupCallParticipantsContext { self.updateQueue.removeAll() - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) + self.disposable.set((_internal_getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -2034,7 +2034,7 @@ public final class GroupCallParticipantsContext { } self.isLoadingMore = true - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) + self.disposable.set((_internal_getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, ssrcs: [], limit: 100, sortAscending: self.stateValue.state.sortAscending) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -2126,7 +2126,7 @@ public enum InviteToGroupCallError { case generic } -public func inviteToGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId) -> Signal { +func _internal_inviteToGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Peer? in return transaction.getPeer(peerId) } @@ -2161,7 +2161,7 @@ public struct GroupCallInviteLinks { } } -public func groupCallInviteLinks(account: Account, callId: Int64, accessHash: Int64) -> Signal { +func _internal_groupCallInviteLinks(account: Account, callId: Int64, accessHash: Int64) -> Signal { let call = Api.InputGroupCall.inputGroupCall(id: callId, accessHash: accessHash) let listenerInvite: Signal = account.network.request(Api.functions.phone.exportGroupCallInvite(flags: 0, call: call)) |> map(Optional.init) @@ -2201,7 +2201,7 @@ public enum EditGroupCallTitleError { case generic } -public func editGroupCallTitle(account: Account, callId: Int64, accessHash: Int64, title: String) -> Signal { +func _internal_editGroupCallTitle(account: Account, callId: Int64, accessHash: Int64, title: String) -> Signal { return account.network.request(Api.functions.phone.editGroupCallTitle(call: .inputGroupCall(id: callId, accessHash: accessHash), title: title)) |> mapError { _ -> EditGroupCallTitleError in return .generic } @@ -2211,7 +2211,7 @@ public func editGroupCallTitle(account: Account, callId: Int64, accessHash: Int6 } } -public func groupCallDisplayAsAvailablePeers(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[FoundPeer], NoError> { +func _internal_groupCallDisplayAsAvailablePeers(network: Network, postbox: Postbox, peerId: PeerId) -> Signal<[FoundPeer], NoError> { return postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) } |> mapToSignal { inputPeer in @@ -2279,7 +2279,7 @@ public final class CachedDisplayAsPeers: PostboxCoding { } } -public func clearCachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: PeerId) -> Signal { +func _internal_clearCachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Void in let key = ValueBoxKey(length: 8) key.setInt64(0, value: peerId.toInt64()) @@ -2288,7 +2288,7 @@ public func clearCachedGroupCallDisplayAsAvailablePeers(account: Account, peerId |> ignoreValues } -public func cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: PeerId) -> Signal<[FoundPeer], NoError> { +func _internal_cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: PeerId) -> Signal<[FoundPeer], NoError> { let key = ValueBoxKey(length: 8) key.setInt64(0, value: peerId.toInt64()) return account.postbox.transaction { transaction -> ([FoundPeer], Int32)? in @@ -2314,7 +2314,7 @@ public func cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: Pee if let (cachedPeers, timestamp) = cachedPeersAndTimestamp, currentTimestamp - timestamp < 60 * 3 && !cachedPeers.isEmpty { return .single(cachedPeers) } else { - return groupCallDisplayAsAvailablePeers(network: account.network, postbox: account.postbox, peerId: peerId) + return _internal_groupCallDisplayAsAvailablePeers(network: account.network, postbox: account.postbox, peerId: peerId) |> mapToSignal { peers -> Signal<[FoundPeer], NoError> in return account.postbox.transaction { transaction -> [FoundPeer] in let currentTimestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) @@ -2326,8 +2326,8 @@ public func cachedGroupCallDisplayAsAvailablePeers(account: Account, peerId: Pee } } -public func updatedCurrentPeerGroupCall(account: Account, peerId: PeerId) -> Signal { - return fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox) +func _internal_updatedCurrentPeerGroupCall(account: Account, peerId: PeerId) -> Signal { + return _internal_fetchAndUpdateCachedPeerData(accountPeerId: account.peerId, peerId: peerId, network: account.network, postbox: account.postbox) |> mapToSignal { _ -> Signal in return account.postbox.transaction { transaction -> CachedChannelData.ActiveCall? in return (transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData)?.activeCall @@ -2363,7 +2363,7 @@ public final class AudioBroadcastDataSource { } } -public func getAudioBroadcastDataSource(account: Account, callId: Int64, accessHash: Int64) -> Signal { +func _internal_getAudioBroadcastDataSource(account: Account, callId: Int64, accessHash: Int64) -> Signal { return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> map(Optional.init) |> `catch` { _ -> Signal in @@ -2399,7 +2399,7 @@ public struct GetAudioBroadcastPartResult { public var responseTimestamp: Double } -public func getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal { +func _internal_getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal { let scale: Int32 switch durationMilliseconds { case 1000: diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift index 8f2dd214df..3e0f02a662 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift @@ -1,4 +1,6 @@ import SwiftSignalKit +import Postbox +import SyncCore public extension TelegramEngine { final class Calls { @@ -15,5 +17,93 @@ public extension TelegramEngine { public func saveCallDebugLog(callId: CallId, log: String) -> Signal { return _internal_saveCallDebugLog(network: self.account.network, callId: callId, log: log) } + + public func getCurrentGroupCall(callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal { + return _internal_getCurrentGroupCall(account: self.account, callId: callId, accessHash: accessHash, peerId: peerId) + } + + public func createGroupCall(peerId: PeerId, title: String?, scheduleDate: Int32?) -> Signal { + return _internal_createGroupCall(account: self.account, peerId: peerId, title: title, scheduleDate: scheduleDate) + } + + public func startScheduledGroupCall(peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { + return _internal_startScheduledGroupCall(account: self.account, peerId: peerId, callId: callId, accessHash: accessHash) + } + + public func toggleScheduledGroupCallSubscription(peerId: PeerId, callId: Int64, accessHash: Int64, subscribe: Bool) -> Signal { + return _internal_toggleScheduledGroupCallSubscription(account: self.account, peerId: peerId, callId: callId, accessHash: accessHash, subscribe: subscribe) + } + + public func updateGroupCallJoinAsPeer(peerId: PeerId, joinAs: PeerId) -> Signal { + return _internal_updateGroupCallJoinAsPeer(account: self.account, peerId: peerId, joinAs: joinAs) + } + + public func getGroupCallParticipants(callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal { + return _internal_getGroupCallParticipants(account: self.account, callId: callId, accessHash: accessHash, offset: offset, ssrcs: ssrcs, limit: limit, sortAscending: sortAscending) + } + + public func joinGroupCall(peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal { + return _internal_joinGroupCall(account: self.account, peerId: peerId, joinAs: joinAs, callId: callId, accessHash: accessHash, preferMuted: preferMuted, joinPayload: joinPayload, peerAdminIds: peerAdminIds, inviteHash: inviteHash) + } + + public func joinGroupCallAsScreencast(peerId: PeerId, callId: Int64, accessHash: Int64, joinPayload: String) -> Signal { + return _internal_joinGroupCallAsScreencast(account: self.account, peerId: peerId, callId: callId, accessHash: accessHash, joinPayload: joinPayload) + } + + public func leaveGroupCallAsScreencast(callId: Int64, accessHash: Int64) -> Signal { + return _internal_leaveGroupCallAsScreencast(account: self.account, callId: callId, accessHash: accessHash) + } + + public func leaveGroupCall(callId: Int64, accessHash: Int64, source: UInt32) -> Signal { + return _internal_leaveGroupCall(account: self.account, callId: callId, accessHash: accessHash, source: source) + } + + public func stopGroupCall(peerId: PeerId, callId: Int64, accessHash: Int64) -> Signal { + return _internal_stopGroupCall(account: self.account, peerId: peerId, callId: callId, accessHash: accessHash) + } + + public func checkGroupCall(callId: Int64, accessHash: Int64, ssrcs: [UInt32]) -> Signal<[UInt32], NoError> { + return _internal_checkGroupCall(account: account, callId: callId, accessHash: accessHash, ssrcs: ssrcs) + } + + public func inviteToGroupCall(callId: Int64, accessHash: Int64, peerId: PeerId) -> Signal { + return _internal_inviteToGroupCall(account: self.account, callId: callId, accessHash: accessHash, peerId: peerId) + } + + public func groupCallInviteLinks(callId: Int64, accessHash: Int64) -> Signal { + return _internal_groupCallInviteLinks(account: self.account, callId: callId, accessHash: accessHash) + } + + public func editGroupCallTitle(callId: Int64, accessHash: Int64, title: String) -> Signal { + return _internal_editGroupCallTitle(account: self.account, callId: callId, accessHash: accessHash, title: title) + } + + /*public func groupCallDisplayAsAvailablePeers(peerId: PeerId) -> Signal<[FoundPeer], NoError> { + return _internal_groupCallDisplayAsAvailablePeers(network: self.account.network, postbox: self.account.postbox, peerId: peerId) + }*/ + + public func clearCachedGroupCallDisplayAsAvailablePeers(peerId: PeerId) -> Signal { + return _internal_clearCachedGroupCallDisplayAsAvailablePeers(account: self.account, peerId: peerId) + } + + public func cachedGroupCallDisplayAsAvailablePeers(peerId: PeerId) -> Signal<[FoundPeer], NoError> { + return _internal_cachedGroupCallDisplayAsAvailablePeers(account: self.account, peerId: peerId) + } + + public func updatedCurrentPeerGroupCall(peerId: PeerId) -> Signal { + return _internal_updatedCurrentPeerGroupCall(account: self.account, peerId: peerId) + } + + public func getAudioBroadcastDataSource(callId: Int64, accessHash: Int64) -> Signal { + return _internal_getAudioBroadcastDataSource(account: self.account, callId: callId, accessHash: accessHash) + } + + public func getAudioBroadcastPart(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64, timestampIdMilliseconds: Int64, durationMilliseconds: Int64) -> Signal { + return _internal_getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds) + } + + public func groupCall(peerId: PeerId, myPeerId: PeerId, id: Int64, accessHash: Int64, state: GroupCallParticipantsContext.State, previousServiceState: GroupCallParticipantsContext.ServiceState?) -> GroupCallParticipantsContext { + return GroupCallParticipantsContext(account: self.account, peerId: peerId, myPeerId: myPeerId, id: id, accessHash: accessHash, state: state, previousServiceState: previousServiceState) + } } } diff --git a/submodules/TelegramCore/Sources/OutgoingMessageWithChatContextResult.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift similarity index 79% rename from submodules/TelegramCore/Sources/OutgoingMessageWithChatContextResult.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift index 9b186b1fd0..51b5b930f5 100644 --- a/submodules/TelegramCore/Sources/OutgoingMessageWithChatContextResult.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift @@ -3,8 +3,15 @@ import Postbox import SwiftSignalKit import SyncCore +func _internal_enqueueOutgoingMessageWithChatContextResult(account: Account, to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, replyToMessageId: MessageId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> Bool { + guard let message = outgoingMessageWithChatContextResult(to: peerId, results: results, result: result, replyToMessageId: replyToMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId) else { + return false + } + let _ = enqueueMessages(account: account, peerId: peerId, messages: [message]).start() + return true +} -public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, hideVia: Bool = false, scheduleTime: Int32? = nil, correlationId: Int64? = nil) -> EnqueueMessage? { +private func outgoingMessageWithChatContextResult(to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, replyToMessageId: MessageId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> EnqueueMessage? { var attributes: [MessageAttribute] = [] attributes.append(OutgoingChatContextResultMessageAttribute(queryId: result.queryId, id: result.id, hideVia: hideVia)) if !hideVia { @@ -13,6 +20,9 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha if let scheduleTime = scheduleTime { attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: scheduleTime)) } + if silentPosting { + attributes.append(NotificationInfoMessageAttribute(flags: .muted)) + } switch result.message { case let .auto(caption, entities, replyMarkup): if let entities = entities { @@ -32,19 +42,19 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha return true } if let media: Media = internalReference.file ?? internalReference.image { - return .message(text: caption, attributes: filteredAttributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: filteredAttributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else { - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else if let file = internalReference.file, internalReference.type == "gif" { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else if let image = internalReference.image { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: image), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else if let file = internalReference.file { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { return nil } @@ -56,9 +66,9 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha let thumbnailResource = thumbnail.resource let imageDimensions = thumbnail.dimensions ?? PixelDimensions(width: 128, height: 128) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: [TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: tmpImage), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else if externalReference.type == "document" || externalReference.type == "gif" || externalReference.type == "audio" || externalReference.type == "voice" { var videoThumbnails: [TelegramMediaFile.VideoThumbnail] = [] @@ -118,9 +128,9 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha } let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: nil, mimeType: externalReference.content?.mimeType ?? "application/binary", size: nil, attributes: fileAttributes) - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } case let .text(text, entities, disableUrlPreview, replyMarkup): @@ -130,21 +140,21 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .mapLocation(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .contact(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .invoice(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } diff --git a/submodules/TelegramCore/Sources/PeerLiveLocationsContext.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/PeerLiveLocationsContext.swift similarity index 88% rename from submodules/TelegramCore/Sources/PeerLiveLocationsContext.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/PeerLiveLocationsContext.swift index 3609e85ced..04be82ce54 100644 --- a/submodules/TelegramCore/Sources/PeerLiveLocationsContext.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/PeerLiveLocationsContext.swift @@ -2,10 +2,9 @@ import Foundation import Postbox import SwiftSignalKit import TelegramApi - import SyncCore -public func topPeerActiveLiveLocationMessages(viewTracker: AccountViewTracker, accountPeerId: PeerId, peerId: PeerId) -> Signal<(Peer?, [Message]), NoError> { +func _internal_topPeerActiveLiveLocationMessages(viewTracker: AccountViewTracker, accountPeerId: PeerId, peerId: PeerId) -> Signal<(Peer?, [Message]), NoError> { return viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 50, fixedCombinedReadStates: nil, tagMask: .liveLocation, orderStatistics: [], additionalData: [.peer(accountPeerId)]) |> map { (view, _, _) -> (Peer?, [Message]) in var accountPeer: Peer? diff --git a/submodules/TelegramCore/Sources/RecentlyUsedHashtags.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RecentlyUsedHashtags.swift similarity index 90% rename from submodules/TelegramCore/Sources/RecentlyUsedHashtags.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/RecentlyUsedHashtags.swift index 0bd04d68a4..9c313facbe 100644 --- a/submodules/TelegramCore/Sources/RecentlyUsedHashtags.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RecentlyUsedHashtags.swift @@ -30,7 +30,7 @@ func addRecentlyUsedHashtag(transaction: Transaction, string: String) { } } -public func removeRecentlyUsedHashtag(postbox: Postbox, string: String) -> Signal { +func _internal_removeRecentlyUsedHashtag(postbox: Postbox, string: String) -> Signal { return postbox.transaction { transaction -> Void in if let itemId = RecentHashtagItemId(string) { transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlyUsedHashtags, itemId: itemId.rawValue) @@ -38,7 +38,7 @@ public func removeRecentlyUsedHashtag(postbox: Postbox, string: String) -> Signa } } -public func recentlyUsedHashtags(postbox: Postbox) -> Signal<[String], NoError> { +func _internal_recentlyUsedHashtags(postbox: Postbox) -> Signal<[String], NoError> { return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlyUsedHashtags)]) |> mapToSignal { view -> Signal<[String], NoError> in return postbox.transaction { transaction -> [String] in diff --git a/submodules/TelegramCore/Sources/RequestChatContextResults.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift similarity index 95% rename from submodules/TelegramCore/Sources/RequestChatContextResults.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift index 20ef3a4b63..39f0488710 100644 --- a/submodules/TelegramCore/Sources/RequestChatContextResults.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestChatContextResults.swift @@ -51,7 +51,7 @@ public struct RequestChatContextResultsResult { } } -public func requestChatContextResults(account: Account, botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String, incompleteResults: Bool = false, staleCachedResults: Bool = false) -> Signal { +func _internal_requestChatContextResults(account: Account, botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String, incompleteResults: Bool = false, staleCachedResults: Bool = false) -> Signal { return account.postbox.transaction { transaction -> (bot: Peer, peer: Peer)? in if let bot = transaction.getPeer(botId), let peer = transaction.getPeer(peerId) { return (bot, peer) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index c11b8dca37..6dc415b280 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -151,5 +151,25 @@ public extension TelegramEngine { public func exportMessageLink(peerId: PeerId, messageId: MessageId, isThread: Bool = false) -> Signal { return _internal_exportMessageLink(account: self.account, peerId: peerId, messageId: messageId, isThread: isThread) } + + public func enqueueOutgoingMessageWithChatContextResult(to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, replyToMessageId: MessageId? = nil, hideVia: Bool = false, silentPosting: Bool = false, scheduleTime: Int32? = nil, correlationId: Int64? = nil) -> Bool { + return _internal_enqueueOutgoingMessageWithChatContextResult(account: self.account, to: peerId, results: results, result: result, replyToMessageId: replyToMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId) + } + + public func requestChatContextResults(botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String, incompleteResults: Bool = false, staleCachedResults: Bool = false) -> Signal { + return _internal_requestChatContextResults(account: self.account, botId: botId, peerId: peerId, query: query, location: location, offset: offset, incompleteResults: incompleteResults, staleCachedResults: staleCachedResults) + } + + public func removeRecentlyUsedHashtag(string: String) -> Signal { + return _internal_removeRecentlyUsedHashtag(postbox: self.account.postbox, string: string) + } + + public func recentlyUsedHashtags() -> Signal<[String], NoError> { + return _internal_recentlyUsedHashtags(postbox: self.account.postbox) + } + + public func topPeerActiveLiveLocationMessages(peerId: PeerId) -> Signal<(Peer?, [Message]), NoError> { + return _internal_topPeerActiveLiveLocationMessages(viewTracker: self.account.viewTracker, accountPeerId: self.account.peerId, peerId: peerId) + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/PeerManagement/TelegramEnginePeerManagement.swift b/submodules/TelegramCore/Sources/TelegramEngine/PeerManagement/TelegramEnginePeerManagement.swift deleted file mode 100644 index 112d788c1d..0000000000 --- a/submodules/TelegramCore/Sources/TelegramEngine/PeerManagement/TelegramEnginePeerManagement.swift +++ /dev/null @@ -1,13 +0,0 @@ -import SwiftSignalKit - -public extension TelegramEngine { - final class PeerManagement { - private let account: Account - - init(account: Account) { - self.account = account - } - - - } -} diff --git a/submodules/TelegramCore/Sources/ChatListFiltering.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift similarity index 97% rename from submodules/TelegramCore/Sources/ChatListFiltering.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift index c2061ac38b..d94bb2b995 100644 --- a/submodules/TelegramCore/Sources/ChatListFiltering.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift @@ -367,7 +367,7 @@ public enum RequestUpdateChatListFilterError { case generic } -public func requestUpdateChatListFilter(postbox: Postbox, network: Network, id: Int32, filter: ChatListFilter?) -> Signal { +func _internal_requestUpdateChatListFilter(postbox: Postbox, network: Network, id: Int32, filter: ChatListFilter?) -> Signal { return postbox.transaction { transaction -> Api.DialogFilter? in return filter?.apiFilter(transaction: transaction) } @@ -391,7 +391,7 @@ public enum RequestUpdateChatListFilterOrderError { case generic } -public func requestUpdateChatListFilterOrder(account: Account, ids: [Int32]) -> Signal { +func _internal_requestUpdateChatListFilterOrder(account: Account, ids: [Int32]) -> Signal { return account.network.request(Api.functions.messages.updateDialogFiltersOrder(order: ids)) |> mapError { _ -> RequestUpdateChatListFilterOrderError in return .generic @@ -781,7 +781,7 @@ struct ChatListFiltersState: PreferencesEntry, Equatable { } } -public func generateNewChatListFilterId(filters: [ChatListFilter]) -> Int32 { +func _internal_generateNewChatListFilterId(filters: [ChatListFilter]) -> Int32 { while true { let id = Int32(2 + arc4random_uniform(255 - 2)) if !filters.contains(where: { $0.id == id }) { @@ -790,7 +790,7 @@ public func generateNewChatListFilterId(filters: [ChatListFilter]) -> Int32 { } } -public func updateChatListFiltersInteractively(postbox: Postbox, _ f: @escaping ([ChatListFilter]) -> [ChatListFilter]) -> Signal<[ChatListFilter], NoError> { +func _internal_updateChatListFiltersInteractively(postbox: Postbox, _ f: @escaping ([ChatListFilter]) -> [ChatListFilter]) -> Signal<[ChatListFilter], NoError> { return postbox.transaction { transaction -> [ChatListFilter] in var updated: [ChatListFilter] = [] var hasUpdates = false @@ -811,7 +811,7 @@ public func updateChatListFiltersInteractively(postbox: Postbox, _ f: @escaping } } -public func updateChatListFiltersInteractively(transaction: Transaction, _ f: ([ChatListFilter]) -> [ChatListFilter]) { +func _internal_updateChatListFiltersInteractively(transaction: Transaction, _ f: ([ChatListFilter]) -> [ChatListFilter]) { var hasUpdates = false transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFilters, { entry in var state = entry as? ChatListFiltersState ?? ChatListFiltersState.default @@ -828,7 +828,7 @@ public func updateChatListFiltersInteractively(transaction: Transaction, _ f: ([ } -public func updatedChatListFilters(postbox: Postbox) -> Signal<[ChatListFilter], NoError> { +func _internal_updatedChatListFilters(postbox: Postbox) -> Signal<[ChatListFilter], NoError> { return postbox.preferencesView(keys: [PreferencesKeys.chatListFilters]) |> map { preferences -> [ChatListFilter] in let filtersState = preferences.values[PreferencesKeys.chatListFilters] as? ChatListFiltersState ?? ChatListFiltersState.default @@ -837,7 +837,7 @@ public func updatedChatListFilters(postbox: Postbox) -> Signal<[ChatListFilter], |> distinctUntilChanged } -public func updatedChatListFiltersInfo(postbox: Postbox) -> Signal<(filters: [ChatListFilter], synchronized: Bool), NoError> { +func _internal_updatedChatListFiltersInfo(postbox: Postbox) -> Signal<(filters: [ChatListFilter], synchronized: Bool), NoError> { return postbox.preferencesView(keys: [PreferencesKeys.chatListFilters]) |> map { preferences -> (filters: [ChatListFilter], synchronized: Bool) in let filtersState = preferences.values[PreferencesKeys.chatListFilters] as? ChatListFiltersState ?? ChatListFiltersState.default @@ -854,7 +854,7 @@ public func updatedChatListFiltersInfo(postbox: Postbox) -> Signal<(filters: [Ch }) } -public func currentChatListFilters(postbox: Postbox) -> Signal<[ChatListFilter], NoError> { +func _internal_currentChatListFilters(postbox: Postbox) -> Signal<[ChatListFilter], NoError> { return postbox.transaction { transaction -> [ChatListFilter] in let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default return settings.filters @@ -941,7 +941,7 @@ public struct ChatListFiltersFeaturedState: PreferencesEntry, Equatable { } } -public func markChatListFeaturedFiltersAsSeen(postbox: Postbox) -> Signal { +func _internal_markChatListFeaturedFiltersAsSeen(postbox: Postbox) -> Signal { return postbox.transaction { transaction -> Void in transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFiltersFeaturedState, { entry in guard var state = entry as? ChatListFiltersFeaturedState else { @@ -954,7 +954,7 @@ public func markChatListFeaturedFiltersAsSeen(postbox: Postbox) -> Signal ignoreValues } -public func unmarkChatListFeaturedFiltersAsSeen(transaction: Transaction) { +func _internal_unmarkChatListFeaturedFiltersAsSeen(transaction: Transaction) { transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFiltersFeaturedState, { entry in guard var state = entry as? ChatListFiltersFeaturedState else { return entry @@ -964,7 +964,7 @@ public func unmarkChatListFeaturedFiltersAsSeen(transaction: Transaction) { }) } -public func updateChatListFeaturedFilters(postbox: Postbox, network: Network) -> Signal { +func _internal_updateChatListFeaturedFilters(postbox: Postbox, network: Network) -> Signal { return network.request(Api.functions.messages.getSuggestedDialogFilters()) |> `catch` { _ -> Signal<[Api.DialogFilterSuggested], NoError> in return .single([]) @@ -1111,7 +1111,7 @@ func requestChatListFiltersSync(transaction: Transaction) { func managedChatListFilters(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal { return Signal { _ in - let updateFeaturedDisposable = updateChatListFeaturedFilters(postbox: postbox, network: network).start() + let updateFeaturedDisposable = _internal_updateChatListFeaturedFilters(postbox: postbox, network: network).start() let _ = postbox.transaction({ transaction in requestChatListFiltersSync(transaction: transaction) }).start() @@ -1218,7 +1218,7 @@ private func synchronizeChatListFilters(transaction: Transaction, accountPeerId: if !mergedFilterIds.contains(where: { $0 == filter.id }) { deleteSignals = deleteSignals |> then( - requestUpdateChatListFilter(postbox: postbox, network: network, id: filter.id, filter: nil) + _internal_requestUpdateChatListFilter(postbox: postbox, network: network, id: filter.id, filter: nil) |> `catch` { _ -> Signal in return .complete() } @@ -1238,7 +1238,7 @@ private func synchronizeChatListFilters(transaction: Transaction, accountPeerId: if updated { addSignals = addSignals |> then( - requestUpdateChatListFilter(postbox: postbox, network: network, id: filter.id, filter: filter) + _internal_requestUpdateChatListFilter(postbox: postbox, network: network, id: filter.id, filter: filter) |> `catch` { _ -> Signal in return .complete() } diff --git a/submodules/TelegramCore/Sources/CheckPeerChatServiceActions.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CheckPeerChatServiceActions.swift similarity index 87% rename from submodules/TelegramCore/Sources/CheckPeerChatServiceActions.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/CheckPeerChatServiceActions.swift index d72f1b809a..01b5acd4ce 100644 --- a/submodules/TelegramCore/Sources/CheckPeerChatServiceActions.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CheckPeerChatServiceActions.swift @@ -4,7 +4,7 @@ import SwiftSignalKit import SyncCore -public func checkPeerChatServiceActions(postbox: Postbox, peerId: PeerId) -> Signal { +func _internal_checkPeerChatServiceActions(postbox: Postbox, peerId: PeerId) -> Signal { return postbox.transaction { transaction -> Void in transaction.applyMarkUnread(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, value: false, interactive: true) diff --git a/submodules/TelegramCore/Sources/InvitationLinks.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift similarity index 95% rename from submodules/TelegramCore/Sources/InvitationLinks.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift index 32e6a8cbf4..840afb6ce2 100644 --- a/submodules/TelegramCore/Sources/InvitationLinks.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift @@ -3,11 +3,9 @@ import Postbox import SwiftSignalKit import TelegramApi import MtProtoKit - import SyncCore - -public func revokePersistentPeerExportedInvitation(account: Account, peerId: PeerId) -> Signal { +func _internal_revokePersistentPeerExportedInvitation(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { let flags: Int32 = (1 << 2) @@ -58,7 +56,7 @@ public enum CreatePeerExportedInvitationError { case generic } -public func createPeerExportedInvitation(account: Account, peerId: PeerId, expireDate: Int32?, usageLimit: Int32?) -> Signal { +func _internal_createPeerExportedInvitation(account: Account, peerId: PeerId, expireDate: Int32?, usageLimit: Int32?) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { var flags: Int32 = 0 @@ -85,7 +83,7 @@ public enum EditPeerExportedInvitationError { case generic } -public func editPeerExportedInvitation(account: Account, peerId: PeerId, link: String, expireDate: Int32?, usageLimit: Int32?) -> Signal { +func _internal_editPeerExportedInvitation(account: Account, peerId: PeerId, link: String, expireDate: Int32?, usageLimit: Int32?) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { var flags: Int32 = 0 @@ -131,7 +129,7 @@ public enum RevokeExportedInvitationResult { case replace(ExportedInvitation, ExportedInvitation) } -public func revokePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal { +func _internal_revokePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { let flags: Int32 = (1 << 2) @@ -197,7 +195,7 @@ public struct ExportedInvitations : Equatable { public let totalCount: Int32 } -public func peerExportedInvitations(account: Account, peerId: PeerId, revoked: Bool, adminId: PeerId? = nil, offsetLink: ExportedInvitation? = nil) -> Signal { +func _internal_peerExportedInvitations(account: Account, peerId: PeerId, revoked: Bool, adminId: PeerId? = nil, offsetLink: ExportedInvitation? = nil) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let adminPeer = transaction.getPeer(adminId ?? account.peerId), let adminId = apiInputUser(adminPeer) { var flags: Int32 = 0 @@ -244,7 +242,7 @@ public enum DeletePeerExportedInvitationError { case generic } -public func deletePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal { +func _internal_deletePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { return account.network.request(Api.functions.messages.deleteExportedChatInvite(peer: inputPeer, link: link)) @@ -258,7 +256,7 @@ public func deletePeerExportedInvitation(account: Account, peerId: PeerId, link: |> switchToLatest } -public func deleteAllRevokedPeerExportedInvitations(account: Account, peerId: PeerId, adminId: PeerId) -> Signal { +func _internal_deleteAllRevokedPeerExportedInvitations(account: Account, peerId: PeerId, adminId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let adminPeer = transaction.getPeer(adminId), let inputAdminId = apiInputUser(adminPeer) { return account.network.request(Api.functions.messages.deleteRevokedExportedChatInvites(peer: inputPeer, adminId: inputAdminId)) @@ -304,7 +302,7 @@ final class CachedPeerExportedInvitations: PostboxCoding { let canLoadMore: Bool let count: Int32 - public static func key(peerId: PeerId, revoked: Bool) -> ValueBoxKey { + static func key(peerId: PeerId, revoked: Bool) -> ValueBoxKey { let key = ValueBoxKey(length: 8 + 4) key.setInt64(0, value: peerId.toInt64()) key.setInt32(8, value: revoked ? 1 : 0) @@ -317,13 +315,13 @@ final class CachedPeerExportedInvitations: PostboxCoding { self.count = count } - public init(decoder: PostboxDecoder) { + init(decoder: PostboxDecoder) { self.invitations = decoder.decodeObjectArrayForKey("invitations") self.canLoadMore = decoder.decodeBoolForKey("canLoadMore", orElse: false) self.count = decoder.decodeInt32ForKey("count", orElse: 0) } - public func encode(_ encoder: PostboxEncoder) { + func encode(_ encoder: PostboxEncoder) { encoder.encodeObjectArray(self.invitations, forKey: "invitations") encoder.encodeBool(self.canLoadMore, forKey: "canLoadMore") encoder.encodeInt32(self.count, forKey: "count") @@ -494,7 +492,7 @@ private final class PeerExportedInvitationsContextImpl { self.updateState() } - public func add(_ invite: ExportedInvitation) { + func add(_ invite: ExportedInvitation) { var results = self.results results.removeAll(where: { $0.link == invite.link}) results.insert(invite, at: 0) @@ -503,7 +501,7 @@ private final class PeerExportedInvitationsContextImpl { self.updateCache() } - public func update(_ invite: ExportedInvitation) { + func update(_ invite: ExportedInvitation) { var results = self.results if let index = self.results.firstIndex(where: { $0.link == invite.link }) { results[index] = invite @@ -513,7 +511,7 @@ private final class PeerExportedInvitationsContextImpl { self.updateCache() } - public func remove(_ invite: ExportedInvitation) { + func remove(_ invite: ExportedInvitation) { var results = self.results results.removeAll(where: { $0.link == invite.link}) self.results = results @@ -521,7 +519,7 @@ private final class PeerExportedInvitationsContextImpl { self.updateCache() } - public func clear() { + func clear() { self.results = [] self.count = 0 self.updateState() @@ -564,7 +562,7 @@ public final class PeerExportedInvitationsContext { } } - public init(account: Account, peerId: PeerId, adminId: PeerId?, revoked: Bool, forceUpdate: Bool) { + init(account: Account, peerId: PeerId, adminId: PeerId?, revoked: Bool, forceUpdate: Bool) { let queue = self.queue self.impl = QueueLocalObject(queue: queue, generate: { return PeerExportedInvitationsContextImpl(queue: queue, account: account, peerId: peerId, adminId: adminId, revoked: revoked, forceUpdate: forceUpdate) @@ -629,7 +627,7 @@ final class CachedPeerInvitationImporters: PostboxCoding { let dates: [PeerId: Int32] let count: Int32 - public static func key(peerId: PeerId, link: String) -> ValueBoxKey { + static func key(peerId: PeerId, link: String) -> ValueBoxKey { let key = ValueBoxKey(length: 8 + 4) key.setInt64(0, value: peerId.toInt64()) key.setInt32(8, value: Int32(HashFunctions.murMurHash32(link))) @@ -644,13 +642,13 @@ final class CachedPeerInvitationImporters: PostboxCoding { self.count = count } - public init(peerIds: [PeerId], dates: [PeerId: Int32], count: Int32) { + init(peerIds: [PeerId], dates: [PeerId: Int32], count: Int32) { self.peerIds = peerIds self.dates = dates self.count = count } - public init(decoder: PostboxDecoder) { + init(decoder: PostboxDecoder) { self.peerIds = decoder.decodeInt64ArrayForKey("peerIds").map(PeerId.init) var dates: [PeerId: Int32] = [:] @@ -666,7 +664,7 @@ final class CachedPeerInvitationImporters: PostboxCoding { self.count = decoder.decodeInt32ForKey("count", orElse: 0) } - public func encode(_ encoder: PostboxEncoder) { + func encode(_ encoder: PostboxEncoder) { encoder.encodeInt64Array(self.peerIds.map { $0.toInt64() }, forKey: "peerIds") var dates: [Int32] = [] @@ -859,7 +857,7 @@ public final class PeerInvitationImportersContext { } } - public init(account: Account, peerId: PeerId, invite: ExportedInvitation) { + init(account: Account, peerId: PeerId, invite: ExportedInvitation) { let queue = self.queue self.impl = QueueLocalObject(queue: queue, generate: { return PeerInvitationImportersContextImpl(queue: queue, account: account, peerId: peerId, invite: invite) @@ -879,7 +877,7 @@ public struct ExportedInvitationCreator : Equatable { public let revokedCount: Int32 } -public func peerExportedInvitationsCreators(account: Account, peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> { +func _internal_peerExportedInvitationsCreators(account: Account, peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> { return account.postbox.transaction { transaction -> Signal<[ExportedInvitationCreator], NoError> in if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { var isCreator = false diff --git a/submodules/TelegramCore/Sources/JoinLink.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift similarity index 94% rename from submodules/TelegramCore/Sources/JoinLink.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift index cd8fbc8486..fccad10f9c 100644 --- a/submodules/TelegramCore/Sources/JoinLink.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift @@ -29,7 +29,7 @@ public enum ExternalJoiningChatState { case peek(PeerId, Int32) } -public func joinChatInteractively(with hash: String, account: Account) -> Signal { +func _internal_joinChatInteractively(with hash: String, account: Account) -> Signal { return account.network.request(Api.functions.messages.importChatInvite(hash: hash)) |> mapError { error -> JoinLinkError in switch error.errorDescription { @@ -59,7 +59,7 @@ public func joinChatInteractively(with hash: String, account: Account) -> Signal } } -public func joinLinkInformation(_ hash: String, account: Account) -> Signal { +func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal { return account.network.request(Api.functions.messages.checkChatInvite(hash: hash)) |> map(Optional.init) |> `catch` { _ -> Signal in diff --git a/submodules/TelegramCore/Sources/NotificationExceptionsList.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationExceptionsList.swift similarity index 96% rename from submodules/TelegramCore/Sources/NotificationExceptionsList.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationExceptionsList.swift index 1210a78445..1c43e7a60f 100644 --- a/submodules/TelegramCore/Sources/NotificationExceptionsList.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/NotificationExceptionsList.swift @@ -19,7 +19,7 @@ public final class NotificationExceptionsList: Equatable { } } -public func notificationExceptionsList(postbox: Postbox, network: Network) -> Signal { +func _internal_notificationExceptionsList(postbox: Postbox, network: Network) -> Signal { return network.request(Api.functions.account.getNotifyExceptions(flags: 1 << 1, peer: nil)) |> retryRequest |> mapToSignal { result -> Signal in diff --git a/submodules/TelegramCore/Sources/PeerPhotoUpdater.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift similarity index 89% rename from submodules/TelegramCore/Sources/PeerPhotoUpdater.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift index a5eb6c5ccf..8a2a04e011 100644 --- a/submodules/TelegramCore/Sources/PeerPhotoUpdater.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift @@ -15,8 +15,8 @@ public enum UploadPeerPhotoError { case generic } -public func updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) +func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } public struct UploadedPeerPhotoData { @@ -37,7 +37,7 @@ enum UploadedPeerPhotoDataContent { case error } -public func uploadedPeerPhoto(postbox: Postbox, network: Network, resource: MediaResource) -> Signal { +func _internal_uploadedPeerPhoto(postbox: Postbox, network: Network, resource: MediaResource) -> Signal { return multipartUpload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image), hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: false) |> map { result -> UploadedPeerPhotoData in return UploadedPeerPhotoData(resource: resource, content: .result(result)) @@ -47,7 +47,7 @@ public func uploadedPeerPhoto(postbox: Postbox, network: Network, resource: Medi } } -public func uploadedPeerVideo(postbox: Postbox, network: Network, messageMediaPreuploadManager: MessageMediaPreuploadManager?, resource: MediaResource) -> Signal { +func _internal_uploadedPeerVideo(postbox: Postbox, network: Network, messageMediaPreuploadManager: MessageMediaPreuploadManager?, resource: MediaResource) -> Signal { if let messageMediaPreuploadManager = messageMediaPreuploadManager { return messageMediaPreuploadManager.upload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .video), hintFileSize: nil, hintFileIsLarge: false) |> map { result -> UploadedPeerPhotoData in @@ -67,11 +67,11 @@ public func uploadedPeerVideo(postbox: Postbox, network: Network, messageMediaPr } } -public func updatePeerPhoto(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return updatePeerPhotoInternal(postbox: postbox, network: network, stateManager: stateManager, accountPeerId: accountPeerId, peer: postbox.loadedPeerWithId(peerId), photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) +func _internal_updatePeerPhoto(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updatePeerPhotoInternal(postbox: postbox, network: network, stateManager: stateManager, accountPeerId: accountPeerId, peer: postbox.loadedPeerWithId(peerId), photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } -public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peer: Signal, photo: Signal?, video: Signal?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { +func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peer: Signal, photo: Signal?, video: Signal?, videoStartTimestamp: Double?, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { return peer |> mapError { _ in return .generic } |> mapToSignal { peer -> Signal in @@ -260,7 +260,7 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan } |> mapToSignal { result, resource, videoResource -> Signal in if case .complete = result { - return fetchAndUpdateCachedPeerData(accountPeerId: accountPeerId, peerId: peer.id, network: network, postbox: postbox) + return _internal_fetchAndUpdateCachedPeerData(accountPeerId: accountPeerId, peerId: peer.id, network: network, postbox: postbox) |> castError(UploadPeerPhotoError.self) |> mapToSignal { status -> Signal in return postbox.transaction { transaction in @@ -335,7 +335,7 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan } } -public func updatePeerPhotoExisting(network: Network, reference: TelegramMediaImageReference) -> Signal { +func _internal_updatePeerPhotoExisting(network: Network, reference: TelegramMediaImageReference) -> Signal { switch reference { case let .cloud(imageId, accessHash, fileReference): return network.request(Api.functions.photos.updateProfilePhoto(id: .inputPhoto(id: imageId, accessHash: accessHash, fileReference: Buffer(data: fileReference)))) @@ -352,7 +352,7 @@ public func updatePeerPhotoExisting(network: Network, reference: TelegramMediaIm } } -public func removeAccountPhoto(network: Network, reference: TelegramMediaImageReference?) -> Signal { +func _internal_removeAccountPhoto(network: Network, reference: TelegramMediaImageReference?) -> Signal { if let reference = reference { switch reference { case let .cloud(imageId, accessHash, fileReference): diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RemovePeerChat.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RemovePeerChat.swift index f5c31ba638..3858dcf79e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RemovePeerChat.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RemovePeerChat.swift @@ -34,7 +34,7 @@ func _internal_removePeerChat(account: Account, transaction: Transaction, mediaB } }) } - updateChatListFiltersInteractively(transaction: transaction, { filters in + _internal_updateChatListFiltersInteractively(transaction: transaction, { filters in var filters = filters for i in 0 ..< filters.count { if filters[i].data.includePeers.peers.contains(peerId) { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 093d4af9f3..00f3ddddb6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -1,3 +1,4 @@ +import Foundation import SwiftSignalKit import Postbox import SyncCore @@ -327,5 +328,136 @@ public extension TelegramEngine { public func removeRecentlyUsedInlineBot(peerId: PeerId) -> Signal { return _internal_removeRecentlyUsedInlineBot(account: self.account, peerId: peerId) } + + public func uploadedPeerPhoto(resource: MediaResource) -> Signal { + return _internal_uploadedPeerPhoto(postbox: self.account.postbox, network: self.account.network, resource: resource) + } + + public func uploadedPeerVideo(resource: MediaResource) -> Signal { + return _internal_uploadedPeerVideo(postbox: self.account.postbox, network: self.account.network, messageMediaPreuploadManager: self.account.messageMediaPreuploadManager, resource: resource) + } + + public func updatePeerPhoto(peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { + return _internal_updatePeerPhoto(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, accountPeerId: self.account.peerId, peerId: peerId, photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + } + + public func requestUpdateChatListFilter(id: Int32, filter: ChatListFilter?) -> Signal { + return _internal_requestUpdateChatListFilter(postbox: self.account.postbox, network: self.account.network, id: id, filter: filter) + } + + public func requestUpdateChatListFilterOrder(ids: [Int32]) -> Signal { + return _internal_requestUpdateChatListFilterOrder(account: self.account, ids: ids) + } + + public func generateNewChatListFilterId(filters: [ChatListFilter]) -> Int32 { + return _internal_generateNewChatListFilterId(filters: filters) + } + + public func updateChatListFiltersInteractively(_ f: @escaping ([ChatListFilter]) -> [ChatListFilter]) -> Signal<[ChatListFilter], NoError> { + return _internal_updateChatListFiltersInteractively(postbox: self.account.postbox, f) + } + + public func updatedChatListFilters() -> Signal<[ChatListFilter], NoError> { + return _internal_updatedChatListFilters(postbox: self.account.postbox) + } + + public func updatedChatListFiltersInfo() -> Signal<(filters: [ChatListFilter], synchronized: Bool), NoError> { + return _internal_updatedChatListFiltersInfo(postbox: self.account.postbox) + } + + public func currentChatListFilters() -> Signal<[ChatListFilter], NoError> { + return _internal_currentChatListFilters(postbox: self.account.postbox) + } + + public func markChatListFeaturedFiltersAsSeen() -> Signal { + return _internal_markChatListFeaturedFiltersAsSeen(postbox: self.account.postbox) + } + + public func updateChatListFeaturedFilters() -> Signal { + return _internal_updateChatListFeaturedFilters(postbox: self.account.postbox, network: self.account.network) + } + + public func unmarkChatListFeaturedFiltersAsSeen() -> Signal { + return self.account.postbox.transaction { transaction in + _internal_unmarkChatListFeaturedFiltersAsSeen(transaction: transaction) + } + |> ignoreValues + } + + public func checkPeerChatServiceActions(peerId: PeerId) -> Signal { + return _internal_checkPeerChatServiceActions(postbox: self.account.postbox, peerId: peerId) + } + + public func createPeerExportedInvitation(peerId: PeerId, expireDate: Int32?, usageLimit: Int32?) -> Signal { + return _internal_createPeerExportedInvitation(account: self.account, peerId: peerId, expireDate: expireDate, usageLimit: usageLimit) + } + + public func editPeerExportedInvitation(peerId: PeerId, link: String, expireDate: Int32?, usageLimit: Int32?) -> Signal { + return _internal_editPeerExportedInvitation(account: self.account, peerId: peerId, link: link, expireDate: expireDate, usageLimit: usageLimit) + } + + public func revokePeerExportedInvitation(peerId: PeerId, link: String) -> Signal { + return _internal_revokePeerExportedInvitation(account: self.account, peerId: peerId, link: link) + } + + public func deletePeerExportedInvitation(peerId: PeerId, link: String) -> Signal { + return _internal_deletePeerExportedInvitation(account: self.account, peerId: peerId, link: link) + } + + public func deleteAllRevokedPeerExportedInvitations(peerId: PeerId, adminId: PeerId) -> Signal { + return _internal_deleteAllRevokedPeerExportedInvitations(account: self.account, peerId: peerId, adminId: adminId) + } + + public func peerExportedInvitationsCreators(peerId: PeerId) -> Signal<[ExportedInvitationCreator], NoError> { + return _internal_peerExportedInvitationsCreators(account: self.account, peerId: peerId) + } + + public func peerExportedInvitations(peerId: PeerId, adminId: PeerId?, revoked: Bool, forceUpdate: Bool) -> PeerExportedInvitationsContext { + return PeerExportedInvitationsContext(account: self.account, peerId: peerId, adminId: adminId, revoked: revoked, forceUpdate: forceUpdate) + } + + public func peerInvitationImporters(peerId: PeerId, invite: ExportedInvitation) -> PeerInvitationImportersContext { + return PeerInvitationImportersContext(account: self.account, peerId: peerId, invite: invite) + } + + public func notificationExceptionsList() -> Signal { + return _internal_notificationExceptionsList(postbox: self.account.postbox, network: self.account.network) + } + + public func fetchAndUpdateCachedPeerData(peerId: PeerId) -> Signal { + return _internal_fetchAndUpdateCachedPeerData(accountPeerId: self.account.peerId, peerId: peerId, network: self.account.network, postbox: self.account.postbox) + } + + public func toggleItemPinned(location: TogglePeerChatPinnedLocation, itemId: PinnedItemId) -> Signal { + return _internal_toggleItemPinned(postbox: self.account.postbox, location: location, itemId: itemId) + } + + public func getPinnedItemIds(location: TogglePeerChatPinnedLocation) -> Signal<[PinnedItemId], NoError> { + return self.account.postbox.transaction { transaction -> [PinnedItemId] in + return _internal_getPinnedItemIds(transaction: transaction, location: location) + } + } + + public func reorderPinnedItemIds(location: TogglePeerChatPinnedLocation, itemIds: [PinnedItemId]) -> Signal { + return self.account.postbox.transaction { transaction -> Bool in + return _internal_reorderPinnedItemIds(transaction: transaction, location: location, itemIds: itemIds) + } + } + + public func joinChatInteractively(with hash: String) -> Signal { + return _internal_joinChatInteractively(with: hash, account: self.account) + } + + public func joinLinkInformation(_ hash: String) -> Signal { + return _internal_joinLinkInformation(hash, account: self.account) + } + + public func updatePeerTitle(peerId: PeerId, title: String) -> Signal { + return _internal_updatePeerTitle(account: self.account, peerId: peerId, title: title) + } + + public func updatePeerDescription(peerId: PeerId, description: String?) -> Signal { + return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description) + } } } diff --git a/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift similarity index 86% rename from submodules/TelegramCore/Sources/TogglePeerChatPinned.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift index ab3a0de39e..a49b9b445d 100644 --- a/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift @@ -14,7 +14,7 @@ public enum TogglePeerChatPinnedResult { case limitExceeded(Int) } -public func toggleItemPinned(postbox: Postbox, location: TogglePeerChatPinnedLocation, itemId: PinnedItemId) -> Signal { +func _internal_toggleItemPinned(postbox: Postbox, location: TogglePeerChatPinnedLocation, itemId: PinnedItemId) -> Signal { return postbox.transaction { transaction -> TogglePeerChatPinnedResult in switch location { case let .group(groupId): @@ -60,7 +60,7 @@ public func toggleItemPinned(postbox: Postbox, location: TogglePeerChatPinnedLoc } case let .filter(filterId): var result: TogglePeerChatPinnedResult = .done - updateChatListFiltersInteractively(transaction: transaction, { filters in + _internal_updateChatListFiltersInteractively(transaction: transaction, { filters in var filters = filters if let index = filters.firstIndex(where: { $0.id == filterId }) { switch itemId { @@ -81,13 +81,13 @@ public func toggleItemPinned(postbox: Postbox, location: TogglePeerChatPinnedLoc } } -public func getPinnedItemIds(transaction: Transaction, location: TogglePeerChatPinnedLocation) -> [PinnedItemId] { +func _internal_getPinnedItemIds(transaction: Transaction, location: TogglePeerChatPinnedLocation) -> [PinnedItemId] { switch location { case let .group(groupId): return transaction.getPinnedItemIds(groupId: groupId) case let .filter(filterId): var itemIds: [PinnedItemId] = [] - let _ = updateChatListFiltersInteractively(transaction: transaction, { filters in + let _ = _internal_updateChatListFiltersInteractively(transaction: transaction, { filters in if let index = filters.firstIndex(where: { $0.id == filterId }) { itemIds = filters[index].data.includePeers.pinnedPeers.map { peerId in return .peer(peerId) @@ -99,7 +99,7 @@ public func getPinnedItemIds(transaction: Transaction, location: TogglePeerChatP } } -public func reorderPinnedItemIds(transaction: Transaction, location: TogglePeerChatPinnedLocation, itemIds: [PinnedItemId]) -> Bool { +func _internal_reorderPinnedItemIds(transaction: Transaction, location: TogglePeerChatPinnedLocation, itemIds: [PinnedItemId]) -> Bool { switch location { case let .group(groupId): if transaction.getPinnedItemIds(groupId: groupId) != itemIds { @@ -111,7 +111,7 @@ public func reorderPinnedItemIds(transaction: Transaction, location: TogglePeerC } case let .filter(filterId): var result: Bool = false - updateChatListFiltersInteractively(transaction: transaction, { filters in + _internal_updateChatListFiltersInteractively(transaction: transaction, { filters in var filters = filters if let index = filters.firstIndex(where: { $0.id == filterId }) { let peerIds: [PeerId] = itemIds.map { itemId -> PeerId in diff --git a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift similarity index 99% rename from submodules/TelegramCore/Sources/UpdateCachedPeerData.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 56fb081c41..a4e378fbb8 100644 --- a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -124,7 +124,7 @@ func fetchAndUpdateSupplementalCachedPeerData(peerId rawPeerId: PeerId, network: } } -public func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerId, network: Network, postbox: Postbox) -> Signal { +func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerId, network: Network, postbox: Postbox) -> Signal { return postbox.combinedView(keys: [.basicPeer(rawPeerId)]) |> mapToSignal { views -> Signal in if accountPeerId == rawPeerId { diff --git a/submodules/TelegramCore/Sources/UpdatePeerInfo.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift similarity index 94% rename from submodules/TelegramCore/Sources/UpdatePeerInfo.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift index db1115c585..6eaba7a6ae 100644 --- a/submodules/TelegramCore/Sources/UpdatePeerInfo.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift @@ -10,7 +10,7 @@ public enum UpdatePeerTitleError { case generic } -public func updatePeerTitle(account: Account, peerId: PeerId, title: String) -> Signal { +func _internal_updatePeerTitle(account: Account, peerId: PeerId, title: String) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId) { if let peer = peer as? TelegramChannel, let inputChannel = apiInputChannel(peer) { @@ -58,7 +58,7 @@ public enum UpdatePeerDescriptionError { case generic } -public func updatePeerDescription(account: Account, peerId: PeerId, description: String?) -> Signal { +func _internal_updatePeerDescription(account: Account, peerId: PeerId, description: String?) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId) { if (peer is TelegramChannel || peer is TelegramGroup), let inputPeer = apiInputPeer(peer) { diff --git a/submodules/TelegramCore/Sources/DeepLinkInfo.swift b/submodules/TelegramCore/Sources/TelegramEngine/Resolve/DeepLinkInfo.swift similarity index 87% rename from submodules/TelegramCore/Sources/DeepLinkInfo.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Resolve/DeepLinkInfo.swift index c56272ad08..c517df7d6c 100644 --- a/submodules/TelegramCore/Sources/DeepLinkInfo.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Resolve/DeepLinkInfo.swift @@ -10,7 +10,7 @@ public struct DeepLinkInfo { public let updateApp: Bool } -public func getDeepLinkInfo(network: Network, path: String) -> Signal { +func _internal_getDeepLinkInfo(network: Network, path: String) -> Signal { return network.request(Api.functions.help.getDeepLinkInfo(path: path)) |> retryRequest |> map { value -> DeepLinkInfo? in switch value { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Resolve/TelegramEngineResolve.swift b/submodules/TelegramCore/Sources/TelegramEngine/Resolve/TelegramEngineResolve.swift new file mode 100644 index 0000000000..909b39dda8 --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/Resolve/TelegramEngineResolve.swift @@ -0,0 +1,16 @@ +import SwiftSignalKit +import Postbox + +public extension TelegramEngine { + final class Resolve { + private let account: Account + + init(account: Account) { + self.account = account + } + + public func getDeepLinkInfo(path: String) -> Signal { + return _internal_getDeepLinkInfo(network: self.account.network, path: path) + } + } +} diff --git a/submodules/TelegramCore/Sources/CollectCacheUsageStats.swift b/submodules/TelegramCore/Sources/TelegramEngine/Resources/CollectCacheUsageStats.swift similarity index 98% rename from submodules/TelegramCore/Sources/CollectCacheUsageStats.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Resources/CollectCacheUsageStats.swift index 1c3bc503de..f668e7e65f 100644 --- a/submodules/TelegramCore/Sources/CollectCacheUsageStats.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Resources/CollectCacheUsageStats.swift @@ -53,7 +53,7 @@ private final class CacheUsageStatsState { var upperBound: MessageIndex? } -public func collectCacheUsageStats(account: Account, peerId: PeerId? = nil, additionalCachePaths: [String] = [], logFilesPath: String? = nil) -> Signal { +func _internal_collectCacheUsageStats(account: Account, peerId: PeerId? = nil, additionalCachePaths: [String] = [], logFilesPath: String? = nil) -> Signal { var initialState = CacheUsageStatsState() if let peerId = peerId { initialState.lowerBound = MessageIndex.lowerBound(peerId: peerId) @@ -291,6 +291,6 @@ public func collectCacheUsageStats(account: Account, peerId: PeerId? = nil, addi } } -public func clearCachedMediaResources(account: Account, mediaResourceIds: Set) -> Signal { +func _internal_clearCachedMediaResources(account: Account, mediaResourceIds: Set) -> Signal { return account.postbox.mediaBox.removeCachedResources(mediaResourceIds) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift b/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift new file mode 100644 index 0000000000..726005cae6 --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift @@ -0,0 +1,24 @@ +import SwiftSignalKit +import Postbox + +public extension TelegramEngine { + final class Resources { + private let account: Account + + init(account: Account) { + self.account = account + } + + public func preUpload(id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete: (()->Void)? = nil) { + return self.account.messageMediaPreuploadManager.add(network: self.account.network, postbox: self.account.postbox, id: id, encrypt: encrypt, tag: tag, source: source, onComplete: onComplete) + } + + public func collectCacheUsageStats(peerId: PeerId? = nil, additionalCachePaths: [String] = [], logFilesPath: String? = nil) -> Signal { + return _internal_collectCacheUsageStats(account: self.account, peerId: peerId, additionalCachePaths: additionalCachePaths, logFilesPath: logFilesPath) + } + + public func clearCachedMediaResources(mediaResourceIds: Set) -> Signal { + return _internal_clearCachedMediaResources(account: self.account, mediaResourceIds: mediaResourceIds) + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift index 36c8520316..0f1464fbf8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift @@ -346,7 +346,7 @@ func _internal_searchGifs(account: Account, query: String, nextOffset: String = return account.postbox.loadedPeerWithId(peerId) } |> mapToSignal { peer -> Signal in - return requestChatContextResults(account: account, botId: peer.id, peerId: account.peerId, query: query, offset: nextOffset) + return _internal_requestChatContextResults(account: account, botId: peer.id, peerId: account.peerId, query: query, offset: nextOffset) |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index f6a5546d13..d4902923e1 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -36,10 +36,6 @@ public final class TelegramEngine { return Stickers(account: self.account) }() - public lazy var peerManagement: PeerManagement = { - return PeerManagement(account: self.account) - }() - public lazy var localization: Localization = { return Localization(account: self.account) }() @@ -63,6 +59,14 @@ public final class TelegramEngine { public lazy var contacts: Contacts = { return Contacts(account: self.account) }() + + public lazy var resources: Resources = { + return Resources(account: self.account) + }() + + public lazy var resolve: Resolve = { + return Resolve(account: self.account) + }() } public final class TelegramEngineUnauthorized { diff --git a/submodules/TelegramCore/Sources/MediaResourceNetworkStatsTag.swift b/submodules/TelegramCore/Sources/Utils/MediaResourceNetworkStatsTag.swift similarity index 81% rename from submodules/TelegramCore/Sources/MediaResourceNetworkStatsTag.swift rename to submodules/TelegramCore/Sources/Utils/MediaResourceNetworkStatsTag.swift index 8518603109..8d008623d3 100644 --- a/submodules/TelegramCore/Sources/MediaResourceNetworkStatsTag.swift +++ b/submodules/TelegramCore/Sources/Utils/MediaResourceNetworkStatsTag.swift @@ -9,7 +9,7 @@ public enum MediaResourceStatsCategory { case call } -public final class TelegramMediaResourceFetchTag: MediaResourceFetchTag { +final class TelegramMediaResourceFetchTag: MediaResourceFetchTag { public let statsCategory: MediaResourceStatsCategory public init(statsCategory: MediaResourceStatsCategory) { diff --git a/submodules/TelegramCore/Sources/UpdateMessageMedia.swift b/submodules/TelegramCore/Sources/Utils/UpdateMessageMedia.swift similarity index 100% rename from submodules/TelegramCore/Sources/UpdateMessageMedia.swift rename to submodules/TelegramCore/Sources/Utils/UpdateMessageMedia.swift diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/Contents.json new file mode 100644 index 0000000000..829a0300d8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "smallscreen_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/smallscreen_30.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/smallscreen_30.pdf new file mode 100644 index 0000000000..7c2c50ebb8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Collapse.imageset/smallscreen_30.pdf @@ -0,0 +1,161 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.334991 5.334999 cm +0.000000 0.000000 0.000000 scn +6.665000 19.330002 m +7.032269 19.330002 7.330000 19.032270 7.330000 18.665001 c +7.330000 15.865002 l +7.330000 15.837518 l +7.330000 15.837514 l +7.330000 15.837511 l +7.330009 15.300820 7.330016 14.857977 7.300543 14.497252 c +7.269935 14.122624 7.204253 13.778399 7.039532 13.455116 c +6.784030 12.953665 6.376337 12.545971 5.874885 12.290468 c +5.551602 12.125748 5.207376 12.060066 4.832748 12.029457 c +4.472024 11.999985 4.029181 11.999992 3.492490 12.000001 c +3.492487 12.000001 l +3.492483 12.000001 l +3.465000 12.000001 l +0.665000 12.000001 l +0.297731 12.000001 0.000000 12.297731 0.000000 12.665001 c +0.000000 13.032270 0.297731 13.330001 0.665000 13.330001 c +3.465000 13.330001 l +4.036026 13.330001 4.424301 13.330519 4.724444 13.355041 c +5.016824 13.378929 5.166537 13.422241 5.271077 13.475508 c +5.522274 13.603498 5.726503 13.807728 5.854494 14.058924 c +5.907760 14.163464 5.951072 14.313177 5.974960 14.605556 c +5.999483 14.905701 6.000000 15.293976 6.000000 15.865002 c +6.000000 18.665001 l +6.000000 19.032270 6.297730 19.330002 6.665000 19.330002 c +h +13.330000 18.665001 m +13.330000 19.032270 13.032269 19.330002 12.665000 19.330002 c +12.297730 19.330002 12.000000 19.032270 12.000000 18.665001 c +12.000000 15.865002 l +12.000000 15.837526 l +12.000000 15.837497 l +11.999991 15.300814 11.999985 14.857974 12.029457 14.497252 c +12.060065 14.122624 12.125747 13.778399 12.290467 13.455116 c +12.545970 12.953665 12.953663 12.545971 13.455115 12.290468 c +13.778399 12.125748 14.122623 12.060066 14.497252 12.029457 c +14.857978 11.999985 15.300823 11.999992 15.837517 12.000001 c +15.865000 12.000001 l +18.665001 12.000001 l +19.032270 12.000001 19.330002 12.297731 19.330002 12.665001 c +19.330002 13.032270 19.032270 13.330001 18.665001 13.330001 c +15.865000 13.330001 l +15.293975 13.330001 14.905700 13.330519 14.605556 13.355041 c +14.313176 13.378929 14.163464 13.422241 14.058923 13.475508 c +13.807726 13.603498 13.603498 13.807728 13.475507 14.058924 c +13.422240 14.163464 13.378928 14.313177 13.355040 14.605556 c +13.330517 14.905701 13.330000 15.293976 13.330000 15.865002 c +13.330000 18.665001 l +h +15.865000 7.330001 m +15.837525 7.330001 l +15.837497 7.330001 l +15.300811 7.330009 14.857973 7.330016 14.497252 7.300544 c +14.122623 7.269936 13.778399 7.204254 13.455115 7.039534 c +12.953663 6.784031 12.545970 6.376338 12.290467 5.874886 c +12.125747 5.551602 12.060065 5.207377 12.029457 4.832749 c +11.999985 4.472028 11.999991 4.029190 12.000000 3.492504 c +12.000000 3.492476 l +12.000000 3.465000 l +12.000000 0.665001 l +12.000000 0.297731 12.297730 0.000000 12.665000 0.000000 c +13.032269 0.000000 13.330000 0.297731 13.330000 0.665001 c +13.330000 3.465000 l +13.330000 4.036026 13.330517 4.424301 13.355040 4.724444 c +13.378928 5.016825 13.422240 5.166537 13.475507 5.271078 c +13.603498 5.522275 13.807726 5.726503 14.058923 5.854494 c +14.163464 5.907761 14.313176 5.951073 14.605556 5.974961 c +14.905700 5.999484 15.293975 6.000001 15.865000 6.000001 c +18.665001 6.000001 l +19.032270 6.000001 19.330002 6.297731 19.330002 6.665001 c +19.330002 7.032270 19.032270 7.330001 18.665001 7.330001 c +15.865000 7.330001 l +h +3.465000 6.000001 m +4.036026 6.000001 4.424301 5.999484 4.724444 5.974961 c +5.016824 5.951073 5.166537 5.907761 5.271077 5.854494 c +5.522274 5.726503 5.726503 5.522275 5.854494 5.271078 c +5.907760 5.166537 5.951072 5.016825 5.974960 4.724444 c +5.999483 4.424301 6.000000 4.036026 6.000000 3.465000 c +6.000000 0.665001 l +6.000000 0.297731 6.297730 0.000000 6.665000 0.000000 c +7.032269 0.000000 7.330000 0.297731 7.330000 0.665001 c +7.330000 3.465000 l +7.330000 3.492484 l +7.330009 4.029178 7.330016 4.472023 7.300543 4.832749 c +7.269935 5.207377 7.204253 5.551602 7.039532 5.874886 c +6.784030 6.376338 6.376337 6.784031 5.874885 7.039534 c +5.551602 7.204254 5.207376 7.269936 4.832748 7.300544 c +4.472027 7.330016 4.029188 7.330009 3.492504 7.330001 c +3.492474 7.330001 l +3.465000 7.330001 l +0.665000 7.330001 l +0.297731 7.330001 0.000000 7.032270 0.000000 6.665001 c +0.000000 6.297731 0.297731 6.000001 0.665000 6.000001 c +3.465000 6.000001 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 4194 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000004284 00000 n +0000004307 00000 n +0000004480 00000 n +0000004554 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4613 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/Contents.json new file mode 100644 index 0000000000..c5c261d24f --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "down_24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/down_24.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/down_24.pdf new file mode 100644 index 0000000000..074b2bc7ae --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Download.imageset/down_24.pdf @@ -0,0 +1,92 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.334999 3.334999 cm +0.000000 0.000000 0.000000 scn +8.665000 16.000002 m +4.613991 16.000002 1.330000 12.716011 1.330000 8.665002 c +1.330000 4.613994 4.613991 1.330002 8.665000 1.330002 c +12.716008 1.330002 16.000000 4.613994 16.000000 8.665002 c +16.000000 12.716011 12.716008 16.000002 8.665000 16.000002 c +h +0.000000 8.665002 m +0.000000 13.450549 3.879453 17.330002 8.665000 17.330002 c +13.450547 17.330002 17.330002 13.450549 17.330002 8.665002 c +17.330002 3.879455 13.450547 0.000000 8.665000 0.000000 c +3.879453 0.000000 0.000000 3.879455 0.000000 8.665002 c +h +8.665000 12.830002 m +9.032269 12.830002 9.330000 12.532271 9.330000 12.165002 c +9.330000 6.770453 l +11.194775 8.635228 l +11.454473 8.894926 11.875527 8.894926 12.135225 8.635228 c +12.394924 8.375529 12.394924 7.954474 12.135225 7.694776 c +9.135226 4.694776 l +8.875527 4.435078 8.454473 4.435078 8.194774 4.694776 c +5.194774 7.694776 l +4.935075 7.954474 4.935075 8.375529 5.194774 8.635228 c +5.454473 8.894926 5.875527 8.894926 6.135226 8.635228 c +8.000000 6.770453 l +8.000000 12.165002 l +8.000000 12.532271 8.297730 12.830002 8.665000 12.830002 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1188 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001278 00000 n +0000001301 00000 n +0000001474 00000 n +0000001548 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1607 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/Contents.json new file mode 100644 index 0000000000..fa440a32b6 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "fullscreen_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/fullscreen_30.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/fullscreen_30.pdf new file mode 100644 index 0000000000..7df6de5287 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Expand.imageset/fullscreen_30.pdf @@ -0,0 +1,161 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.334991 5.334970 cm +0.000000 0.000000 0.000000 scn +15.465001 18.000031 m +16.036026 18.000031 16.424301 17.999512 16.724445 17.974989 c +17.016825 17.951101 17.166538 17.907789 17.271078 17.854523 c +17.522274 17.726532 17.726503 17.522303 17.854494 17.271107 c +17.907761 17.166567 17.951073 17.016853 17.974960 16.724474 c +17.999483 16.424330 18.000000 16.036055 18.000000 15.465029 c +18.000000 12.665030 l +18.000000 12.297760 18.297731 12.000029 18.665001 12.000029 c +19.032270 12.000029 19.330002 12.297760 19.330002 12.665030 c +19.330002 15.465029 l +19.330002 15.492513 l +19.330002 15.492586 l +19.330009 16.029245 19.330015 16.472069 19.300545 16.832777 c +19.269936 17.207407 19.204254 17.551632 19.039534 17.874914 c +18.784031 18.376366 18.376337 18.784060 17.874886 19.039562 c +17.551603 19.204283 17.207378 19.269964 16.832748 19.300573 c +16.472025 19.330046 16.029184 19.330038 15.492496 19.330030 c +15.492476 19.330030 l +15.465001 19.330030 l +12.665001 19.330030 l +12.297731 19.330030 12.000001 19.032299 12.000001 18.665030 c +12.000001 18.297760 12.297731 18.000031 12.665001 18.000031 c +15.465001 18.000031 l +h +3.865001 19.330030 m +3.837527 19.330030 l +3.837508 19.330030 l +3.300819 19.330038 2.857976 19.330046 2.497253 19.300573 c +2.122624 19.269964 1.778399 19.204283 1.455116 19.039562 c +0.953664 18.784060 0.545971 18.376366 0.290469 17.874914 c +0.125748 17.551632 0.060066 17.207407 0.029458 16.832777 c +-0.000015 16.472054 -0.000008 16.029211 0.000000 15.492522 c +0.000000 15.492504 l +0.000000 15.465029 l +0.000000 12.665030 l +0.000000 12.297760 0.297732 12.000029 0.665001 12.000029 c +1.032270 12.000029 1.330001 12.297760 1.330001 12.665030 c +1.330001 15.465029 l +1.330001 16.036055 1.330518 16.424330 1.355041 16.724474 c +1.378929 17.016853 1.422241 17.166567 1.475507 17.271107 c +1.603498 17.522303 1.807727 17.726532 2.058923 17.854523 c +2.163464 17.907789 2.313177 17.951101 2.605557 17.974989 c +2.905700 17.999512 3.293975 18.000031 3.865001 18.000031 c +6.665001 18.000031 l +7.032271 18.000031 7.330001 18.297760 7.330001 18.665030 c +7.330001 19.032299 7.032271 19.330030 6.665001 19.330030 c +3.865001 19.330030 l +h +1.330001 6.665030 m +1.330001 7.032299 1.032270 7.330029 0.665001 7.330029 c +0.297732 7.330029 0.000000 7.032299 0.000000 6.665030 c +0.000000 3.865030 l +0.000000 3.837555 l +0.000000 3.837535 l +-0.000008 3.300846 -0.000015 2.858006 0.029458 2.497282 c +0.060066 2.122652 0.125748 1.778427 0.290469 1.455145 c +0.545971 0.953693 0.953664 0.546000 1.455116 0.290497 c +1.778399 0.125776 2.122624 0.060095 2.497253 0.029486 c +2.857963 0.000015 3.300784 0.000021 3.837445 0.000029 c +3.837518 0.000029 l +3.865001 0.000029 l +6.665001 0.000029 l +7.032271 0.000029 7.330001 0.297760 7.330001 0.665030 c +7.330001 1.032299 7.032271 1.330030 6.665001 1.330030 c +3.865001 1.330030 l +3.293975 1.330030 2.905700 1.330547 2.605557 1.355070 c +2.313177 1.378958 2.163464 1.422270 2.058923 1.475536 c +1.807727 1.603527 1.603498 1.807756 1.475507 2.058952 c +1.422241 2.163492 1.378929 2.313206 1.355041 2.605585 c +1.330518 2.905729 1.330001 3.294004 1.330001 3.865030 c +1.330001 6.665030 l +h +18.665001 7.330029 m +19.032270 7.330029 19.330002 7.032299 19.330002 6.665030 c +19.330002 3.865030 l +19.330002 3.837546 l +19.330002 3.837475 l +19.330009 3.300812 19.330015 2.857990 19.300545 2.497282 c +19.269936 2.122652 19.204254 1.778427 19.039534 1.455145 c +18.784031 0.953693 18.376337 0.546000 17.874886 0.290497 c +17.551603 0.125776 17.207378 0.060095 16.832748 0.029486 c +16.472040 0.000015 16.029217 0.000021 15.492556 0.000029 c +15.492484 0.000029 l +15.465001 0.000029 l +12.665001 0.000029 l +12.297731 0.000029 12.000001 0.297760 12.000001 0.665030 c +12.000001 1.032299 12.297731 1.330030 12.665001 1.330030 c +15.465001 1.330030 l +16.036026 1.330030 16.424301 1.330547 16.724445 1.355070 c +17.016825 1.378958 17.166538 1.422270 17.271078 1.475536 c +17.522274 1.603527 17.726503 1.807756 17.854494 2.058952 c +17.907761 2.163492 17.951073 2.313206 17.974960 2.605585 c +17.999483 2.905729 18.000000 3.294004 18.000000 3.865030 c +18.000000 6.665030 l +18.000000 7.032299 18.297731 7.330029 18.665001 7.330029 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 4198 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000004288 00000 n +0000004311 00000 n +0000004484 00000 n +0000004558 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4617 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/Contents.json new file mode 100644 index 0000000000..3bf115d3ba --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "playspeed_24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/playspeed_24.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/playspeed_24.pdf new file mode 100644 index 0000000000..c8af2af3b2 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed24.imageset/playspeed_24.pdf @@ -0,0 +1,113 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.335007 3.334999 cm +0.000000 0.000000 0.000000 scn +0.000007 16.665001 m +0.000007 17.032270 0.297737 17.330002 0.665007 17.330002 c +1.165007 17.330002 l +1.532276 17.330002 1.830007 17.032270 1.830007 16.665001 c +1.830007 16.297733 1.532276 16.000002 1.165007 16.000002 c +0.665007 16.000002 l +0.297737 16.000002 0.000007 16.297733 0.000007 16.665001 c +h +9.665000 17.330002 m +9.297730 17.330002 9.000000 17.032270 9.000000 16.665001 c +9.000000 16.297731 9.297730 16.000000 9.665000 16.000000 c +16.665001 16.000000 l +17.032270 16.000000 17.330002 16.297731 17.330002 16.665001 c +17.330002 17.032270 17.032270 17.330002 16.665001 17.330002 c +9.665000 17.330002 l +h +9.665000 1.330002 m +9.297730 1.330002 9.000000 1.032270 9.000000 0.665001 c +9.000000 0.297731 9.297730 0.000000 9.665000 0.000000 c +16.665001 0.000000 l +17.032270 0.000000 17.330002 0.297731 17.330002 0.665001 c +17.330002 1.032270 17.032270 1.330002 16.665001 1.330002 c +9.665000 1.330002 l +h +0.665000 1.330002 m +0.297731 1.330002 0.000000 1.032270 0.000000 0.665001 c +0.000000 0.297731 0.297731 0.000000 0.665000 0.000000 c +1.165000 0.000000 l +1.532269 0.000000 1.830000 0.297731 1.830000 0.665001 c +1.830000 1.032270 1.532269 1.330002 1.165000 1.330002 c +0.665000 1.330002 l +h +3.000000 16.665001 m +3.000000 17.032270 3.297731 17.330002 3.665000 17.330002 c +7.165000 17.330002 l +7.532269 17.330002 7.830000 17.032270 7.830000 16.665001 c +7.830000 16.297731 7.532269 16.000000 7.165000 16.000000 c +3.665000 16.000000 l +3.297731 16.000000 3.000000 16.297731 3.000000 16.665001 c +h +3.665000 1.330002 m +3.297731 1.330002 3.000000 1.032270 3.000000 0.665001 c +3.000000 0.297731 3.297731 0.000000 3.665000 0.000000 c +7.165000 0.000000 l +7.532269 0.000000 7.830000 0.297731 7.830000 0.665001 c +7.830000 1.032270 7.532269 1.330002 7.165000 1.330002 c +3.665000 1.330002 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1901 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001991 00000 n +0000002014 00000 n +0000002187 00000 n +0000002261 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2320 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/Contents.json new file mode 100644 index 0000000000..e75becabad --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "playspeed_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/playspeed_30.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/playspeed_30.pdf new file mode 100644 index 0000000000..4d99d69bdb --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Playspeed30.imageset/playspeed_30.pdf @@ -0,0 +1,113 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.335007 5.334999 cm +0.000000 0.000000 0.000000 scn +0.000000 18.665001 m +0.000000 19.032270 0.297731 19.330002 0.665000 19.330002 c +1.665000 19.330002 l +2.032269 19.330002 2.330000 19.032270 2.330000 18.665001 c +2.330000 18.297733 2.032269 18.000002 1.665000 18.000002 c +0.665000 18.000002 l +0.297731 18.000002 0.000000 18.297733 0.000000 18.665001 c +h +11.665000 19.330002 m +11.297730 19.330002 11.000000 19.032270 11.000000 18.665001 c +11.000000 18.297733 11.297730 18.000002 11.665000 18.000002 c +18.665001 18.000002 l +19.032269 18.000002 19.330000 18.297733 19.330000 18.665001 c +19.330000 19.032270 19.032269 19.330002 18.665001 19.330002 c +11.665000 19.330002 l +h +11.665000 1.330002 m +11.297730 1.330002 11.000000 1.032270 11.000000 0.665001 c +11.000000 0.297731 11.297730 0.000000 11.665000 0.000000 c +18.665001 0.000000 l +19.032269 0.000000 19.330000 0.297731 19.330000 0.665001 c +19.330000 1.032270 19.032269 1.330002 18.665001 1.330002 c +11.665000 1.330002 l +h +0.665000 1.330002 m +0.297731 1.330002 0.000000 1.032270 0.000000 0.665001 c +0.000000 0.297731 0.297731 0.000000 0.665000 0.000000 c +1.665000 0.000000 l +2.032269 0.000000 2.330000 0.297731 2.330000 0.665001 c +2.330000 1.032270 2.032269 1.330002 1.665000 1.330002 c +0.665000 1.330002 l +h +4.000000 18.665001 m +4.000000 19.032270 4.297730 19.330002 4.665000 19.330002 c +8.665000 19.330002 l +9.032269 19.330002 9.330000 19.032270 9.330000 18.665001 c +9.330000 18.297733 9.032269 18.000002 8.665000 18.000002 c +4.665000 18.000002 l +4.297730 18.000002 4.000000 18.297733 4.000000 18.665001 c +h +4.665000 1.330002 m +4.297730 1.330002 4.000000 1.032270 4.000000 0.665001 c +4.000000 0.297731 4.297730 0.000000 4.665000 0.000000 c +8.665000 0.000000 l +9.032269 0.000000 9.330000 0.297731 9.330000 0.665001 c +9.330000 1.032270 9.032269 1.330002 8.665000 1.330002 c +4.665000 1.330002 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1917 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000002007 00000 n +0000002030 00000 n +0000002203 00000 n +0000002277 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2336 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/AccountContext.swift b/submodules/TelegramUI/Sources/AccountContext.swift index 34ea3cd855..ad8e0acac8 100644 --- a/submodules/TelegramUI/Sources/AccountContext.swift +++ b/submodules/TelegramUI/Sources/AccountContext.swift @@ -157,7 +157,7 @@ public final class AccountContextImpl: AccountContext { public let cachedGroupCallContexts: AccountGroupCallContextCache - public init(sharedContext: SharedAccountContextImpl, account: Account, /*tonContext: StoredTonContext?, */limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, appConfiguration: AppConfiguration, temp: Bool = false) + public init(sharedContext: SharedAccountContextImpl, account: Account, limitsConfiguration: LimitsConfiguration, contentSettings: ContentSettings, appConfiguration: AppConfiguration, temp: Bool = false) { self.sharedContextImpl = sharedContext self.account = account @@ -166,7 +166,7 @@ public final class AccountContextImpl: AccountContext { self.downloadedMediaStoreManager = DownloadedMediaStoreManagerImpl(postbox: account.postbox, accountManager: sharedContext.accountManager) if let locationManager = self.sharedContextImpl.locationManager { - self.liveLocationManager = LiveLocationManagerImpl(account: account, locationManager: locationManager, inForeground: sharedContext.applicationBindings.applicationInForeground) + self.liveLocationManager = LiveLocationManagerImpl(engine: self.engine, account: account, locationManager: locationManager, inForeground: sharedContext.applicationBindings.applicationInForeground) } else { self.liveLocationManager = nil } diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift index 3df08bd4d1..8d1675a6a4 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift @@ -705,7 +705,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail } |> mapToSignal { resource -> Signal in if let resource = resource { - return uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: nil, resource: resource) |> map(Optional.init) + return TelegramEngineUnauthorized(account: account).auth.uploadedPeerVideo(resource: resource) |> map(Optional.init) } else { return .single(nil) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index b77f6af949..fbf469106b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -621,7 +621,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G statusController?.dismiss() } strongSelf.present(statusController, in: .window(.root)) - strongSelf.createVoiceChatDisposable.set((createGroupCall(account: strongSelf.context.account, peerId: message.id.peerId, title: nil, scheduleDate: nil) + strongSelf.createVoiceChatDisposable.set((strongSelf.context.engine.calls.createGroupCall(peerId: message.id.peerId, title: nil, scheduleDate: nil) |> deliverOnMainQueue).start(next: { [weak self] info in guard let strongSelf = self else { return @@ -804,13 +804,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { strongSelf.controllerInteraction?.addContact(phoneNumber) } - }, storeMediaPlaybackState: { [weak self] messageId, timestamp in + }, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in guard let strongSelf = self else { return } var storedState: MediaPlaybackStoredState? if let timestamp = timestamp { - storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: .x1) + storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate)) } let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start() }, editMedia: { [weak self] messageId, snapshots, transitionCompletion in @@ -7175,7 +7175,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if case let .peer(peerId) = self.chatLocation { - let _ = checkPeerChatServiceActions(postbox: self.context.account.postbox, peerId: peerId).start() + let _ = self.context.engine.peers.checkPeerChatServiceActions(peerId: peerId).start() } if self.chatDisplayNode.frameForInputActionButton() != nil { @@ -7302,7 +7302,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } strongSelf.peekTimerDisposable.set( - (joinChatInteractively(with: peekData.linkData, account: strongSelf.context.account) + (strongSelf.context.engine.peers.joinChatInteractively(with: peekData.linkData) |> deliverOnMainQueue).start(next: { peerId in guard let strongSelf = self else { return @@ -8336,7 +8336,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } let peerId = peer.id - let _ = (collectCacheUsageStats(account: strongSelf.context.account, peerId: peer.id) + let _ = (strongSelf.context.engine.resources.collectCacheUsageStats(peerId: peer.id) |> deliverOnMainQueue).start(next: { [weak self, weak controller] result in controller?.dismiss() @@ -8455,7 +8455,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - var signal = clearCachedMediaResources(account: strongSelf.context.account, mediaResourceIds: clearResourceIds) + var signal = strongSelf.context.engine.resources.clearCachedMediaResources(mediaResourceIds: clearResourceIds) var cancelImpl: (() -> Void)? let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } @@ -9888,10 +9888,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } private func enqueueChatContextResult(_ results: ChatContextResultCollection, _ result: ChatContextResult, hideVia: Bool = false, closeMediaInput: Bool = false, silentPosting: Bool = false) { + if !canSendMessagesToChat(self.presentationInterfaceState) { + return + } + let peerId = self.chatLocation.peerId - - if let message = outgoingMessageWithChatContextResult(to: peerId, results: results, result: result, hideVia: hideVia), canSendMessagesToChat(self.presentationInterfaceState) { - let replyMessageId = self.presentationInterfaceState.interfaceState.replyMessageId + + let replyMessageId = self.presentationInterfaceState.interfaceState.replyMessageId + + if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, results: results, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting) { self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in @@ -9913,9 +9918,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, nil) - var messages = [message.withUpdatedReplyToMessageId(replyMessageId)] - messages = self.transformEnqueueMessages(messages, silentPosting: silentPosting) - self.sendMessages(messages) } } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index 8684fe0875..3863d95b40 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -149,7 +149,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee signal = .single({ _ in return .hashtags([]) }) } - let hashtags: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> = recentlyUsedHashtags(postbox: context.account.postbox) + let hashtags: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> = context.engine.messages.recentlyUsedHashtags() |> map { hashtags -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in let normalizedQuery = query.lowercased() var result: [String] = [] @@ -279,7 +279,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee |> castError(ChatContextQueryError.self) |> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> in if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { - let contextResults = requestChatContextResults(account: context.account, botId: user.id, peerId: chatPeer.id, query: query, location: context.sharedContext.locationManager.flatMap { locationManager -> Signal<(Double, Double)?, NoError> in + let contextResults = context.engine.messages.requestChatContextResults(botId: user.id, peerId: chatPeer.id, query: query, location: context.sharedContext.locationManager.flatMap { locationManager -> Signal<(Double, Double)?, NoError> in return `deferred` { Queue.mainQueue().async { requestBotLocationStatus(user.id) diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 5c0076a5bb..b24da72856 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -168,8 +168,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.InviteLink_ContextRevoke, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - let _ = (revokePeerExportedInvitation(account: strongSelf.context.account, peerId: peer.id, link: invite.link) - + let _ = (strongSelf.context.engine.peers.revokePeerExportedInvitation(peerId: peer.id, link: invite.link) |> deliverOnMainQueue).start(completed: { [weak self] in self?.eventLogContext.reload() }) diff --git a/submodules/TelegramUI/Sources/CreateChannelController.swift b/submodules/TelegramUI/Sources/CreateChannelController.swift index 3083cd405e..d93801c7bf 100644 --- a/submodules/TelegramUI/Sources/CreateChannelController.swift +++ b/submodules/TelegramUI/Sources/CreateChannelController.swift @@ -273,7 +273,7 @@ public func createChannelController(context: AccountContext) -> ViewController { return $0.avatar } if let _ = updatingAvatar { - let _ = updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in + let _ = context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }).start() } @@ -329,7 +329,7 @@ public func createChannelController(context: AccountContext) -> ViewController { let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: [], immediateThumbnailData: nil) - uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource)) + uploadedAvatar.set(context.engine.peers.uploadedPeerPhoto(resource: resource)) uploadedVideoAvatar = nil updateState { current in var current = current @@ -363,7 +363,7 @@ public func createChannelController(context: AccountContext) -> ViewController { return nil } } - let uploadInterface = LegacyLiveUploadInterface(account: context.account) + let uploadInterface = LegacyLiveUploadInterface(context: context) let signal: SSignal if let asset = asset as? AVAsset { signal = TGMediaVideoConverter.convert(asset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)! @@ -427,7 +427,7 @@ public func createChannelController(context: AccountContext) -> ViewController { } } - uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: photoResource)) + uploadedAvatar.set(context.engine.peers.uploadedPeerPhoto(resource: photoResource)) let promise = Promise() promise.set(signal @@ -436,7 +436,7 @@ public func createChannelController(context: AccountContext) -> ViewController { } |> mapToSignal { resource -> Signal in if let resource = resource { - return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init) + return context.engine.peers.uploadedPeerVideo(resource: resource) |> map(Optional.init) } else { return .single(nil) } diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index ea4ee4ff42..daf2740e82 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -482,7 +482,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return $0.avatar } if let _ = updatingAvatar { - return updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in + return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }) |> ignoreValues @@ -576,7 +576,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: [], immediateThumbnailData: nil) - uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource)) + uploadedAvatar.set(context.engine.peers.uploadedPeerPhoto(resource: resource)) uploadedVideoAvatar = nil updateState { current in var current = current @@ -611,7 +611,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return nil } } - let uploadInterface = LegacyLiveUploadInterface(account: context.account) + let uploadInterface = LegacyLiveUploadInterface(context: context) let signal: SSignal if let asset = asset as? AVAsset { signal = TGMediaVideoConverter.convert(asset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)! @@ -675,7 +675,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] } } - uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: photoResource)) + uploadedAvatar.set(context.engine.peers.uploadedPeerPhoto(resource: photoResource)) let promise = Promise() promise.set(signal @@ -684,7 +684,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] } |> mapToSignal { resource -> Signal in if let resource = resource { - return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init) + return context.engine.peers.uploadedPeerVideo(resource: resource) |> map(Optional.init) } else { return .single(nil) } diff --git a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift index d7de6f7637..6c79d3ebfc 100644 --- a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift @@ -46,7 +46,7 @@ func paneGifSearchForQuery(context: AccountContext, query: String, offset: Strin } |> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?, Bool, Bool), NoError> in if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { - let results = requestContextResults(account: context.account, botId: user.id, query: query, peerId: context.account.peerId, offset: offset ?? "", incompleteResults: incompleteResults, staleCachedResults: staleCachedResults, limit: 1) + let results = requestContextResults(context: context, botId: user.id, query: query, peerId: context.account.peerId, offset: offset ?? "", incompleteResults: incompleteResults, staleCachedResults: staleCachedResults, limit: 1) |> map { results -> (ChatPresentationInputQueryResult?, Bool, Bool) in return (.contextRequestResult(user, results?.results), results != nil, results?.isStale ?? false) } diff --git a/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift index c97dfa1c68..13d813efca 100644 --- a/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift @@ -141,7 +141,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode { } }, removeRequested: { [weak self] text in if let strongSelf = self { - let _ = removeRecentlyUsedHashtag(postbox: strongSelf.context.account.postbox, string: text).start() + let _ = strongSelf.context.engine.messages.removeRecentlyUsedHashtag(string: text).start() strongSelf.revealedHashtag = nil } }) diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index 2fd0b0eb73..81340bfc95 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -234,7 +234,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont let geoPoint = currentProcessedResults.geoPoint.flatMap { geoPoint -> (Double, Double) in return (geoPoint.latitude, geoPoint.longitude) } - self.loadMoreDisposable.set((requestChatContextResults(account: self.context.account, botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) + self.loadMoreDisposable.set((self.context.engine.messages.requestChatContextResults(botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift index cc92ef8e82..ce69f1bad7 100644 --- a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift +++ b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift @@ -144,7 +144,7 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, legacyController.view.disablesInteractiveTransitionGestureRecognizer = true var uploadInterface: LegacyLiveUploadInterface? if peerId.namespace != Namespaces.Peer.SecretChat { - uploadInterface = LegacyLiveUploadInterface(account: context.account) + uploadInterface = LegacyLiveUploadInterface(context: context) } var slowmodeValidUntil: Int32 = 0 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index 1a5062a83c..c4b9964353 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -649,7 +649,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen canManageInvitations = true } if canManageInvitations { - let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: nil, revoked: false, forceUpdate: true) + let invitationsContext = context.engine.peers.peerExportedInvitations(peerId: peerId, adminId: nil, revoked: false, forceUpdate: true) invitationsContextPromise.set(.single(invitationsContext)) invitationsStatePromise.set(invitationsContext.state |> map(Optional.init)) } @@ -812,7 +812,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen canManageInvitations = true } if canManageInvitations { - let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, adminId: nil, revoked: false, forceUpdate: true) + let invitationsContext = context.engine.peers.peerExportedInvitations(peerId: peerId, adminId: nil, revoked: false, forceUpdate: true) invitationsContextPromise.set(.single(invitationsContext)) invitationsStatePromise.set(invitationsContext.state |> map(Optional.init)) } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 516f67b17a..7a34df2f69 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2609,7 +2609,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var hasProgress = false if title != group.title { updateDataSignals.append( - updatePeerTitle(account: strongSelf.context.account, peerId: group.id, title: title) + strongSelf.context.engine.peers.updatePeerTitle(peerId: group.id, title: title) |> ignoreValues |> mapError { _ in return Void() } ) @@ -2617,7 +2617,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if description != (data.cachedData as? CachedGroupData)?.about { updateDataSignals.append( - updatePeerDescription(account: strongSelf.context.account, peerId: group.id, description: description.isEmpty ? nil : description) + strongSelf.context.engine.peers.updatePeerDescription(peerId: group.id, description: description.isEmpty ? nil : description) |> ignoreValues |> mapError { _ in return Void() } ) @@ -2667,7 +2667,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD var hasProgress = false if title != channel.title { updateDataSignals.append( - updatePeerTitle(account: strongSelf.context.account, peerId: channel.id, title: title) + strongSelf.context.engine.peers.updatePeerTitle(peerId: channel.id, title: title) |> ignoreValues |> mapError { _ in return Void() } ) @@ -2675,7 +2675,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if description != (data.cachedData as? CachedChannelData)?.about { updateDataSignals.append( - updatePeerDescription(account: strongSelf.context.account, peerId: channel.id, description: description.isEmpty ? nil : description) + strongSelf.context.engine.peers.updatePeerDescription(peerId: channel.id, description: description.isEmpty ? nil : description) |> ignoreValues |> mapError { _ in return Void() } ) @@ -2752,7 +2752,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if self.isSettings { self.notificationExceptions.set(.single(NotificationExceptionsList(peers: [:], settings: [:])) |> then( - notificationExceptionsList(postbox: context.account.postbox, network: context.account.network) + context.engine.peers.notificationExceptionsList() |> map(Optional.init) )) self.privacySettings.set(.single(nil) |> then(context.engine.privacy.requestAccountPrivacySettings() |> map(Optional.init))) @@ -2837,7 +2837,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(peerId.namespace) { - self.displayAsPeersPromise.set(cachedGroupCallDisplayAsAvailablePeers(account: context.account, peerId: peerId)) + self.displayAsPeersPromise.set(context.engine.calls.cachedGroupCallDisplayAsAvailablePeers(peerId: peerId)) } } @@ -3072,13 +3072,13 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } }, completed: {}) } - }, storeMediaPlaybackState: { [weak self] messageId, timestamp in + }, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in guard let strongSelf = self else { return } var storedState: MediaPlaybackStoredState? if let timestamp = timestamp { - storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: .x1) + storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate) ?? .x1) } let _ = updateMediaPlaybackStoredStateInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, state: storedState).start() }, editMedia: { [weak self] messageId, snapshots, transitionCompletion in @@ -3995,13 +3995,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD private func scheduleGroupCall() { self.context.scheduleGroupCall(peerId: self.peerId) -// -// -// let time = Int32(Date().timeIntervalSince1970 + 86400) -// self.activeActionDisposable.set((createGroupCall(account: self.context.account, peerId: self.peerId, title: nil, scheduleDate: time) -// |> deliverOnMainQueue).start(next: { [weak self] info in -// -// })) } private func createAndJoinGroupCall(peerId: PeerId, joinAsPeerId: PeerId?) { @@ -4027,7 +4020,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD |> runOn(Queue.mainQueue()) |> delay(0.15, queue: Queue.mainQueue()) let progressDisposable = progressSignal.start() - let createSignal = createGroupCall(account: strongSelf.context.account, peerId: peerId, title: nil, scheduleDate: nil) + let createSignal = strongSelf.context.engine.calls.createGroupCall(peerId: peerId, title: nil, scheduleDate: nil) |> afterDisposed { Queue.mainQueue().async { progressDisposable.dispose() @@ -4389,7 +4382,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } strongSelf.openVoiceChatDisplayAsPeerSelection(completion: { joinAsPeerId in - let _ = updateGroupCallJoinAsPeer(account: context.account, peerId: peerId, joinAs: joinAsPeerId).start() + let _ = context.engine.calls.updateGroupCallJoinAsPeer(peerId: peerId, joinAs: joinAsPeerId).start() self?.openVoiceChatOptions(defaultJoinAsPeerId: joinAsPeerId, gesture: nil, contextController: c) }, gesture: gesture, contextController: c, result: f, backAction: { [weak self] c in self?.openVoiceChatOptions(defaultJoinAsPeerId: defaultJoinAsPeerId, gesture: nil, contextController: c) @@ -5005,7 +4998,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if case let .image(reference, _, _, _) = item { if let reference = reference { if remove { - let _ = removeAccountPhoto(network: self.context.account.network, reference: reference).start() + let _ = self.context.engine.accountData.removeAccountPhoto(reference: reference).start() } let dismiss = self.headerNode.avatarListNode.listContainerNode.deleteItem(item) if dismiss { @@ -5046,9 +5039,9 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.headerNode.ignoreCollapse = false let postbox = self.context.account.postbox - let signal = self.isSettings ? updateAccountPhoto(account: self.context.account, resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in + let signal = self.isSettings ? self.context.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) - }) : updatePeerPhoto(postbox: postbox, network: self.context.account.network, stateManager: self.context.account.stateManager, accountPeerId: self.context.account.peerId, peerId: self.peerId, photo: uploadedPeerPhoto(postbox: postbox, network: self.context.account.network, resource: resource), mapResourceToAvatarSizes: { resource, representations in + }) : self.context.engine.peers.updatePeerPhoto(peerId: self.peerId, photo: self.context.engine.peers.uploadedPeerPhoto(resource: resource), mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) self.updateAvatarDisposable.set((signal @@ -5096,6 +5089,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } let account = self.context.account + let context = self.context let signal = Signal { [weak self] subscriber in let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in if let paintingData = adjustments.paintingData, paintingData.hasAnimation { @@ -5104,7 +5098,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return nil } } - let uploadInterface = LegacyLiveUploadInterface(account: account) + let uploadInterface = LegacyLiveUploadInterface(context: context) let signal: SSignal if let asset = asset as? AVAsset { signal = TGMediaVideoConverter.convert(asset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)! @@ -5180,11 +5174,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.updateAvatarDisposable.set((signal |> mapToSignal { videoResource -> Signal in if isSettings { - return updateAccountPhoto(account: account, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } else { - return updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: photoResource), video: uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: videoResource) |> map(Optional.init), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: context.engine.peers.uploadedPeerVideo(resource: videoResource) |> map(Optional.init), videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } @@ -5305,7 +5299,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } let postbox = strongSelf.context.account.postbox - strongSelf.updateAvatarDisposable.set((updatePeerPhoto(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, stateManager: strongSelf.context.account.stateManager, accountPeerId: strongSelf.context.account.peerId, peerId: strongSelf.peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in + strongSelf.updateAvatarDisposable.set((strongSelf.context.engine.peers.updatePeerPhoto(peerId: strongSelf.peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) |> deliverOnMainQueue).start(next: { result in diff --git a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift index c9eba8d4c0..0277922cae 100644 --- a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift +++ b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift @@ -442,19 +442,7 @@ final class SharedMediaPlayer { case let .setBaseRate(baseRate): self.playbackRate = baseRate if let playbackItem = self.playbackItem { - let rateValue: Double - switch baseRate { - case .x1: - rateValue = 1.0 - case .x2: - rateValue = 1.8 - case .x4: - rateValue = 4.0 - case .x8: - rateValue = 8.0 - case .x16: - rateValue = 16.0 - } + let rateValue: Double = baseRate.doubleValue switch playbackItem { case let .audio(player): player.setBaseRate(rateValue) diff --git a/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift index 6808bbc0a1..fd1c032325 100644 --- a/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift @@ -340,7 +340,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex let geoPoint = currentProcessedResults.geoPoint.flatMap { geoPoint -> (Double, Double) in return (geoPoint.latitude, geoPoint.longitude) } - self.loadMoreDisposable.set((requestChatContextResults(account: self.context.account, botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) + self.loadMoreDisposable.set((self.context.engine.messages.requestChatContextResults(botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/TelegramUIPreferences/Sources/MusicPlaybackSettings.swift b/submodules/TelegramUIPreferences/Sources/MusicPlaybackSettings.swift index 14cfe6a36c..d2707fa138 100644 --- a/submodules/TelegramUIPreferences/Sources/MusicPlaybackSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/MusicPlaybackSettings.swift @@ -15,15 +15,25 @@ public enum MusicPlaybackSettingsLooping: Int32 { } public enum AudioPlaybackRate: Int32 { + case x0_5 = 500 case x1 = 1000 + case x1_5 = 1500 case x2 = 2000 case x4 = 4000 case x8 = 8000 case x16 = 16000 - var doubleValue: Double { + public var doubleValue: Double { return Double(self.rawValue) / 1000.0 } + + public init(_ value: Double) { + if let resolved = AudioPlaybackRate(rawValue: Int32(value * 1000.0)) { + self = resolved + } else { + self = .x1 + } + } } public struct MusicPlaybackSettings: PreferencesEntry, Equatable { diff --git a/submodules/TelegramVoip/Sources/GroupCallContext.swift b/submodules/TelegramVoip/Sources/GroupCallContext.swift index 68867a1e1d..cea1f85d45 100644 --- a/submodules/TelegramVoip/Sources/GroupCallContext.swift +++ b/submodules/TelegramVoip/Sources/GroupCallContext.swift @@ -34,27 +34,16 @@ private protocol BroadcastPartSource: AnyObject { private final class NetworkBroadcastPartSource: BroadcastPartSource { private let queue: Queue - private let account: Account + private let engine: TelegramEngine private let callId: Int64 private let accessHash: Int64 private var dataSource: AudioBroadcastDataSource? - - #if DEBUG - private let debugDumpDirectory: TempBoxDirectory? - #endif - init(queue: Queue, account: Account, callId: Int64, accessHash: Int64) { + init(queue: Queue, engine: TelegramEngine, callId: Int64, accessHash: Int64) { self.queue = queue - self.account = account + self.engine = engine self.callId = callId self.accessHash = accessHash - - #if DEBUG - self.debugDumpDirectory = nil - /*let debugDumpDirectory = TempBox.shared.tempDirectory() - self.debugDumpDirectory = debugDumpDirectory - print("Debug streaming dump path: \(debugDumpDirectory.path)")*/ - #endif } func requestPart(timestampMilliseconds: Int64, durationMilliseconds: Int64, completion: @escaping (OngoingGroupCallBroadcastPart) -> Void, rejoinNeeded: @escaping () -> Void) -> Disposable { @@ -69,11 +58,12 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource { if let dataSourceValue = self.dataSource { dataSource = .single(dataSourceValue) } else { - dataSource = getAudioBroadcastDataSource(account: self.account, callId: self.callId, accessHash: self.accessHash) + dataSource = self.engine.calls.getAudioBroadcastDataSource(callId: self.callId, accessHash: self.accessHash) } let callId = self.callId let accessHash = self.accessHash + let engine = self.engine let queue = self.queue let signal = dataSource @@ -81,7 +71,7 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource { |> mapToSignal { [weak self] dataSource -> Signal in if let dataSource = dataSource { self?.dataSource = dataSource - return getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds) + return engine.calls.getAudioBroadcastPart(dataSource: dataSource, callId: callId, accessHash: accessHash, timestampIdMilliseconds: timestampIdMilliseconds, durationMilliseconds: durationMilliseconds) |> map(Optional.init) } else { return .single(nil) @@ -89,10 +79,6 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource { } } |> deliverOn(self.queue) - - #if DEBUG - let debugDumpDirectory = self.debugDumpDirectory - #endif return signal.start(next: { result in guard let result = result else { @@ -102,12 +88,6 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource { let part: OngoingGroupCallBroadcastPart switch result.status { case let .data(dataValue): - #if DEBUG - if let debugDumpDirectory = debugDumpDirectory { - let _ = try? dataValue.write(to: URL(fileURLWithPath: debugDumpDirectory.path + "/" + "\(timestampIdMilliseconds).ogg")) - } - #endif - part = OngoingGroupCallBroadcastPart(timestampMilliseconds: timestampIdMilliseconds, responseTimestamp: result.responseTimestamp, status: .success, oggData: dataValue) case .notReady: part = OngoingGroupCallBroadcastPart(timestampMilliseconds: timestampIdMilliseconds, responseTimestamp: result.responseTimestamp, status: .notReady, oggData: Data()) @@ -137,12 +117,12 @@ private final class OngoingGroupCallBroadcastPartTaskImpl : NSObject, OngoingGro public final class OngoingGroupCallContext { public struct AudioStreamData { - public var account: Account + public var engine: TelegramEngine public var callId: Int64 public var accessHash: Int64 - public init(account: Account, callId: Int64, accessHash: Int64) { - self.account = account + public init(engine: TelegramEngine, callId: Int64, accessHash: Int64) { + self.engine = engine self.callId = callId self.accessHash = accessHash } @@ -351,7 +331,7 @@ public final class OngoingGroupCallContext { var audioLevelsUpdatedImpl: (([NSNumber]) -> Void)? if let audioStreamData = audioStreamData { - let broadcastPartsSource = NetworkBroadcastPartSource(queue: queue, account: audioStreamData.account, callId: audioStreamData.callId, accessHash: audioStreamData.accessHash) + let broadcastPartsSource = NetworkBroadcastPartSource(queue: queue, engine: audioStreamData.engine, callId: audioStreamData.callId, accessHash: audioStreamData.accessHash) self.broadcastPartsSource = broadcastPartsSource } diff --git a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift index 533cd32c5e..81249019eb 100644 --- a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift +++ b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift @@ -755,7 +755,7 @@ final class WatchLocationHandler: WatchRequestHandler { guard let peerId = peerId else { return .single(nil) } - return requestChatContextResults(account: context.account, botId: peerId, peerId: context.account.peerId, query: "", location: .single((args.coordinate.latitude, args.coordinate.longitude)), offset: "") + return context.engine.messages.requestChatContextResults(botId: peerId, peerId: context.account.peerId, query: "", location: .single((args.coordinate.latitude, args.coordinate.longitude)), offset: "") |> map { results -> ChatContextResultCollection? in return results?.results } diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index 71c802442d..3fc012211b 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -10,8 +10,8 @@ import LegacyComponents import TelegramUIPreferences import AccountContext -public func requestContextResults(account: Account, botId: PeerId, query: String, peerId: PeerId, offset: String = "", existingResults: ChatContextResultCollection? = nil, incompleteResults: Bool = false, staleCachedResults: Bool = false, limit: Int = 60) -> Signal { - return requestChatContextResults(account: account, botId: botId, peerId: peerId, query: query, offset: offset, incompleteResults: incompleteResults, staleCachedResults: staleCachedResults) +public func requestContextResults(context: AccountContext, botId: PeerId, query: String, peerId: PeerId, offset: String = "", existingResults: ChatContextResultCollection? = nil, incompleteResults: Bool = false, staleCachedResults: Bool = false, limit: Int = 60) -> Signal { + return context.engine.messages.requestChatContextResults(botId: botId, peerId: peerId, query: query, offset: offset, incompleteResults: incompleteResults, staleCachedResults: staleCachedResults) |> `catch` { error -> Signal in return .single(nil) } @@ -40,7 +40,7 @@ public func requestContextResults(account: Account, botId: PeerId, query: String updated = true } if let collection = collection, collection.results.count < limit, let nextOffset = collection.nextOffset, updated { - let nextResults = requestContextResults(account: account, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection, limit: limit) + let nextResults = requestContextResults(context: context, botId: botId, query: query, peerId: peerId, offset: nextOffset, existingResults: collection, limit: limit) if collection.results.count > 10 { return .single(RequestChatContextResultsResult(results: collection, isStale: resultsStruct?.isStale ?? false)) |> then(nextResults) @@ -445,6 +445,7 @@ public final class WebSearchController: ViewController { } let account = self.context.account + let context = self.context let contextBot = self.context.engine.peers.resolvePeerByName(name: name) |> mapToSignal { peerId -> Signal in if let peerId = peerId { @@ -459,7 +460,7 @@ public final class WebSearchController: ViewController { } |> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> in if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder { - let results = requestContextResults(account: account, botId: user.id, query: query, peerId: peerId, limit: 64) + let results = requestContextResults(context: context, botId: user.id, query: query, peerId: peerId, limit: 64) |> map { results -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in return { _ in return .contextRequestResult(user, results?.results) diff --git a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift index b2b279f61d..450ee647df 100644 --- a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift @@ -577,7 +577,7 @@ class WebSearchControllerNode: ASDisplayNode { let geoPoint = currentProcessedResults.geoPoint.flatMap { geoPoint -> (Double, Double) in return (geoPoint.latitude, geoPoint.longitude) } - self.loadMoreDisposable.set((requestChatContextResults(account: self.context.account, botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) + self.loadMoreDisposable.set((self.context.engine.messages.requestChatContextResults(botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(geoPoint), offset: nextOffset) |> deliverOnMainQueue).start(next: { [weak self] nextResults in guard let strongSelf = self, let nextResults = nextResults else { return diff --git a/third-party/webrtc/BUILD b/third-party/webrtc/BUILD index 0dae08f165..8da4664043 100644 --- a/third-party/webrtc/BUILD +++ b/third-party/webrtc/BUILD @@ -3239,12 +3239,14 @@ arm_specific_flags = [ "-DWEBRTC_ARCH_ARM", "-DWEBRTC_ARCH_ARM_V7", "-DWEBRTC_HAS_NEON", + "-DLIBYUV_NEON", ] arm64_specific_flags = [ "-DWEBRTC_ARCH_ARM64", "-DWEBRTC_HAS_NEON", "-mfpu=neon", + "-DLIBYUV_NEON", ] x86_64_specific_flags = [ @@ -3513,7 +3515,6 @@ cc_library( copts = [ "-ffp-contract=fast", "-Ithird-party/webrtc/dependencies/third_party/libyuv/include", - "-DLIBYUV_NEON", ] + arch_specific_cflags + optimization_flags, visibility = ["//visibility:public"], )