diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index c10ee63d47..deeca75664 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -619,7 +619,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo } for (_, messageId) in maxMessageIdsToApply { - signals.append(applyMaxReadIndexInteractively(postbox: account.postbox, stateManager: account.stateManager, index: MessageIndex(id: messageId, timestamp: 0)) + signals.append(TelegramEngine(account: account).messages.applyMaxReadIndexInteractively(index: MessageIndex(id: messageId, timestamp: 0)) |> castError(IntentHandlingError.self)) } diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutController.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutController.swift index 93adaa12f1..560dd508be 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutController.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutController.swift @@ -36,13 +36,13 @@ public final class BotCheckoutController: ViewController { "button_text_color": Int32(bitPattern: presentationData.theme.list.itemCheckColors.foregroundColor.argb) ] - return fetchBotPaymentForm(postbox: context.account.postbox, network: context.account.network, messageId: messageId, themeParams: themeParams) + return context.engine.payments.fetchBotPaymentForm(messageId: messageId, themeParams: themeParams) |> mapError { _ -> FetchError in return .generic } |> mapToSignal { paymentForm -> Signal in if let current = paymentForm.savedInfo { - return validateBotPaymentForm(account: context.account, saveInfo: true, messageId: messageId, formInfo: current) + return context.engine.payments.validateBotPaymentForm(saveInfo: true, messageId: messageId, formInfo: current) |> mapError { _ -> FetchError in return .generic } diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index cf03bb4a04..6a212cecbb 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -1229,7 +1229,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz let totalAmount = currentTotalPrice(paymentForm: paymentForm, validatedFormInfo: self.currentValidatedFormInfo, currentShippingOptionId: self.currentShippingOptionId, currentTip: self.currentTipAmount) let currencyValue = formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency) - self.payDisposable.set((sendBotPaymentForm(account: self.context.account, messageId: self.messageId, formId: paymentForm.id, validatedInfoId: self.currentValidatedFormInfo?.id, shippingOptionId: self.currentShippingOptionId, tipAmount: tipAmount, credentials: credentials) |> deliverOnMainQueue).start(next: { [weak self] result in + self.payDisposable.set((self.context.engine.payments.sendBotPaymentForm(messageId: self.messageId, formId: paymentForm.id, validatedInfoId: self.currentValidatedFormInfo?.id, shippingOptionId: self.currentShippingOptionId, tipAmount: tipAmount, credentials: credentials) |> deliverOnMainQueue).start(next: { [weak self] result in if let strongSelf = self { strongSelf.inProgressDimNode.isUserInteractionEnabled = false strongSelf.inProgressDimNode.alpha = 0.0 diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift index 8f91094946..034628432e 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift @@ -338,7 +338,7 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi func verify() { self.isVerifying = true let formInfo = self.collectFormInfo() - self.verifyDisposable.set((validateBotPaymentForm(account: self.context.account, saveInfo: self.saveInfoItem.isOn, messageId: self.messageId, formInfo: formInfo) |> deliverOnMainQueue).start(next: { [weak self] result in + self.verifyDisposable.set((self.context.engine.payments.validateBotPaymentForm(saveInfo: self.saveInfoItem.isOn, messageId: self.messageId, formInfo: formInfo) |> deliverOnMainQueue).start(next: { [weak self] result in if let strongSelf = self { strongSelf.formInfoUpdated(formInfo, result) } diff --git a/submodules/BotPaymentsUI/Sources/BotReceiptControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotReceiptControllerNode.swift index f605cf78dd..522e9f91bf 100644 --- a/submodules/BotPaymentsUI/Sources/BotReceiptControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotReceiptControllerNode.swift @@ -306,7 +306,7 @@ final class BotReceiptControllerNode: ItemListControllerNode { super.init(controller: controller, navigationBar: navigationBar, updateNavigationOffset: updateNavigationOffset, state: signal) - self.dataRequestDisposable = (requestBotPaymentReceipt(account: context.account, messageId: messageId) |> deliverOnMainQueue).start(next: { [weak self] receipt in + self.dataRequestDisposable = (context.engine.payments.requestBotPaymentReceipt(messageId: messageId) |> deliverOnMainQueue).start(next: { [weak self] receipt in if let strongSelf = self { UIView.transition(with: strongSelf.view, duration: 0.25, options: UIView.AnimationOptions.transitionCrossDissolve, animations: { }, completion: nil) diff --git a/submodules/CallListUI/Sources/CallListController.swift b/submodules/CallListUI/Sources/CallListController.swift index 01e5c07ff0..dc53949168 100644 --- a/submodules/CallListUI/Sources/CallListController.swift +++ b/submodules/CallListUI/Sources/CallListController.swift @@ -288,7 +288,7 @@ public final class CallListController: TelegramBaseController { return } - var signal = clearCallHistory(account: strongSelf.context.account, forEveryone: forEveryone) + var signal = strongSelf.context.engine.messages.clearCallHistory(forEveryone: forEveryone) var cancelImpl: (() -> Void)? let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/CallListUI/Sources/CallListControllerNode.swift b/submodules/CallListUI/Sources/CallListControllerNode.swift index db7cf53b83..52a77c4730 100644 --- a/submodules/CallListUI/Sources/CallListControllerNode.swift +++ b/submodules/CallListUI/Sources/CallListControllerNode.swift @@ -343,7 +343,7 @@ final class CallListControllerNode: ASDisplayNode { guard let strongSelf = self else { return } - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messageIds, type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: messageIds, type: .forEveryone).start() })) items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe, color: .destructive, action: { [weak actionSheet] in @@ -353,7 +353,7 @@ final class CallListControllerNode: ASDisplayNode { return } - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messageIds, type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: messageIds, type: .forLocalPeer).start() })) actionSheet.setItemGroups([ diff --git a/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift b/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift index 29fd0383e0..4c9001312c 100644 --- a/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift +++ b/submodules/ChatImportUI/Sources/ChatImportActivityScreen.swift @@ -823,7 +823,7 @@ public final class ChatImportActivityScreen: ViewController { let resolvedPeerId: Signal if self.peerId.namespace == Namespaces.Peer.CloudGroup { - resolvedPeerId = convertGroupToSupergroup(account: self.context.account, peerId: self.peerId) + resolvedPeerId = self.context.engine.peers.convertGroupToSupergroup(peerId: self.peerId) |> mapError { _ -> ImportManager.ImportError in return .generic } diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 71a48ce17a..113c170936 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1180,7 +1180,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if !self.didSuggestLocalization { self.didSuggestLocalization = true - let network = self.context.account.network + let context = self.context let signal = combineLatest(self.context.sharedContext.accountManager.transaction { transaction -> String in let languageCode: String if let current = transaction.getSharedData(SharedDataKeys.localizationSettings) as? LocalizationSettings { @@ -1206,7 +1206,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard let suggestedLocalization = value.1, !suggestedLocalization.isSeen && suggestedLocalization.languageCode != "en" && suggestedLocalization.languageCode != value.0 else { return .single(nil) } - return suggestedLocalizationInfo(network: network, languageCode: suggestedLocalization.languageCode, extractKeys: LanguageSuggestionControllerStrings.keys) + return context.engine.localization.suggestedLocalizationInfo(languageCode: suggestedLocalization.languageCode, extractKeys: LanguageSuggestionControllerStrings.keys) |> map({ suggestedLocalization -> (String, SuggestedLocalizationInfo)? in return (value.0, suggestedLocalization) }) @@ -1223,7 +1223,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } }) { strongSelf.present(controller, in: .window(.root)) - _ = markSuggestedLocalizationAsSeenInteractively(postbox: strongSelf.context.account.postbox, languageCode: suggestedLocalization.languageCode).start() + _ = strongSelf.context.engine.localization.markSuggestedLocalizationAsSeenInteractively(languageCode: suggestedLocalization.languageCode).start() } })) @@ -2295,7 +2295,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return false } if value == .commit { - let _ = clearHistoryInteractively(postbox: strongSelf.context.account.postbox, peerId: peerId, type: type).start(completed: { + let _ = strongSelf.context.engine.messages.clearHistoryInteractively(peerId: peerId, type: type).start(completed: { guard let strongSelf = self else { return } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index a2df45c8cd..5da162da88 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -844,7 +844,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() strongSelf.updateState { state in return state.withUpdatedSelectedMessageIds(nil) @@ -867,7 +867,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forLocalPeer).start() strongSelf.updateState { state in return state.withUpdatedSelectedMessageIds(nil) diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 7d2313a5f4..4bb50c8669 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -920,7 +920,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { addAppLogEvent(postbox: context.account.postbox, type: "search_global_query") } - let searchSignal = searchMessages(account: context.account, location: location, query: finalQuery, state: nil, limit: 50) + let searchSignal = context.engine.messages.searchMessages(location: location, query: finalQuery, state: nil, limit: 50) |> map { result, updatedState -> ChatListSearchMessagesResult in return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState) } @@ -929,7 +929,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { |> mapToSignal { searchContext -> Signal<(([Message], [PeerId: CombinedPeerReadState], Int32), Bool), NoError> in if let searchContext = searchContext, searchContext.result.hasMore { if let _ = searchContext.loadMoreIndex { - return searchMessages(account: context.account, location: location, query: finalQuery, state: searchContext.result.state, limit: 80) + return context.engine.messages.searchMessages(location: location, query: finalQuery, state: searchContext.result.state, limit: 80) |> map { result, updatedState -> ChatListSearchMessagesResult in return ChatListSearchMessagesResult(query: finalQuery, messages: result.messages.sorted(by: { $0.index > $1.index }), readStates: result.readStates, hasMore: !result.completed, totalCount: result.totalCount, state: updatedState) } @@ -966,7 +966,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { |> then(context.sharedContext.resolveUrl(context: context, peerId: nil, url: finalQuery, skipUrlAuth: true) |> mapToSignal { resolvedUrl -> Signal in if case let .channelMessage(_, messageId) = resolvedUrl { - return downloadMessage(postbox: context.account.postbox, network: context.account.network, messageId: messageId) + return context.engine.messages.downloadMessage(messageId: messageId) } else { return .single(nil) } diff --git a/submodules/ContactListUI/Sources/ContactContextMenus.swift b/submodules/ContactListUI/Sources/ContactContextMenus.swift index 2a525d8e60..17dbcc8682 100644 --- a/submodules/ContactListUI/Sources/ContactContextMenus.swift +++ b/submodules/ContactListUI/Sources/ContactContextMenus.swift @@ -61,7 +61,7 @@ func contactContextMenuItems(context: AccountContext, peerId: PeerId, contactsCo context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(currentPeerId), peekData: nil)) } } else { - var createSignal = createSecretChat(account: context.account, peerId: peerId) + var createSignal = context.engine.peers.createSecretChat(peerId: peerId) var cancelImpl: (() -> Void)? let progressSignal = Signal { subscriber in let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index b31b9d97d7..1845ca9656 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -718,6 +718,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi } func animateOut(result initialResult: ContextMenuActionResult, completion: @escaping () -> Void) { + self.isUserInteractionEnabled = false + self.beganAnimatingOut() var transitionDuration: Double = 0.2 diff --git a/submodules/Display/Source/CAAnimationUtils.swift b/submodules/Display/Source/CAAnimationUtils.swift index 060f9fb134..129c3581b8 100644 --- a/submodules/Display/Source/CAAnimationUtils.swift +++ b/submodules/Display/Source/CAAnimationUtils.swift @@ -229,6 +229,10 @@ public extension CALayer { func animateScale(from: CGFloat, to: CGFloat, duration: Double, delay: Double = 0.0, timingFunction: String = CAMediaTimingFunctionName.easeInEaseOut.rawValue, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { self.animate(from: NSNumber(value: Float(from)), to: NSNumber(value: Float(to)), keyPath: "transform.scale", timingFunction: timingFunction, duration: duration, delay: delay, mediaTimingFunction: mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: additive, completion: completion) } + + func animateScaleX(from: CGFloat, to: CGFloat, duration: Double, delay: Double = 0.0, timingFunction: String = CAMediaTimingFunctionName.easeInEaseOut.rawValue, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) { + self.animate(from: NSNumber(value: Float(from)), to: NSNumber(value: Float(to)), keyPath: "transform.scale.x", timingFunction: timingFunction, duration: duration, delay: delay, mediaTimingFunction: mediaTimingFunction, removeOnCompletion: removeOnCompletion, completion: completion) + } func animateScaleY(from: CGFloat, to: CGFloat, duration: Double, delay: Double = 0.0, timingFunction: String = CAMediaTimingFunctionName.easeInEaseOut.rawValue, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, completion: ((Bool) -> Void)? = nil) { self.animate(from: NSNumber(value: Float(from)), to: NSNumber(value: Float(to)), keyPath: "transform.scale.y", timingFunction: timingFunction, duration: duration, delay: delay, mediaTimingFunction: mediaTimingFunction, removeOnCompletion: removeOnCompletion, completion: completion) diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index 2642564f85..50de64416a 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -675,6 +675,52 @@ public extension ContainedViewLayoutTransition { }) } } + + func animateTransformScale(node: ASDisplayNode, from fromScale: CGPoint, completion: ((Bool) -> Void)? = nil) { + let t = node.layer.transform + + switch self { + case .immediate: + if let completion = completion { + completion(true) + } + case let .animated(duration, curve): + let calculatedFrom: CGPoint + let calculatedTo: CGPoint + + calculatedFrom = fromScale + calculatedTo = CGPoint(x: 1.0, y: 1.0) + + node.layer.animateScaleX(from: calculatedFrom.x, to: calculatedTo.x, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in + if let completion = completion { + completion(result) + } + }) + node.layer.animateScaleY(from: calculatedFrom.y, to: calculatedTo.y, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction) + } + } + + func animateTransformScale(layer: CALayer, from fromScale: CGPoint, completion: ((Bool) -> Void)? = nil) { + switch self { + case .immediate: + if let completion = completion { + completion(true) + } + case let .animated(duration, curve): + let calculatedFrom: CGPoint + let calculatedTo: CGPoint + + calculatedFrom = fromScale + calculatedTo = CGPoint(x: 1.0, y: 1.0) + + layer.animateScaleX(from: calculatedFrom.x, to: calculatedTo.x, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, completion: { result in + if let completion = completion { + completion(result) + } + }) + layer.animateScaleY(from: calculatedFrom.y, to: calculatedTo.y, duration: duration, timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction) + } + } func animateTransformScale(view: UIView, from fromScale: CGFloat, completion: ((Bool) -> Void)? = nil) { let t = view.layer.transform @@ -920,7 +966,12 @@ public extension ContainedViewLayoutTransition { completion?(true) return } - let t = node.layer.transform + + self.updateTransformScale(layer: node.layer, scale: scale, completion: completion) + } + + func updateTransformScale(layer: CALayer, scale: CGPoint, completion: ((Bool) -> Void)? = nil) { + let t = layer.transform let currentScaleX = sqrt((t.m11 * t.m11) + (t.m12 * t.m12) + (t.m13 * t.m13)) var currentScaleY = sqrt((t.m21 * t.m21) + (t.m22 * t.m22) + (t.m23 * t.m23)) if t.m22 < 0.0 { @@ -932,16 +983,16 @@ public extension ContainedViewLayoutTransition { } return } - + switch self { case .immediate: - node.layer.transform = CATransform3DMakeScale(scale.x, scale.y, 1.0) + layer.transform = CATransform3DMakeScale(scale.x, scale.y, 1.0) if let completion = completion { completion(true) } case let .animated(duration, curve): - node.layer.transform = CATransform3DMakeScale(scale.x, scale.y, 1.0) - node.layer.animate(from: NSValue(caTransform3D: t), to: NSValue(caTransform3D: node.layer.transform), keyPath: "transform", timingFunction: curve.timingFunction, duration: duration, delay: 0.0, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: true, additive: false, completion: { + layer.transform = CATransform3DMakeScale(scale.x, scale.y, 1.0) + layer.animate(from: NSValue(caTransform3D: t), to: NSValue(caTransform3D: layer.transform), keyPath: "transform", timingFunction: curve.timingFunction, duration: duration, delay: 0.0, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: true, additive: false, completion: { result in if let completion = completion { completion(result) diff --git a/submodules/Display/Source/ContextContentSourceNode.swift b/submodules/Display/Source/ContextContentSourceNode.swift index ffd7ab165e..5eb8d82223 100644 --- a/submodules/Display/Source/ContextContentSourceNode.swift +++ b/submodules/Display/Source/ContextContentSourceNode.swift @@ -24,10 +24,27 @@ public final class ContextExtractedContentContainingNode: ASDisplayNode { self.addSubnode(self.contentNode) } + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.contentNode.supernode === self { + return self.contentNode.hitTest(self.view.convert(point, to: self.contentNode.view), with: event) + } else { + return nil + } + } } public final class ContextExtractedContentNode: ASDisplayNode { public var customHitTest: ((CGPoint) -> UIView?)? + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let result = self.view.hitTest(point, with: event) + if result === self.view { + return nil + } else { + return result + } + } } public final class ContextControllerContentNode: ASDisplayNode { diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 46fdf27b98..ad84f2079a 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -998,7 +998,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll items.append(ActionSheetButtonItem(title: globalTitle, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: messages.map { $0.id }, type: .forEveryone).start() strongSelf.controllerInteraction?.dismissController() } })) @@ -1013,13 +1013,13 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll items.append(ActionSheetButtonItem(title: localOptionText, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: messages.map { $0.id }, type: .forLocalPeer).start() strongSelf.controllerInteraction?.dismissController() } })) } if !ask && items.count == 1 { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: messages.map { $0.id }, type: .forEveryone).start() strongSelf.controllerInteraction?.dismissController() } else if !items.isEmpty { strongSelf.interacting?(true) diff --git a/submodules/GradientBackground/BUILD b/submodules/GradientBackground/BUILD new file mode 100644 index 0000000000..e84cbca60e --- /dev/null +++ b/submodules/GradientBackground/BUILD @@ -0,0 +1,16 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "GradientBackground", + module_name = "GradientBackground", + srcs = glob([ + "Sources/**/*.swift", + ]), + deps = [ + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + "//submodules/Display:Display", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/GradientBackground/Sources/GradientBackground.swift b/submodules/GradientBackground/Sources/GradientBackground.swift new file mode 100644 index 0000000000..7e55be5a08 --- /dev/null +++ b/submodules/GradientBackground/Sources/GradientBackground.swift @@ -0,0 +1,249 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit + +private struct GradientPoint { + var color: UIColor + var position: CGPoint +} + +private func applyTransformerToPoints(step: Int, substep: Int) -> [GradientPoint] { + var points: [GradientPoint] = [] + + var firstSet: [CGPoint] + var secondSet: [CGPoint] + + let colors: [UIColor] = [ + UIColor(rgb: 0x7FA381), + UIColor(rgb: 0xFFF5C5), + UIColor(rgb: 0x336F55), + UIColor(rgb: 0xFBE37D) + ] + + let firstStepPoints: [CGPoint] = [ + CGPoint(x: 0.823, y: 0.086), + CGPoint(x: 0.362, y: 0.254), + CGPoint(x: 0.184, y: 0.923), + CGPoint(x: 0.648, y: 0.759) + ] + + let nextStepPoints: [CGPoint] = [ + CGPoint(x: 0.59, y: 0.16), + CGPoint(x: 0.28, y: 0.58), + CGPoint(x: 0.42, y: 0.83), + CGPoint(x: 0.74, y: 0.42) + ] + + if step % 2 == 0 { + firstSet = shiftArray(array: firstStepPoints, offset: step / 2) + secondSet = shiftArray(array: nextStepPoints, offset: step / 2) + } else { + firstSet = shiftArray(array: nextStepPoints, offset: step / 2) + secondSet = shiftArray(array: firstStepPoints, offset: step / 2 + 1) + } + + for index in 0 ..< colors.count { + let point = transformPoint( + points: (firstSet[index], secondSet[index]), + substep: substep + ) + + points.append(GradientPoint( + color: colors[index], + position: point + )) + } + + return points +} + +private func shiftArray(array: [CGPoint], offset: Int) -> [CGPoint] { + var newArray = array + var offset = offset + while offset > 0 { + let element = newArray.removeFirst() + newArray.append(element) + offset -= 1 + } + return newArray +} + +private func transformPoint(points: (first: CGPoint, second: CGPoint), substep: Int) -> CGPoint { + let delta = CGFloat(substep) / CGFloat(30) + let x = points.first.x + (points.second.x - points.first.x) * delta + let y = points.first.y + (points.second.y - points.first.y) * delta + + return CGPoint(x: x, y: y) +} + +private func generateGradientComponent(size: CGSize, color: UIColor) -> UIImage? { + UIGraphicsBeginImageContextWithOptions(size, false, 1.0) + + let c = UIGraphicsGetCurrentContext() + + c?.clear(CGRect(origin: CGPoint.zero, size: size)) + + c?.setBlendMode(.normal) + + //var gradLocs: [CGFloat] = [0, 0.1, 0.35, 1] + var gradLocs: [CGFloat] = [0.0, 1.0] + let colorSpace = CGColorSpaceCreateDeviceRGB() + let radius = min(size.width / 2.0, size.height / 2.0) + + let colors = [ + color.cgColor, + //color.withAlphaComponent(0.8).cgColor, + //color.withAlphaComponent(0.3).cgColor, + color.withAlphaComponent(0).cgColor + ] + + let grad = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &gradLocs) + if let grad = grad { + let newPoint = CGPoint(x: size.width / 2.0, y: size.height / 2.0) + + c?.drawRadialGradient(grad, startCenter: newPoint, startRadius: 0, endCenter: newPoint, endRadius: radius, options: []) + } + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return image +} + +public final class GradientBackgroundNode: ASDisplayNode { + //private let imageView: UIImageView + + private var pointImages: [UIImageView] = [] + private let dimView: UIView + + private let firstStepPoints: [CGPoint] = [ + CGPoint(x: 0.823, y: 0.086), + CGPoint(x: 0.362, y: 0.254), + CGPoint(x: 0.184, y: 0.923), + CGPoint(x: 0.648, y: 0.759) + ] + + private let nextStepPoints: [CGPoint] = [ + CGPoint(x: 0.59, y: 0.16), + CGPoint(x: 0.28, y: 0.58), + CGPoint(x: 0.42, y: 0.83), + CGPoint(x: 0.74, y: 0.42) + ] + + private var phase: Int = 0 + private var subphase: Int = 0 + + private var timer: Timer? + + private var validLayout: CGSize? + + override public init() { + //self.imageView = UIImageView() + + self.dimView = UIView() + self.dimView.backgroundColor = UIColor(white: 1.0, alpha: 0.0) + + super.init() + + self.phase = 0 + + self.backgroundColor = .white + self.clipsToBounds = true + + //self.view.addSubview(self.imageView) + + /*let compositingModes: [String] = CIFilter + .filterNames(inCategory: nil) // fetch all the available filters + .filter { $0.contains("Compositing")} // retrieve only the compositing ones + .map { + let capitalizedFilter = $0.dropFirst(2) // drop the CIn prefix + let first = capitalizedFilter.first! // fetch the first letter + // lowercase the first letter and drop the `Compositing` suffix + return "\(first.lowercased())\(capitalizedFilter.dropFirst().dropLast("Compositing".count))" + }*/ + + //print("compositingModes: \(compositingModes)") + + //self.imageView.alpha = 0.5 + //self.imageView.layer.compositingFilter = "multiplyBlendMode" + + let colors: [UIColor] = [ + UIColor(rgb: 0x7FA381), + UIColor(rgb: 0xFFF5C5), + UIColor(rgb: 0x336F55), + UIColor(rgb: 0xFBE37D) + ] + + for i in 0 ..< colors.count { + let pointImage = UIImageView(image: generateGradientComponent(size: CGSize(width: 300.0, height: 300.0), color: colors[i].withMultiplied(hue: 1.0, saturation: 1.1, brightness: 1.1))) + //pointImage.layer.compositingFilter = "multiplyBlendMode" + self.view.addSubview(pointImage) + self.pointImages.append(pointImage) + } + + self.view.addSubview(self.dimView) + + /*if #available(iOS 10.0, *) { + let timer = Timer(timeInterval: 2.0, repeats: true, block: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.phase = (strongSelf.phase + 1) % 4 + if let size = strongSelf.validLayout { + strongSelf.updateLayout(size: size, transition: .animated(duration: 0.5, curve: .spring)) + } + }) + self.timer = timer + RunLoop.main.add(timer, forMode: .common) + }*/ + } + + deinit { + self.timer?.invalidate() + } + + public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { + self.validLayout = size + + self.dimView.frame = CGRect(origin: CGPoint(), size: size) + + let positions: [CGPoint] + + let basePositions: [CGPoint] = [ + CGPoint(x: 0.1, y: 0.1), + CGPoint(x: 0.1, y: 0.9), + CGPoint(x: 0.9, y: 0.9), + CGPoint(x: 0.9, y: 0.1), + ] + + switch self.phase % 4 { + case 0: + positions = basePositions + case 1: + positions = shiftArray(array: basePositions, offset: 1) + case 2: + positions = shiftArray(array: basePositions, offset: 2) + case 3: + positions = shiftArray(array: basePositions, offset: 3) + default: + preconditionFailure() + } + + for i in 0 ..< firstStepPoints.count { + if self.pointImages.count <= i { + break + } + let pointCenter = CGPoint(x: size.width * positions[i].x, y: size.height * positions[i].y) + let pointSize = CGSize(width: size.width * 2.0, height: size.height * 2.0) + transition.updateFrame(view: self.pointImages[i], frame: CGRect(origin: CGPoint(x: pointCenter.x - pointSize.width / 2.0, y: pointCenter.y - pointSize.height / 2.0), size: pointSize)) + } + } + + public func animateEvent(transition: ContainedViewLayoutTransition) { + self.phase = (self.phase + 1) % 4 + if let size = self.validLayout { + self.updateLayout(size: size, transition: transition) + } + } +} diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index 03b576262f..1bbf864d87 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -43,7 +43,7 @@ public final class HashtagSearchController: TelegramBaseController { let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations) let location: SearchMessagesLocation = .general(tags: nil, minDate: nil, maxDate: nil) - let search = searchMessages(account: context.account, location: location, query: query, state: nil) + let search = context.engine.messages.searchMessages(location: location, query: query, state: nil) let foundMessages: Signal<[ChatListSearchEntry], NoError> = search |> map { result, _ in return result.messages.map({ .message($0, RenderedPeer(message: $0), result.readStates[$0.id.peerId], chatListPresentationData, result.totalCount, nil, false) }) diff --git a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewController.swift b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewController.swift index 82c76ccd0c..fb69b70373 100644 --- a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewController.swift +++ b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewController.swift @@ -65,7 +65,7 @@ public final class LanguageLinkPreviewController: ViewController { } self.displayNodeDidLoad() - self.disposable.set((requestLocalizationPreview(network: self.context.account.network, identifier: self.identifier) + self.disposable.set((self.context.engine.localization.requestLocalizationPreview(identifier: self.identifier) |> deliverOnMainQueue).start(next: { [weak self] result in guard let strongSelf = self else { return @@ -115,7 +115,7 @@ public final class LanguageLinkPreviewController: ViewController { return } self.controllerNode.setInProgress(true) - self.disposable.set((downloadAndApplyLocalization(accountManager: self.context.sharedContext.accountManager, postbox: self.context.account.postbox, network: self.context.account.network, languageCode: localizationInfo.languageCode) + self.disposable.set((self.context.engine.localization.downloadAndApplyLocalization(accountManager: self.context.sharedContext.accountManager, languageCode: localizationInfo.languageCode) |> deliverOnMainQueue).start(error: { [weak self] _ in guard let strongSelf = self else { return diff --git a/submodules/LanguageSuggestionUI/Sources/LanguageSuggestionController.swift b/submodules/LanguageSuggestionUI/Sources/LanguageSuggestionController.swift index bdde36d467..0635c5b176 100644 --- a/submodules/LanguageSuggestionUI/Sources/LanguageSuggestionController.swift +++ b/submodules/LanguageSuggestionUI/Sources/LanguageSuggestionController.swift @@ -353,7 +353,7 @@ public func languageSuggestionController(context: AccountContext, suggestedLocal dismissImpl?(true) } else { startActivity() - disposable.set((downloadAndApplyLocalization(accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, languageCode: languageCode) + disposable.set((context.engine.localization.downloadAndApplyLocalization(accountManager: context.sharedContext.accountManager, languageCode: languageCode) |> deliverOnMainQueue).start(completed: { dismissImpl?(true) })) diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGAttachmentCarouselItemView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGAttachmentCarouselItemView.h index 9346362f3d..407b78688f 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGAttachmentCarouselItemView.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGAttachmentCarouselItemView.h @@ -62,4 +62,6 @@ - (instancetype)initWithContext:(id)context camera:(bool)hasCamera selfPortrait:(bool)selfPortrait forProfilePhoto:(bool)forProfilePhoto assetType:(TGMediaAssetType)assetType saveEditedPhotos:(bool)saveEditedPhotos allowGrouping:(bool)allowGrouping allowSelection:(bool)allowSelection allowEditing:(bool)allowEditing document:(bool)document selectionLimit:(int)selectionLimit; +- (UIView *)getItemSnapshot:(NSString *)uniqueId; + @end diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h index 9f16354018..5d94419416 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGMediaAssetsController.h @@ -74,7 +74,7 @@ typedef enum @property (nonatomic, strong) NSString *recipientName; -@property (nonatomic, copy) NSDictionary *(^descriptionGenerator)(id, NSString *, NSArray *, NSString *); +@property (nonatomic, copy) NSDictionary *(^descriptionGenerator)(id, NSString *, NSArray *, NSString *, NSString *); @property (nonatomic, copy) void (^avatarCompletionBlock)(UIImage *image); @property (nonatomic, copy) void (^completionBlock)(NSArray *signals, bool silentPosting, int32_t scheduleTime); @property (nonatomic, copy) void (^avatarVideoCompletionBlock)(UIImage *image, AVAsset *asset, TGVideoEditAdjustments *adjustments); @@ -92,7 +92,7 @@ typedef enum - (UIBarButtonItem *)rightBarButtonItem; -- (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator; +- (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *, NSString *))descriptionGenerator; - (void)completeWithAvatarImage:(UIImage *)image; - (void)completeWithAvatarVideo:(AVAsset *)asset adjustments:(TGVideoEditAdjustments *)adjustments image:(UIImage *)image; @@ -105,6 +105,6 @@ typedef enum + (TGMediaAssetType)assetTypeForIntent:(TGMediaAssetsControllerIntent)intent; -+ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext intent:(TGMediaAssetsControllerIntent)intent currentItem:(TGMediaAsset *)currentItem storeAssets:(bool)storeAssets useMediaCache:(bool)useMediaCache descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator saveEditedPhotos:(bool)saveEditedPhotos; ++ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext intent:(TGMediaAssetsControllerIntent)intent currentItem:(TGMediaAsset *)currentItem storeAssets:(bool)storeAssets useMediaCache:(bool)useMediaCache descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *, NSString *))descriptionGenerator saveEditedPhotos:(bool)saveEditedPhotos; @end diff --git a/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m b/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m index 3aa9bcda19..5cb451457b 100644 --- a/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m +++ b/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m @@ -346,6 +346,21 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500; [_itemsSizeChangedDisposable dispose]; } +- (UIView *)getItemSnapshot:(NSString *)uniqueId { + for (UIView *cell in _collectionView.visibleCells) { + if ([cell isKindOfClass:[TGAttachmentAssetCell class]]) { + TGAttachmentAssetCell *assetCell = (TGAttachmentAssetCell *)cell; + if (assetCell.asset.identifier != nil && [assetCell.asset.identifier isEqualToString:uniqueId]) { + UIView *snapshotView = [assetCell snapshotViewAfterScreenUpdates:false]; + snapshotView.frame = [assetCell convertRect:assetCell.bounds toView:nil]; + assetCell.alpha = 0.01f; + return snapshotView; + } + } + } + return nil; +} + - (void)setPallete:(TGMenuSheetPallete *)pallete { _pallete = pallete; diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m index 4e3c7e6644..23674be13c 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m @@ -578,8 +578,11 @@ [super loadView]; bool hasOnScreenNavigation = false; - if (iosMajorVersion() >= 11) - hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON; + if (iosMajorVersion() >= 11) { + if (@available(iOS 11.0, *)) { + hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON; + } + } CGFloat inset = [TGViewController safeAreaInsetForOrientation:self.interfaceOrientation hasOnScreenNavigation:hasOnScreenNavigation].bottom; _toolbarView = [[TGMediaPickerToolbarView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - TGMediaPickerToolbarHeight - inset, self.view.frame.size.width, TGMediaPickerToolbarHeight + inset)]; @@ -648,7 +651,9 @@ return; [strongController dismissAnimated:true manual:false completion:nil]; + if (@available(iOS 14, *)) { [[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:strongSelf]; + } }], [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"Media.LimitedAccessChangeSettings") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ { @@ -725,8 +730,11 @@ orientation = UIInterfaceOrientationLandscapeLeft; bool hasOnScreenNavigation = false; - if (iosMajorVersion() >= 11) - hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON; + if (iosMajorVersion() >= 11) { + if (@available(iOS 11.0, *)) { + hasOnScreenNavigation = (self.viewLoaded && self.view.safeAreaInsets.bottom > FLT_EPSILON) || _context.safeAreaInset.bottom > FLT_EPSILON; + } + } _toolbarView.safeAreaInset = [TGViewController safeAreaInsetForOrientation:orientation hasOnScreenNavigation:hasOnScreenNavigation]; _accessView.safeAreaInset = [TGViewController safeAreaInsetForOrientation:orientation hasOnScreenNavigation:hasOnScreenNavigation]; @@ -810,7 +818,7 @@ } } -- (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator +- (NSArray *)resultSignalsWithCurrentItem:(TGMediaAsset *)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *, NSString *))descriptionGenerator { bool storeAssets = (_editingContext != nil) && self.shouldStoreAssets; @@ -827,7 +835,7 @@ return value; } -+ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext intent:(TGMediaAssetsControllerIntent)intent currentItem:(TGMediaAsset *)currentItem storeAssets:(bool)storeAssets useMediaCache:(bool)__unused useMediaCache descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator saveEditedPhotos:(bool)saveEditedPhotos ++ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext intent:(TGMediaAssetsControllerIntent)intent currentItem:(TGMediaAsset *)currentItem storeAssets:(bool)storeAssets useMediaCache:(bool)__unused useMediaCache descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *, NSString *))descriptionGenerator saveEditedPhotos:(bool)saveEditedPhotos { NSMutableArray *signals = [[NSMutableArray alloc] init]; NSMutableArray *selectedItems = selectionContext.selectedItems ? [selectionContext.selectedItems mutableCopy] : [[NSMutableArray alloc] init]; @@ -945,7 +953,7 @@ if (groupedId != nil) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }] catch:^SSignal *(id error) { @@ -971,7 +979,7 @@ if (groupedId != nil) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]; }]]; @@ -998,7 +1006,7 @@ else if (groupedId != nil && !hasAnyTimers) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]; @@ -1074,7 +1082,7 @@ else if (groupedId != nil && !hasAnyTimers) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]; }]]; @@ -1156,7 +1164,7 @@ else if (groupedId != nil && !hasAnyTimers) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }] catch:^SSignal *(__unused id error) { @@ -1197,7 +1205,7 @@ if (groupedId != nil) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]]; @@ -1267,7 +1275,7 @@ else if (groupedId != nil && !hasAnyTimers) dict[@"groupedId"] = groupedId; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]]; @@ -1345,7 +1353,7 @@ if (timer != nil) dict[@"timer"] = timer; - id generatedItem = descriptionGenerator(dict, caption, entities, nil); + id generatedItem = descriptionGenerator(dict, caption, entities, nil, asset.identifier); return generatedItem; }]]; diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift index bce688145a..7e27064fc5 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift @@ -106,7 +106,10 @@ public func legacyMediaEditor(context: AccountContext, peer: Peer, media: AnyMed TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, entities: [], withItem: item, paint: true, recipientName: recipientName, stickersContext: paintStickersContext, snapshots: snapshots as? [Any], immediate: transitionCompletion != nil, appeared: { transitionCompletion?() }, completion: { result, editingContext in - let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: result as! TGMediaSelectableItem, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: legacyAssetPickerItemGenerator()) + let nativeGenerator = legacyAssetPickerItemGenerator() + let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: result as! TGMediaSelectableItem, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: { _1, _2, _3, _4 in + nativeGenerator(_1, _2, _3, _4, nil) + }) sendMessagesWithSignals(signals, false, 0) }, dismissed: { [weak legacyController] in legacyController?.dismiss() @@ -114,7 +117,7 @@ public func legacyMediaEditor(context: AccountContext, peer: Peer, media: AnyMed }) } -public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController { +public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, @escaping (String) -> UIView?, @escaping () -> Void) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController { let defaultVideoPreset = defaultVideoPresetForContext(context) UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0") @@ -217,8 +220,14 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocati if slowModeEnabled, let signals = signals, signals.count > 1 { presentCantSendMultipleFiles() } else { - controller.dismiss(animated: true) - sendMessagesWithSignals(signals, silentPosting, scheduleTime) + sendMessagesWithSignals(signals, silentPosting, scheduleTime, { [weak carouselItem] uniqueId in + if let carouselItem = carouselItem { + return carouselItem.getItemSnapshot(uniqueId) + } + return nil + }, { [weak controller] in + controller?.dismiss(animated: true) + }) } } }; @@ -310,8 +319,11 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocati TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: "", entities: [], withItem: item, paint: false, recipientName: recipientName, stickersContext: paintStickersContext, snapshots: [], immediate: false, appeared: { }, completion: { result, editingContext in - let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: result as! TGMediaSelectableItem, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: legacyAssetPickerItemGenerator()) - sendMessagesWithSignals(signals, false, 0) + let nativeGenerator = legacyAssetPickerItemGenerator() + let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: result as! TGMediaSelectableItem, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: { _1, _2, _3, _4 in + nativeGenerator(_1, _2, _3, _4, nil) + }) + sendMessagesWithSignals(signals, false, 0, { _ in nil}, {}) }, dismissed: { [weak legacyController] in legacyController?.dismiss() }) @@ -435,7 +447,10 @@ public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, chatLoca done?(time) } }, completed: { selectionContext, editingContext, currentItem, silentPosting, scheduleTime in - let signals = TGClipboardMenu.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, descriptionGenerator: legacyAssetPickerItemGenerator()) + let nativeGenerator = legacyAssetPickerItemGenerator() + let signals = TGClipboardMenu.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, descriptionGenerator: { _1, _2, _3, _4 in + nativeGenerator(_1, _2, _3, _4, nil) + }) sendMessagesWithSignals(signals, silentPosting, scheduleTime) }, dismissed: { [weak legacyController] in legacyController?.dismiss() diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index 56dec373e7..b1a92b8663 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -130,18 +130,20 @@ private final class LegacyAssetItemWrapper: NSObject { let item: LegacyAssetItem let timer: Int? let groupedId: Int64? + let uniqueId: String? - init(item: LegacyAssetItem, timer: Int?, groupedId: Int64?) { + init(item: LegacyAssetItem, timer: Int?, groupedId: Int64?, uniqueId: String?) { self.item = item self.timer = timer self.groupedId = groupedId + self.uniqueId = uniqueId super.init() } } -public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String?) -> [AnyHashable : Any]?) { - return { anyDict, caption, entities, hash in +public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String?, String?) -> [AnyHashable : Any]?) { + return { anyDict, caption, entities, hash, uniqueId in let dict = anyDict as! NSDictionary let stickers = (dict["stickers"] as? [Data])?.compactMap { data -> FileMediaReference? in let decoder = PostboxDecoder(buffer: MemoryBuffer(data: data)) @@ -160,10 +162,10 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? let url: String? = (dict["url"] as? String) ?? (dict["url"] as? URL)?.path if let url = url { let dimensions = image.size - result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: 4.0), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: false, asAnimation: true, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: 4.0), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: false, asAnimation: true, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) } } else { - result["item" as NSString] = LegacyAssetItemWrapper(item: .image(data: .image(image), thumbnail: thumbnail, caption: caption, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .image(data: .image(image), thumbnail: thumbnail, caption: caption, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) } return result } else if (dict["type"] as! NSString) == "cloudPhoto" { @@ -184,9 +186,9 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? name = customName } - result["item" as NSString] = LegacyAssetItemWrapper(item: .file(data: .asset(asset.backingAsset), thumbnail: thumbnail, mimeType: mimeType, name: name, caption: caption), timer: nil, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .file(data: .asset(asset.backingAsset), thumbnail: thumbnail, mimeType: mimeType, name: name, caption: caption), timer: nil, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) } else { - result["item" as NSString] = LegacyAssetItemWrapper(item: .image(data: .asset(asset.backingAsset), thumbnail: thumbnail, caption: caption, stickers: []), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .image(data: .asset(asset.backingAsset), thumbnail: thumbnail, caption: caption, stickers: []), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) } return result } else if (dict["type"] as! NSString) == "file" { @@ -207,12 +209,12 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? let dimensions = (dict["dimensions"]! as AnyObject).cgSizeValue! let duration = (dict["duration"]! as AnyObject).doubleValue! - result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: tempFileUrl.path, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: nil, caption: caption, asFile: false, asAnimation: true, stickers: []), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: tempFileUrl.path, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: nil, caption: caption, asFile: false, asAnimation: true, stickers: []), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) return result } var result: [AnyHashable: Any] = [:] - result["item" as NSString] = LegacyAssetItemWrapper(item: .file(data: .tempFile(tempFileUrl.path), thumbnail: thumbnail, mimeType: mimeType, name: name, caption: caption), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .file(data: .tempFile(tempFileUrl.path), thumbnail: thumbnail, mimeType: mimeType, name: name, caption: caption), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) return result } } else if (dict["type"] as! NSString) == "video" { @@ -224,13 +226,13 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? if let asset = dict["asset"] as? TGMediaAsset { var result: [AnyHashable: Any] = [:] - result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .asset(asset), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .asset(asset), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) return result } else if let url = (dict["url"] as? String) ?? (dict["url"] as? URL)?.absoluteString { let dimensions = (dict["dimensions"]! as AnyObject).cgSizeValue! let duration = (dict["duration"]! as AnyObject).doubleValue! var result: [AnyHashable: Any] = [:] - result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) return result } } else if (dict["type"] as! NSString) == "cameraVideo" { @@ -246,7 +248,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String? let dimensions = previewImage.pixelSize() let duration = (dict["duration"]! as AnyObject).doubleValue! var result: [AnyHashable: Any] = [:] - result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value) + result["item" as NSString] = LegacyAssetItemWrapper(item: .video(data: .tempFile(path: url, dimensions: dimensions, duration: duration), thumbnail: thumbnail, adjustments: dict["adjustments"] as? TGVideoEditAdjustments, caption: caption, asFile: asFile, asAnimation: false, stickers: stickers), timer: (dict["timer"] as? NSNumber)?.intValue, groupedId: (dict["groupedId"] as? NSNumber)?.int64Value, uniqueId: uniqueId) return result } } @@ -338,10 +340,15 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationI } |> runOn(Queue.concurrentDefaultQueue()) } -public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -> Signal<[EnqueueMessage], Void> { +public struct LegacyAssetPickerEnqueueMessage { + public var message: EnqueueMessage + public var uniqueId: String? +} + +public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -> Signal<[LegacyAssetPickerEnqueueMessage], Void> { return Signal { subscriber in let disposable = SSignal.combineSignals(signals).start(next: { anyValues in - var messages: [EnqueueMessage] = [] + var messages: [LegacyAssetPickerEnqueueMessage] = [] outer: for item in (anyValues as! NSArray) { if let item = (item as? NSDictionary)?.object(forKey: "item") as? LegacyAssetItemWrapper { @@ -391,7 +398,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - } var text = caption ?? "" - messages.append(.message(text: text, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId)) } } case let .asset(asset): @@ -407,7 +414,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - if let timer = item.timer, timer > 0 && timer <= 60 { attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil)) } - messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId)) case .tempFile: break } @@ -418,13 +425,13 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - arc4random_buf(&randomId, 8) let resource = LocalFileReferenceMediaResource(localFilePath: path, randomId: randomId) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)]) - messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId)) case let .asset(asset): var randomId: Int64 = 0 arc4random_buf(&randomId, 8) let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max)) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)]) - messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId)) default: break } @@ -552,7 +559,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - if let timer = item.timer, timer > 0 && timer <= 60 { attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil)) } - messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId)) } } } diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift index dbaebce170..b28f246ed9 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift @@ -328,7 +328,10 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender var result: Double let minDuration: Double = 3.0 if durations.count > 1 { - result = min(6.0, Double(durations.reduce(1.0) { Double(lcm(Int32($0 * 10.0), Int32($1 * 10.0))) }) / 10.0) + let reduced = durations.reduce(1.0) { lhs, rhs -> Double in + return Double(lcm(Int32(lhs * 10.0), Int32(rhs * 10.0))) + } + result = min(6.0, Double(reduced) / 10.0) } else if let duration = durations.first { result = duration } else { diff --git a/submodules/LiveLocationManager/Sources/LiveLocationManager.swift b/submodules/LiveLocationManager/Sources/LiveLocationManager.swift index 0cb7e547ea..d407c26456 100644 --- a/submodules/LiveLocationManager/Sources/LiveLocationManager.swift +++ b/submodules/LiveLocationManager/Sources/LiveLocationManager.swift @@ -10,9 +10,7 @@ import AccountContext public final class LiveLocationManagerImpl: LiveLocationManager { private let queue = Queue.mainQueue() - private let postbox: Postbox - private let network: Network - private let stateManager: AccountStateManager + private let account: Account private let locationManager: DeviceLocationManager private let summaryManagerImpl: LiveLocationSummaryManagerImpl @@ -46,16 +44,14 @@ public final class LiveLocationManagerImpl: LiveLocationManager { private var invalidationTimer: (SwiftSignalKit.Timer, Int32)? - public init(postbox: Postbox, network: Network, accountPeerId: PeerId, viewTracker: AccountViewTracker, stateManager: AccountStateManager, locationManager: DeviceLocationManager, inForeground: Signal) { - self.postbox = postbox - self.network = network - self.stateManager = stateManager + public init(account: Account, locationManager: DeviceLocationManager, inForeground: Signal) { + self.account = account self.locationManager = locationManager - self.summaryManagerImpl = LiveLocationSummaryManagerImpl(queue: self.queue, postbox: postbox, accountPeerId: accountPeerId, viewTracker: viewTracker) + self.summaryManagerImpl = LiveLocationSummaryManagerImpl(queue: self.queue, postbox: account.postbox, accountPeerId: account.peerId, viewTracker: account.viewTracker) let viewKey: PostboxViewKey = .localMessageTag(.OutgoingLiveLocation) - self.messagesDisposable = (postbox.combinedView(keys: [viewKey]) + self.messagesDisposable = (account.postbox.combinedView(keys: [viewKey]) |> deliverOn(self.queue)).start(next: { [weak self] view in if let strongSelf = self { let timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) @@ -175,7 +171,7 @@ public final class LiveLocationManagerImpl: LiveLocationManager { let addedStopped = stopMessageIds.subtracting(self.stopMessageIds) self.stopMessageIds = stopMessageIds for id in addedStopped { - self.editMessageDisposables.set((requestEditLiveLocation(postbox: self.postbox, network: self.network, stateManager: self.stateManager, messageId: id, stop: true, coordinate: nil, heading: nil, proximityNotificationRadius: nil) + self.editMessageDisposables.set((TelegramEngine(account: self.account).messages.requestEditLiveLocation(messageId: id, stop: true, coordinate: nil, heading: nil, proximityNotificationRadius: nil) |> deliverOn(self.queue)).start(completed: { [weak self] in if let strongSelf = self { strongSelf.editMessageDisposables.set(nil, forKey: id) @@ -230,7 +226,7 @@ public final class LiveLocationManagerImpl: LiveLocationManager { let ids = self.broadcastToMessageIds let remainingIds = Atomic>(value: Set(ids.keys)) for id in ids.keys { - self.editMessageDisposables.set((requestEditLiveLocation(postbox: self.postbox, network: self.network, stateManager: self.stateManager, messageId: id, stop: false, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude, accuracyRadius: Int32(accuracyRadius)), heading: heading.flatMap { Int32($0) }, proximityNotificationRadius: nil) + self.editMessageDisposables.set((TelegramEngine(account: self.account).messages.requestEditLiveLocation(messageId: id, stop: false, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude, accuracyRadius: Int32(accuracyRadius)), heading: heading.flatMap { Int32($0) }, proximityNotificationRadius: nil) |> deliverOn(self.queue)).start(completed: { [weak self] in if let strongSelf = self { strongSelf.editMessageDisposables.set(nil, forKey: id) @@ -253,7 +249,7 @@ public final class LiveLocationManagerImpl: LiveLocationManager { let ids = self.broadcastToMessageIds.keys.filter({ $0.peerId == peerId }) if !ids.isEmpty { - let _ = self.postbox.transaction({ transaction -> Void in + let _ = self.account.postbox.transaction({ transaction -> Void in for id in ids { transaction.updateMessage(id, update: { currentMessage in var storeForwardInfo: StoreMessageForwardInfo? diff --git a/submodules/LocationUI/Sources/LocationViewController.swift b/submodules/LocationUI/Sources/LocationViewController.swift index 14920a2593..e99daa8f99 100644 --- a/submodules/LocationUI/Sources/LocationViewController.swift +++ b/submodules/LocationUI/Sources/LocationViewController.swift @@ -192,7 +192,7 @@ public final class LocationViewController: ViewController { return state } - let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0).start(completed: { [weak self] in + let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0).start(completed: { [weak self] in guard let strongSelf = self else { return } @@ -261,7 +261,7 @@ public final class LocationViewController: ViewController { return state } - let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start(completed: { [weak self] in + let _ = context.engine.messages.requestEditLiveLocation(messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start(completed: { [weak self] in guard let strongSelf = self else { return } diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index e901ef56c9..4b0324d822 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -885,7 +885,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr } } else { if let messageId = messageId { - let _ = deleteMessagesInteractively(account: self.context.account, messageIds: [messageId], type: .forEveryone).start() + let _ = self.context.engine.messages.deleteMessagesInteractively(messageIds: [messageId], type: .forEveryone).start() } if entry == self.entries.first { diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift index 45416f9842..24cb05f037 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift @@ -1220,7 +1220,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi case conversionFailed } - let signal = convertGroupToSupergroup(account: context.account, peerId: peerId) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> map(Optional.init) |> `catch` { error -> Signal in switch error { diff --git a/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift b/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift index 872d4bea6a..6ddf88abf6 100644 --- a/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift @@ -650,7 +650,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI } if peerId.namespace == Namespaces.Peer.CloudGroup { - let signal = convertGroupToSupergroup(account: context.account, peerId: peerId) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> map(Optional.init) |> `catch` { error -> Signal in switch error { diff --git a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift index 7c16bdf96b..eee1c7a3fa 100644 --- a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift @@ -327,7 +327,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI var applySignal: Signal var updatedPeerId: PeerId? = nil if let legacyGroup = groupPeer as? TelegramGroup { - applySignal = convertGroupToSupergroup(account: context.account, peerId: legacyGroup.id) + applySignal = context.engine.peers.convertGroupToSupergroup(peerId: legacyGroup.id) |> mapError { error -> ChannelDiscussionGroupError in switch error { case .tooManyChannels: diff --git a/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift b/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift index 2dc4cd0c0f..c25f8f176d 100644 --- a/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift @@ -460,7 +460,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p } |> then(.single(nil)) } else if let peer = peer as? TelegramGroup { - signal = convertGroupToSupergroup(account: context.account, peerId: peer.id) + signal = context.engine.peers.convertGroupToSupergroup(peerId: peer.id) |> map(Optional.init) |> mapError { error -> ChannelOwnershipTransferError in switch error { diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index b416888015..540cce7c68 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -797,7 +797,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina let progress = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) presentControllerImpl?(progress, nil) - let signal = convertGroupToSupergroup(account: context.account, peerId: view.peerId) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: view.peerId) |> mapError { error -> UpdateChannelSlowModeError in switch error { case .tooManyChannels: diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index bb0fa9d466..9c0cb6985a 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -1171,7 +1171,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId, } _ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start() - let signal = convertGroupToSupergroup(account: context.account, peerId: peerId) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> mapToSignal { upgradedPeerId -> Signal in return context.engine.peers.updateAddressName(domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> `catch` { _ -> Signal in diff --git a/submodules/PeerInfoUI/Sources/ConvertToSupergroupController.swift b/submodules/PeerInfoUI/Sources/ConvertToSupergroupController.swift index 494e9537c2..b1dbe193b9 100644 --- a/submodules/PeerInfoUI/Sources/ConvertToSupergroupController.swift +++ b/submodules/PeerInfoUI/Sources/ConvertToSupergroupController.swift @@ -149,7 +149,7 @@ public func convertToSupergroupController(context: AccountContext, peerId: PeerI } if !alreadyConverting { - convertDisposable.set((convertGroupToSupergroup(account: context.account, peerId: peerId) + convertDisposable.set((context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> deliverOnMainQueue).start(next: { createdPeerId in replaceControllerImpl?(context.sharedContext.makeChatController(context: context, chatLocation: .peer(createdPeerId), subject: nil, botStart: nil, mode: .standard(previewing: false))) })) diff --git a/submodules/PeerInfoUI/Sources/GroupPreHistorySetupController.swift b/submodules/PeerInfoUI/Sources/GroupPreHistorySetupController.swift index f16c20505d..6ef4e75beb 100644 --- a/submodules/PeerInfoUI/Sources/GroupPreHistorySetupController.swift +++ b/submodules/PeerInfoUI/Sources/GroupPreHistorySetupController.swift @@ -161,7 +161,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer } if let value = value, value != defaultValue { if peerId.namespace == Namespaces.Peer.CloudGroup { - let signal = convertGroupToSupergroup(account: context.account, peerId: peerId) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> mapToSignal { upgradedPeerId -> Signal in return updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: upgradedPeerId, historyAvailableForNewMembers: value) |> `catch` { _ -> Signal in diff --git a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift index 3840254013..6767eab567 100644 --- a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift +++ b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift @@ -212,7 +212,7 @@ public func peerAutoremoveSetupScreen(context: AccountContext, peerId: PeerId, c } if updated { - let signal = setChatMessageAutoremoveTimeoutInteractively(account: context.account, peerId: peerId, timeout: resolvedValue) + let signal = context.engine.peers.setChatMessageAutoremoveTimeoutInteractively(peerId: peerId, timeout: resolvedValue) |> deliverOnMainQueue applyDisposable.set((signal diff --git a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift index f7393cf892..9beb049164 100644 --- a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift +++ b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift @@ -418,7 +418,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { let transition = preparedLanguageListNodeTransition(presentationData: presentationData, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, openSearch: openSearch, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) >= entries.count, crossfade: (previousState == nil) != (localizationListState == nil)) strongSelf.enqueueTransition(transition) }) - self.updatedDisposable = synchronizedLocalizationListState(postbox: context.account.postbox, network: context.account.network).start() + self.updatedDisposable = context.engine.localization.synchronizedLocalizationListState().start() } deinit { @@ -501,7 +501,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { return } strongSelf.applyingCode.set(.single(info.languageCode)) - strongSelf.applyDisposable.set((downloadAndApplyLocalization(accountManager: strongSelf.context.sharedContext.accountManager, postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, languageCode: info.languageCode) + strongSelf.applyDisposable.set((strongSelf.context.engine.localization.downloadAndApplyLocalization(accountManager: strongSelf.context.sharedContext.accountManager, languageCode: info.languageCode) |> deliverOnMainQueue).start(completed: { self?.applyingCode.set(.single(nil)) })) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift index 3aa25bcff8..04c8921075 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift @@ -360,7 +360,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController { info.insert(.shippingInfo) } - clearPaymentInfoDisposable.set((clearBotPaymentInfo(network: context.account.network, info: info) + clearPaymentInfoDisposable.set((context.engine.payments.clearBotPaymentInfo(info: info) |> deliverOnMainQueue).start(completed: { updateState { state in var state = state @@ -482,7 +482,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController { return state } if clear { - clearPaymentInfoDisposable.set((clearCloudDraftsInteractively(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId) + clearPaymentInfoDisposable.set((context.engine.messages.clearCloudDraftsInteractively() |> deliverOnMainQueue).start(completed: { updateState { state in var state = state diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift index 0f79690bd9..a3f57b7fd6 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift @@ -708,7 +708,7 @@ private func languageSearchableItems(context: AccountContext, localizations: [Lo let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) present(.immediate, controller) - let _ = (downloadAndApplyLocalization(accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, languageCode: languageCode) + let _ = (context.engine.localization.downloadAndApplyLocalization(accountManager: context.sharedContext.accountManager, languageCode: languageCode) |> deliverOnMainQueue).start(completed: { [weak controller] in controller?.dismiss() present(.dismiss, nil) diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 785e24c330..dcf21b5996 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -618,7 +618,7 @@ public final class ShareController: ViewController { if let error = error { Queue.mainQueue().async { let _ = (account.postbox.transaction { transaction -> Peer? in - deleteMessages(transaction: transaction, mediaBox: account.postbox.mediaBox, ids: [id]) + TelegramEngine(account: account).messages.deleteMessages(transaction: transaction, ids: [id]) return transaction.getPeer(id.peerId) } |> deliverOnMainQueue).start(next: { peer in diff --git a/submodules/StatisticsUI/Sources/MessageStatsController.swift b/submodules/StatisticsUI/Sources/MessageStatsController.swift index 72ce6daff7..cd36e64526 100644 --- a/submodules/StatisticsUI/Sources/MessageStatsController.swift +++ b/submodules/StatisticsUI/Sources/MessageStatsController.swift @@ -215,13 +215,13 @@ public func messageStatsController(context: AccountContext, messageId: MessageId let previousData = Atomic(value: nil) - let searchSignal = searchMessages(account: context.account, location: .publicForwards(messageId: messageId, datacenterId: Int(datacenterId)), query: "", state: nil) + let searchSignal = context.engine.messages.searchMessages(location: .publicForwards(messageId: messageId, datacenterId: Int(datacenterId)), query: "", state: nil) |> map(Optional.init) |> afterNext { result in if let result = result { for message in result.0.messages { if let peer = message.peers[message.id.peerId], let peerReference = PeerReference(peer) { - let _ = updatedRemotePeer(postbox: context.account.postbox, network: context.account.network, peer: peerReference).start() + let _ = context.engine.peers.updatedRemotePeer(peer: peerReference).start() } } } diff --git a/submodules/Stripe/PublicHeaders/Stripe/STPToken.h b/submodules/Stripe/PublicHeaders/Stripe/STPToken.h index ad44f21ecb..4f6896d968 100755 --- a/submodules/Stripe/PublicHeaders/Stripe/STPToken.h +++ b/submodules/Stripe/PublicHeaders/Stripe/STPToken.h @@ -21,7 +21,7 @@ /** * You cannot directly instantiate an `STPToken`. You should only use one that has been returned from an `STPAPIClient` callback. */ -- (nonnull instancetype) init __attribute__((unavailable("You cannot directly instantiate an STPToken. You should only use one that has been returned from an STPAPIClient callback."))); +- (nonnull instancetype) init; /** * The value of the token. You can store this value on your server and use it to make charges and customers. @see diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 2be2255adb..0b08446fb0 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -1306,7 +1306,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { strongSelf.requestCall(movingFromBroadcastToRtc: false) } } - }, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, enableVideo: self.isVideoEnabled, enableNoiseSuppression: enableNoiseSuppression) + }, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, videoContentType: self.isVideoEnabled ? .generic : .none, enableNoiseSuppression: enableNoiseSuppression) self.incomingVideoSourcePromise.set(callContext.videoSources |> deliverOnMainQueue |> map { [weak self] sources -> [PeerId: UInt32] in @@ -1852,6 +1852,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } else if participant.muteState?.mutedByYou == true { strongSelf.callContext?.setVolume(ssrc: ssrc, volume: 0.0) } + if participant.isVideoMuted { + strongSelf.callContext?.removeIncomingVideoSource(ssrc) + } } } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 7bf7dba6f1..ed38917dec 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1970,6 +1970,16 @@ public final class VoiceChatController: ViewController { }) } } + + var removeRequestedVideoSources: [UInt32] = [] + for source in strongSelf.requestedVideoSources { + if !validSources.contains(source) { + removeRequestedVideoSources.append(source) + } + } + for source in removeRequestedVideoSources { + strongSelf.requestedVideoSources.remove(source) + } var updated = false for i in (0 ..< strongSelf.videoNodes.count).reversed() { @@ -3194,6 +3204,18 @@ public final class VoiceChatController: ViewController { }) self.controller?.present(controller, in: .window(.root)) } + return; + let controller = voiceChatCameraPreviewController(sharedContext: self.context.sharedContext, account: self.context.account, forceTheme: self.darkTheme, title: self.presentationData.strings.VoiceChat_VideoPreviewTitle, text: self.presentationData.strings.VoiceChat_VideoPreviewDescription, apply: { [weak self] in + guard let strongSelf = self else { + return + } + if strongSelf.call.isVideo { + strongSelf.call.disableVideo() + } else { + strongSelf.call.requestVideo() + } + }) + self.controller?.present(controller, in: .window(.root)) } @objc private func switchCameraPressed() { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift index ddba476d72..3366dd3ce6 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift @@ -1585,6 +1585,8 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode { } })) } + } else { + strongSelf.avatarNode.alpha = 1.0 } if item.style == .list { diff --git a/submodules/TelegramCore/Sources/CachedChannelParticipants.swift b/submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift similarity index 100% rename from submodules/TelegramCore/Sources/CachedChannelParticipants.swift rename to submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift diff --git a/submodules/TelegramCore/Sources/CachedGroupParticipants.swift b/submodules/TelegramCore/Sources/ApiUtils/CachedGroupParticipants.swift similarity index 100% rename from submodules/TelegramCore/Sources/CachedGroupParticipants.swift rename to submodules/TelegramCore/Sources/ApiUtils/CachedGroupParticipants.swift diff --git a/submodules/TelegramCore/Sources/CloudFileMediaResource.swift b/submodules/TelegramCore/Sources/ApiUtils/CloudFileMediaResource.swift similarity index 100% rename from submodules/TelegramCore/Sources/CloudFileMediaResource.swift rename to submodules/TelegramCore/Sources/ApiUtils/CloudFileMediaResource.swift diff --git a/submodules/TelegramCore/Sources/CloudMediaResourceParameters.swift b/submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift similarity index 100% rename from submodules/TelegramCore/Sources/CloudMediaResourceParameters.swift rename to submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift diff --git a/submodules/TelegramCore/Sources/EncryptedMediaResource.swift b/submodules/TelegramCore/Sources/ApiUtils/EncryptedMediaResource.swift similarity index 100% rename from submodules/TelegramCore/Sources/EncryptedMediaResource.swift rename to submodules/TelegramCore/Sources/ApiUtils/EncryptedMediaResource.swift diff --git a/submodules/TelegramCore/Sources/ImageRepresentationWithReference.swift b/submodules/TelegramCore/Sources/ApiUtils/ImageRepresentationWithReference.swift similarity index 100% rename from submodules/TelegramCore/Sources/ImageRepresentationWithReference.swift rename to submodules/TelegramCore/Sources/ApiUtils/ImageRepresentationWithReference.swift diff --git a/submodules/TelegramCore/Sources/Authorization.swift b/submodules/TelegramCore/Sources/Authorization.swift index a921cdf250..fd9d45105b 100644 --- a/submodules/TelegramCore/Sources/Authorization.swift +++ b/submodules/TelegramCore/Sources/Authorization.swift @@ -31,6 +31,44 @@ func switchToAuthorizedAccount(transaction: AccountManagerModifier, account: Una transaction.removeAuth() } +private struct Regex { + let pattern: String + let options: NSRegularExpression.Options! + + private var matcher: NSRegularExpression { + return try! NSRegularExpression(pattern: self.pattern, options: self.options) + } + + init(_ pattern: String) { + self.pattern = pattern + self.options = [] + } + + func match(_ string: String, options: NSRegularExpression.MatchingOptions = []) -> Bool { + return self.matcher.numberOfMatches(in: string, options: options, range: NSMakeRange(0, string.utf16.count)) != 0 + } +} + +private protocol RegularExpressionMatchable { + func match(_ regex: Regex) -> Bool +} + +private struct MatchString: RegularExpressionMatchable { + private let string: String + + init(_ string: String) { + self.string = string + } + + func match(_ regex: Regex) -> Bool { + return regex.match(self.string) + } +} + +private func ~=(pattern: Regex, matchable: T) -> Bool { + return matchable.match(pattern) +} + public func sendAuthorizationCode(accountManager: AccountManager, account: UnauthorizedAccount, phoneNumber: String, apiId: Int32, apiHash: String, syncContacts: Bool) -> Signal { let sendCode = Api.functions.auth.sendCode(phoneNumber: phoneNumber, apiId: apiId, apiHash: apiHash, settings: .codeSettings(flags: 0)) @@ -39,7 +77,7 @@ public func sendAuthorizationCode(accountManager: AccountManager, account: Unaut return (result, account) } |> `catch` { error -> Signal<(Api.auth.SentCode, UnauthorizedAccount), MTRpcError> in - switch (error.errorDescription ?? "") { + switch MatchString(error.errorDescription ?? "") { case Regex("(PHONE_|USER_|NETWORK_)MIGRATE_(\\d+)"): let range = error.errorDescription.range(of: "MIGRATE_")! let updatedMasterDatacenterId = Int32(error.errorDescription[range.upperBound ..< error.errorDescription.endIndex])! @@ -85,7 +123,6 @@ public func sendAuthorizationCode(accountManager: AccountManager, account: Unaut return account } |> mapError { _ -> AuthorizationCodeRequestError in - return .generic(info: nil) } } } @@ -123,7 +160,7 @@ public func resendAuthorizationCode(account: UnauthorizedAccount) -> Signal mapError { _ -> AuthorizationCodeRequestError in return .generic(info: nil) } + } |> mapError { _ -> AuthorizationCodeRequestError in } } } else { return .fail(.generic(info: nil)) @@ -136,7 +173,6 @@ public func resendAuthorizationCode(account: UnauthorizedAccount) -> Signal mapError { _ -> AuthorizationCodeRequestError in - return .generic(info: nil) } |> switchToLatest } @@ -233,7 +269,6 @@ public func authorizeWithCode(accountManager: AccountManager, account: Unauthori } |> switchToLatest |> mapError { _ -> AuthorizationCodeVerificationError in - return .generic } } default: @@ -244,7 +279,6 @@ public func authorizeWithCode(accountManager: AccountManager, account: Unauthori } } |> mapError { _ -> AuthorizationCodeVerificationError in - return .generic } |> switchToLatest } @@ -294,7 +328,6 @@ public func authorizeWithPassword(accountManager: AccountManager, account: Unaut } |> switchToLatest |> mapError { _ -> AuthorizationPasswordVerificationError in - return .generic } } } @@ -369,7 +402,7 @@ public func performPasswordRecovery(accountManager: AccountManager, account: Una } } |> switchToLatest - |> mapError { _ in return PasswordRecoveryError.expired } + |> mapError { _ -> PasswordRecoveryError in } } } @@ -418,7 +451,7 @@ public func performAccountReset(account: UnauthorizedAccount) -> Signal mapError { _ in return AccountResetError.generic } + |> mapError { _ -> AccountResetError in } } } @@ -497,7 +530,6 @@ public func signUpWithName(accountManager: AccountManager, account: Unauthorized } } |> mapError { _ -> SignUpError in - return .generic } |> switchToLatest } diff --git a/submodules/TelegramCore/Sources/FetchedMediaResource.swift b/submodules/TelegramCore/Sources/FetchedMediaResource.swift index 0adc130a3c..8196b509b6 100644 --- a/submodules/TelegramCore/Sources/FetchedMediaResource.swift +++ b/submodules/TelegramCore/Sources/FetchedMediaResource.swift @@ -369,7 +369,7 @@ final class MediaReferenceRevalidationContext { func peer(postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal { return self.genericItem(key: .peer(peer: peer), background: background, request: { next, error in - return (updatedRemotePeer(postbox: postbox, network: network, peer: peer) + return (_internal_updatedRemotePeer(postbox: postbox, network: network, peer: peer) |> mapError { _ -> RevalidateMediaReferenceError in return .generic }).start(next: { value in diff --git a/submodules/TelegramCore/Sources/HistoryViewStateValidation.swift b/submodules/TelegramCore/Sources/HistoryViewStateValidation.swift index b5988b23ae..9dfa747529 100644 --- a/submodules/TelegramCore/Sources/HistoryViewStateValidation.swift +++ b/submodules/TelegramCore/Sources/HistoryViewStateValidation.swift @@ -832,7 +832,7 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: updatedTags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) } else { - deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id]) + _internal_deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id]) Logger.shared.log("HistoryValidation", "deleting message \(id) in \(id.peerId)") } } @@ -1011,7 +1011,7 @@ private func validateReplyThreadBatch(postbox: Postbox, network: Network, transa for id in removedMessageIds { if !validMessageIds.contains(id) { - deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id]) + _internal_deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id]) Logger.shared.log("HistoryValidation", "deleting thread message \(id) in \(id.peerId)") } } diff --git a/submodules/TelegramCore/Sources/InstallInteractiveReadMessagesAction.swift b/submodules/TelegramCore/Sources/InstallInteractiveReadMessagesAction.swift index ec862edad0..fd5a79dc92 100644 --- a/submodules/TelegramCore/Sources/InstallInteractiveReadMessagesAction.swift +++ b/submodules/TelegramCore/Sources/InstallInteractiveReadMessagesAction.swift @@ -56,7 +56,7 @@ public func installInteractiveReadMessagesAction(postbox: Postbox, stateManager: } for (_, index) in readMessageIndexByNamespace { - applyMaxReadIndexInteractively(transaction: transaction, stateManager: stateManager, index: index) + _internal_applyMaxReadIndexInteractively(transaction: transaction, stateManager: stateManager, index: index) } }) } diff --git a/submodules/TelegramCore/Sources/MacInternalUpdater.swift b/submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift similarity index 100% rename from submodules/TelegramCore/Sources/MacInternalUpdater.swift rename to submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift diff --git a/submodules/TelegramCore/Sources/ChatUpdatingMessageMedia.swift b/submodules/TelegramCore/Sources/PendingMessages/ChatUpdatingMessageMedia.swift similarity index 100% rename from submodules/TelegramCore/Sources/ChatUpdatingMessageMedia.swift rename to submodules/TelegramCore/Sources/PendingMessages/ChatUpdatingMessageMedia.swift diff --git a/submodules/TelegramCore/Sources/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift similarity index 99% rename from submodules/TelegramCore/Sources/EnqueueMessage.swift rename to submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index 7c66f0c083..3599c947c6 100644 --- a/submodules/TelegramCore/Sources/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -260,7 +260,7 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal< } let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages.map { (false, $0) }) } - deleteMessages(transaction: transaction, mediaBox: account.postbox.mediaBox, ids: removeMessageIds, deleteMedia: false) + _internal_deleteMessages(transaction: transaction, mediaBox: account.postbox.mediaBox, ids: removeMessageIds, deleteMedia: false) } } diff --git a/submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift similarity index 100% rename from submodules/TelegramCore/Sources/PendingMessageUploadedContent.swift rename to submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift diff --git a/submodules/TelegramCore/Sources/PendingUpdateMessageManager.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/PendingUpdateMessageManager.swift rename to submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift diff --git a/submodules/TelegramCore/Sources/RequestEditMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift similarity index 96% rename from submodules/TelegramCore/Sources/RequestEditMessage.swift rename to submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift index 69ffc23c06..a97ce331bb 100644 --- a/submodules/TelegramCore/Sources/RequestEditMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift @@ -28,7 +28,7 @@ public enum RequestEditMessageError { case invalidGrouping } -public func requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { +func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) } @@ -255,7 +255,7 @@ private func requestEditMessageInternal(postbox: Postbox, network: Network, stat } } -public func requestEditLiveLocation(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal { +func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal { return postbox.transaction { transaction -> (Api.InputPeer, TelegramMediaMap)? in guard let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) else { return nil diff --git a/submodules/TelegramCore/Sources/StandaloneSendMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift similarity index 100% rename from submodules/TelegramCore/Sources/StandaloneSendMessage.swift rename to submodules/TelegramCore/Sources/PendingMessages/StandaloneSendMessage.swift diff --git a/submodules/TelegramCore/Sources/StandaloneUploadedMedia.swift b/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift similarity index 100% rename from submodules/TelegramCore/Sources/StandaloneUploadedMedia.swift rename to submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift diff --git a/submodules/TelegramCore/Sources/Regex.swift b/submodules/TelegramCore/Sources/Regex.swift deleted file mode 100644 index 474e383e1f..0000000000 --- a/submodules/TelegramCore/Sources/Regex.swift +++ /dev/null @@ -1,33 +0,0 @@ -import Foundation - -public struct Regex { - let pattern: String - let options: NSRegularExpression.Options! - - private var matcher: NSRegularExpression { - return try! NSRegularExpression(pattern: self.pattern, options: self.options) - } - - public init(_ pattern: String) { - self.pattern = pattern - self.options = [] - } - - public func match(_ string: String, options: NSRegularExpression.MatchingOptions = []) -> Bool { - return self.matcher.numberOfMatches(in: string, options: options, range: NSMakeRange(0, string.utf16.count)) != 0 - } -} - -public protocol RegularExpressionMatchable { - func match(_ regex: Regex) -> Bool -} - -extension String: RegularExpressionMatchable { - public func match(_ regex: Regex) -> Bool { - return regex.match(self) - } -} - -public func ~=(pattern: Regex, matchable: T) -> Bool { - return matchable.match(pattern) -} diff --git a/submodules/TelegramCore/Sources/RemovePeerChat.swift b/submodules/TelegramCore/Sources/RemovePeerChat.swift index 0cae498d09..1b72cd2cdd 100644 --- a/submodules/TelegramCore/Sources/RemovePeerChat.swift +++ b/submodules/TelegramCore/Sources/RemovePeerChat.swift @@ -58,17 +58,17 @@ public func removePeerChat(account: Account, transaction: Transaction, mediaBox: } } } - clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue) } else { cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible) if peerId.namespace == Namespaces.Peer.CloudUser { transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) - clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) } else if peerId.namespace == Namespaces.Peer.CloudGroup { transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) - clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) } else { transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) } diff --git a/submodules/TelegramCore/Sources/RequestPhoneNumber.swift b/submodules/TelegramCore/Sources/RequestPhoneNumber.swift deleted file mode 100644 index 575f55a634..0000000000 --- a/submodules/TelegramCore/Sources/RequestPhoneNumber.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation -import Postbox -import SwiftSignalKit -import TelegramApi - -public func requestPhoneNumber(account: Account, peerId: PeerId) -> Signal { - return .never() - /*return account.postbox.transaction { transaction -> Api.InputPeer? in - return transaction.getPeer(peerId).flatMap(apiInputPeer) - } - |> mapToSignal { inputPeer -> Signal in - guard let inputPeer = inputPeer else { - return .complete() - } - return account.network.request(Api.functions.messages.sendPhoneNumberRequest(peer: inputPeer, randomId: Int64.random(in: Int64.min ... Int64.max))) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) - } - |> mapToSignal { updates -> Signal in - if let updates = updates { - account.stateManager.addUpdates(updates) - } - return .complete() - } - }*/ -} - diff --git a/submodules/TelegramCore/Sources/SecretChats/UpdateSecretChat.swift b/submodules/TelegramCore/Sources/SecretChats/UpdateSecretChat.swift index 7157b2735a..17a937f8f1 100644 --- a/submodules/TelegramCore/Sources/SecretChats/UpdateSecretChat.swift +++ b/submodules/TelegramCore/Sources/SecretChats/UpdateSecretChat.swift @@ -78,7 +78,7 @@ func updateSecretChat(encryptionProvider: EncryptionProvider, accountPeerId: Pee if isRemoved { let peerId = currentPeer.id - clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue) } diff --git a/submodules/TelegramCore/Sources/SingleMessageView.swift b/submodules/TelegramCore/Sources/SingleMessageView.swift deleted file mode 100644 index 203daf6bce..0000000000 --- a/submodules/TelegramCore/Sources/SingleMessageView.swift +++ /dev/null @@ -1,105 +0,0 @@ -import Foundation -import Postbox -import SwiftSignalKit -import TelegramApi -import MtProtoKit - -import SyncCore - -public func singleMessageView(account: Account, messageId: MessageId, loadIfNotExists: Bool) -> Signal { - return Signal { subscriber in - let loadedMessage = account.postbox.transaction { transaction -> Signal in - if transaction.getMessage(messageId) == nil, loadIfNotExists { - return fetchMessage(transaction: transaction, account: account, messageId: messageId) - } else { - return .complete() - } - } |> switchToLatest - - let disposable = loadedMessage.start() - let viewDisposable = account.postbox.messageView(messageId).start(next: { view in - subscriber.putNext(view) - }) - - return ActionDisposable { - disposable.dispose() - viewDisposable.dispose() - } - } -} - -private func fetchMessage(transaction: Transaction, account: Account, messageId: MessageId) -> Signal { - if let peer = transaction.getPeer(messageId.peerId) { - var signal: Signal? - if messageId.namespace == Namespaces.Message.ScheduledCloud { - if let inputPeer = apiInputPeer(peer) { - signal = account.network.request(Api.functions.messages.getScheduledMessages(peer: inputPeer, id: [messageId.id])) - } - } else if messageId.peerId.namespace == Namespaces.Peer.CloudUser || messageId.peerId.namespace == Namespaces.Peer.CloudGroup { - signal = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)])) - } else if messageId.peerId.namespace == Namespaces.Peer.CloudChannel { - if let inputChannel = apiInputChannel(peer) { - signal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: [Api.InputMessage.inputMessageID(id: messageId.id)])) - } - } - if let signal = signal { - return signal - |> `catch` { _ -> Signal in - return .single(.messages(messages: [], chats: [], users: [])) - } - |> mapToSignal { result -> Signal in - return account.postbox.transaction { transaction -> Void in - let apiMessages: [Api.Message] - let apiChats: [Api.Chat] - let apiUsers: [Api.User] - switch result { - case let .messages(messages, chats, users): - apiMessages = messages - apiChats = chats - apiUsers = users - case let .messagesSlice(_, _, _, _, messages, chats, users): - apiMessages = messages - apiChats = chats - apiUsers = users - case let .channelMessages(_, _, _, _, messages, chats, users): - apiMessages = messages - apiChats = chats - apiUsers = users - case .messagesNotModified: - apiMessages = [] - apiChats = [] - apiUsers = [] - } - - var peers: [PeerId: Peer] = [:] - - for user in apiUsers { - if let user = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) { - peers[user.id] = user - } - } - - for chat in apiChats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers[groupOrChannel.id] = groupOrChannel - } - } - - updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in - return updated - }) - - for message in apiMessages { - if let message = StoreMessage(apiMessage: message, namespace: messageId.namespace) { - let _ = transaction.addMessages([message], location: .Random) - } - } - } - } - } else { - return .complete() - } - } else { - return .complete() - } -} diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 3117d853df..1a5c57a4aa 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -2490,7 +2490,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP } deletedMessageIds.append(contentsOf: ids.map { .global($0) }) case let .DeleteMessages(ids): - deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: ids, manualAddMessageThreadStatsDifference: { id, add, remove in + _internal_deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: ids, manualAddMessageThreadStatsDifference: { id, add, remove in addMessageThreadStatsDifference(threadMessageId: id, remove: remove, addedMessagePeer: nil, addedMessageId: nil, isOutgoing: false) }) deletedMessageIds.append(contentsOf: ids.map { .messageId($0) }) diff --git a/submodules/TelegramCore/Sources/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift similarity index 100% rename from submodules/TelegramCore/Sources/AccountViewTracker.swift rename to submodules/TelegramCore/Sources/State/AccountViewTracker.swift diff --git a/submodules/TelegramCore/Sources/ApplyUpdateMessage.swift b/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift similarity index 100% rename from submodules/TelegramCore/Sources/ApplyUpdateMessage.swift rename to submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift diff --git a/submodules/TelegramCore/Sources/CachedSentMediaReferences.swift b/submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift similarity index 100% rename from submodules/TelegramCore/Sources/CachedSentMediaReferences.swift rename to submodules/TelegramCore/Sources/State/CachedSentMediaReferences.swift diff --git a/submodules/TelegramCore/Sources/CallSessionManager.swift b/submodules/TelegramCore/Sources/State/CallSessionManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/CallSessionManager.swift rename to submodules/TelegramCore/Sources/State/CallSessionManager.swift diff --git a/submodules/TelegramCore/Sources/CloudChatRemoveMessagesOperation.swift b/submodules/TelegramCore/Sources/State/CloudChatRemoveMessagesOperation.swift similarity index 100% rename from submodules/TelegramCore/Sources/CloudChatRemoveMessagesOperation.swift rename to submodules/TelegramCore/Sources/State/CloudChatRemoveMessagesOperation.swift diff --git a/submodules/TelegramCore/Sources/ContactSyncManager.swift b/submodules/TelegramCore/Sources/State/ContactSyncManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/ContactSyncManager.swift rename to submodules/TelegramCore/Sources/State/ContactSyncManager.swift diff --git a/submodules/TelegramCore/Sources/Fetch.swift b/submodules/TelegramCore/Sources/State/Fetch.swift similarity index 100% rename from submodules/TelegramCore/Sources/Fetch.swift rename to submodules/TelegramCore/Sources/State/Fetch.swift diff --git a/submodules/TelegramCore/Sources/FetchChatList.swift b/submodules/TelegramCore/Sources/State/FetchChatList.swift similarity index 100% rename from submodules/TelegramCore/Sources/FetchChatList.swift rename to submodules/TelegramCore/Sources/State/FetchChatList.swift diff --git a/submodules/TelegramCore/Sources/FetchSecretFileResource.swift b/submodules/TelegramCore/Sources/State/FetchSecretFileResource.swift similarity index 100% rename from submodules/TelegramCore/Sources/FetchSecretFileResource.swift rename to submodules/TelegramCore/Sources/State/FetchSecretFileResource.swift diff --git a/submodules/TelegramCore/Sources/Holes.swift b/submodules/TelegramCore/Sources/State/Holes.swift similarity index 100% rename from submodules/TelegramCore/Sources/Holes.swift rename to submodules/TelegramCore/Sources/State/Holes.swift diff --git a/submodules/TelegramCore/Sources/InitializeAccountAfterLogin.swift b/submodules/TelegramCore/Sources/State/InitializeAccountAfterLogin.swift similarity index 100% rename from submodules/TelegramCore/Sources/InitializeAccountAfterLogin.swift rename to submodules/TelegramCore/Sources/State/InitializeAccountAfterLogin.swift diff --git a/submodules/TelegramCore/Sources/State/ManagedAutoremoveMessageOperations.swift b/submodules/TelegramCore/Sources/State/ManagedAutoremoveMessageOperations.swift index a610a0dd9f..6d739dd4a3 100644 --- a/submodules/TelegramCore/Sources/State/ManagedAutoremoveMessageOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedAutoremoveMessageOperations.swift @@ -83,7 +83,7 @@ func managedAutoremoveMessageOperations(network: Network, postbox: Postbox, isRe if let message = transaction.getMessage(entry.messageId) { if message.id.peerId.namespace == Namespaces.Peer.SecretChat || isRemove { - deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [entry.messageId]) + _internal_deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [entry.messageId]) } else { transaction.updateMessage(message.id, update: { currentMessage in var storeForwardInfo: StoreMessageForwardInfo? diff --git a/submodules/TelegramCore/Sources/State/ManagedCloudChatRemoveMessagesOperations.swift b/submodules/TelegramCore/Sources/State/ManagedCloudChatRemoveMessagesOperations.swift index ab4e02c849..eb40e138ec 100644 --- a/submodules/TelegramCore/Sources/State/ManagedCloudChatRemoveMessagesOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedCloudChatRemoveMessagesOperations.swift @@ -96,7 +96,7 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network } } else if let operation = entry.contents as? CloudChatClearHistoryOperation { if let peer = transaction.getPeer(entry.peerId) { - return clearHistory(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, peer: peer, operation: operation) + return _internal_clearHistory(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, peer: peer, operation: operation) } else { return .complete() } @@ -311,7 +311,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net |> then(deleteUser) |> then(reportSignal) |> then(postbox.transaction { transaction -> Void in - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .all) }) } else if peer.id.namespace == Namespaces.Peer.CloudUser { if let inputPeer = apiInputPeer(peer) { @@ -330,7 +330,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net return requestClearHistory(postbox: postbox, network: network, stateManager: stateManager, inputPeer: inputPeer, maxId: operation.topMessageId?.id ?? Int32.max - 1, justClear: false, type: operation.deleteGloballyIfPossible ? .forEveryone : .forLocalPeer) |> then(reportSignal) |> then(postbox.transaction { transaction -> Void in - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .not(Namespaces.Message.allScheduled)) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peer.id, namespaces: .not(Namespaces.Message.allScheduled)) }) } else { return .complete() @@ -376,7 +376,7 @@ private func requestClearHistory(postbox: Postbox, network: Network, stateManage } } -private func clearHistory(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, peer: Peer, operation: CloudChatClearHistoryOperation) -> Signal { +private func _internal_clearHistory(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, peer: Peer, operation: CloudChatClearHistoryOperation) -> Signal { if peer.id.namespace == Namespaces.Peer.CloudGroup || peer.id.namespace == Namespaces.Peer.CloudUser { if let inputPeer = apiInputPeer(peer) { return requestClearHistory(postbox: postbox, network: network, stateManager: stateManager, inputPeer: inputPeer, maxId: operation.topMessageId.id, justClear: true, type: operation.type) diff --git a/submodules/TelegramCore/Sources/State/ManagedLocalizationUpdatesOperations.swift b/submodules/TelegramCore/Sources/State/ManagedLocalizationUpdatesOperations.swift index 4a95be5cf0..68157e0cfd 100644 --- a/submodules/TelegramCore/Sources/State/ManagedLocalizationUpdatesOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedLocalizationUpdatesOperations.swift @@ -228,7 +228,7 @@ private func synchronizeLocalizationUpdates(accountManager: AccountManager, post case .reset: return accountManager.transaction { transaction -> Signal in let (primary, _) = getLocalization(transaction) - return downloadAndApplyLocalization(accountManager: accountManager, postbox: postbox, network: network, languageCode: primary.code) + return _internal_downloadAndApplyLocalization(accountManager: accountManager, postbox: postbox, network: network, languageCode: primary.code) |> mapError { _ -> Void in return Void() } diff --git a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift index 618a7b35a8..4643230e25 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift @@ -1520,7 +1520,7 @@ private func sendMessage(auxiliaryMethods: AccountAuxiliaryMethods, postbox: Pos } } else { replaceOutgoingOperationWithEmptyMessage(transaction: transaction, peerId: messageId.peerId, tagLocalIndex: tagLocalIndex, globallyUniqueId: Int64.random(in: Int64.min ... Int64.max)) - deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [messageId]) + _internal_deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [messageId]) return .complete() } } else { diff --git a/submodules/TelegramCore/Sources/PendingMessageManager.swift b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/PendingMessageManager.swift rename to submodules/TelegramCore/Sources/State/PendingMessageManager.swift diff --git a/submodules/TelegramCore/Sources/ProcessSecretChatIncomingDecryptedOperations.swift b/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift similarity index 99% rename from submodules/TelegramCore/Sources/ProcessSecretChatIncomingDecryptedOperations.swift rename to submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift index dafc41c794..0a5eb061d6 100644 --- a/submodules/TelegramCore/Sources/ProcessSecretChatIncomingDecryptedOperations.swift +++ b/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingDecryptedOperations.swift @@ -276,10 +276,10 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption } } } - deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds) + _internal_deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: filteredMessageIds) } case .clearHistory: - clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId, namespaces: .all) case let .markMessagesContentAsConsumed(globallyUniqueIds): var messageIds: [MessageId] = [] for id in globallyUniqueIds { diff --git a/submodules/TelegramCore/Sources/ProcessSecretChatIncomingEncryptedOperations.swift b/submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingEncryptedOperations.swift similarity index 100% rename from submodules/TelegramCore/Sources/ProcessSecretChatIncomingEncryptedOperations.swift rename to submodules/TelegramCore/Sources/State/ProcessSecretChatIncomingEncryptedOperations.swift diff --git a/submodules/TelegramCore/Sources/Serialization.swift b/submodules/TelegramCore/Sources/State/Serialization.swift similarity index 100% rename from submodules/TelegramCore/Sources/Serialization.swift rename to submodules/TelegramCore/Sources/State/Serialization.swift diff --git a/submodules/TelegramCore/Sources/State/StickerManagement.swift b/submodules/TelegramCore/Sources/State/StickerManagement.swift index ab3da0cac2..4aefb157f1 100644 --- a/submodules/TelegramCore/Sources/State/StickerManagement.swift +++ b/submodules/TelegramCore/Sources/State/StickerManagement.swift @@ -90,7 +90,7 @@ public func preloadedFeaturedStickerSet(network: Network, postbox: Postbox, id: return postbox.transaction { transaction -> Signal in if let pack = transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks, itemId: FeaturedStickerPackItemId(id.id).rawValue)?.contents as? FeaturedStickerPackItem { if pack.topItems.count < 5 && pack.topItems.count < pack.info.count { - return requestStickerSet(postbox: postbox, network: network, reference: .id(id: pack.info.id.id, accessHash: pack.info.accessHash)) + return _internal_requestStickerSet(postbox: postbox, network: network, reference: .id(id: pack.info.id.id, accessHash: pack.info.accessHash)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) diff --git a/submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift b/submodules/TelegramCore/Sources/State/UnauthorizedAccountStateManager.swift similarity index 100% rename from submodules/TelegramCore/Sources/UnauthorizedAccountStateManager.swift rename to submodules/TelegramCore/Sources/State/UnauthorizedAccountStateManager.swift diff --git a/submodules/TelegramCore/Sources/StickerPackCreation.swift b/submodules/TelegramCore/Sources/StickerPackCreation.swift deleted file mode 100644 index fecc4ab449..0000000000 --- a/submodules/TelegramCore/Sources/StickerPackCreation.swift +++ /dev/null @@ -1 +0,0 @@ -import Foundation diff --git a/submodules/TelegramCore/Sources/LocalizationInfo.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationInfo.swift similarity index 100% rename from submodules/TelegramCore/Sources/LocalizationInfo.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationInfo.swift diff --git a/submodules/TelegramCore/Sources/LocalizationListState.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationListState.swift similarity index 96% rename from submodules/TelegramCore/Sources/LocalizationListState.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationListState.swift index 662173ff39..090e40a0cb 100644 --- a/submodules/TelegramCore/Sources/LocalizationListState.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationListState.swift @@ -51,7 +51,7 @@ func updateLocalizationListStateInteractively(transaction: Transaction, _ f: @es }) } -public func synchronizedLocalizationListState(postbox: Postbox, network: Network) -> Signal { +func _internal_synchronizedLocalizationListState(postbox: Postbox, network: Network) -> Signal { return network.request(Api.functions.langpack.getLanguages(langPack: "")) |> retryRequest |> mapToSignal { languages -> Signal in diff --git a/submodules/TelegramCore/Sources/LocalizationPreview.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationPreview.swift similarity index 76% rename from submodules/TelegramCore/Sources/LocalizationPreview.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationPreview.swift index 919c74c013..b6aa82f737 100644 --- a/submodules/TelegramCore/Sources/LocalizationPreview.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/LocalizationPreview.swift @@ -9,7 +9,7 @@ public enum RequestLocalizationPreviewError { case generic } -public func requestLocalizationPreview(network: Network, identifier: String) -> Signal { +func _internal_requestLocalizationPreview(network: Network, identifier: String) -> Signal { return network.request(Api.functions.langpack.getLanguage(langPack: "", langCode: identifier)) |> mapError { _ -> RequestLocalizationPreviewError in return .generic diff --git a/submodules/TelegramCore/Sources/Localizations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift similarity index 85% rename from submodules/TelegramCore/Sources/Localizations.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift index 4f6e4fdef6..fa98c35845 100644 --- a/submodules/TelegramCore/Sources/Localizations.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/Localizations.swift @@ -5,14 +5,14 @@ import SwiftSignalKit import SyncCore -public func currentlySuggestedLocalization(network: Network, extractKeys: [String]) -> Signal { +func _internal_currentlySuggestedLocalization(network: Network, extractKeys: [String]) -> Signal { return network.request(Api.functions.help.getConfig()) |> retryRequest |> mapToSignal { result -> Signal in switch result { case let .config(config): if let suggestedLangCode = config.suggestedLangCode { - return suggestedLocalizationInfo(network: network, languageCode: suggestedLangCode, extractKeys: extractKeys) |> map(Optional.init) + return _internal_suggestedLocalizationInfo(network: network, languageCode: suggestedLangCode, extractKeys: extractKeys) |> map(Optional.init) } else { return .single(nil) } @@ -20,7 +20,7 @@ public func currentlySuggestedLocalization(network: Network, extractKeys: [Strin } } -public func suggestedLocalizationInfo(network: Network, languageCode: String, extractKeys: [String]) -> Signal { +func _internal_suggestedLocalizationInfo(network: Network, languageCode: String, extractKeys: [String]) -> Signal { return combineLatest(network.request(Api.functions.langpack.getLanguages(langPack: "")), network.request(Api.functions.langpack.getStrings(langPack: "", langCode: languageCode, keys: extractKeys))) |> retryRequest |> map { languages, strings -> SuggestedLocalizationInfo in @@ -40,7 +40,7 @@ public func suggestedLocalizationInfo(network: Network, languageCode: String, ex } } -public func availableLocalizations(postbox: Postbox, network: Network, allowCached: Bool) -> Signal<[LocalizationInfo], NoError> { +func _internal_availableLocalizations(postbox: Postbox, network: Network, allowCached: Bool) -> Signal<[LocalizationInfo], NoError> { let cached: Signal<[LocalizationInfo], NoError> if allowCached { cached = postbox.transaction { transaction -> Signal<[LocalizationInfo], NoError> in @@ -69,7 +69,7 @@ public enum DownloadLocalizationError { case generic } -public func downloadLocalization(network: Network, languageCode: String) -> Signal { +func _internal_downloadLocalization(network: Network, languageCode: String) -> Signal { return network.request(Api.functions.langpack.getLangPack(langPack: "", langCode: languageCode)) |> mapError { _ -> DownloadLocalizationError in return .generic @@ -100,16 +100,16 @@ public enum DownloadAndApplyLocalizationError { case generic } -public func downloadAndApplyLocalization(accountManager: AccountManager, postbox: Postbox, network: Network, languageCode: String) -> Signal { - return requestLocalizationPreview(network: network, identifier: languageCode) +func _internal_downloadAndApplyLocalization(accountManager: AccountManager, postbox: Postbox, network: Network, languageCode: String) -> Signal { + return _internal_requestLocalizationPreview(network: network, identifier: languageCode) |> mapError { _ -> DownloadAndApplyLocalizationError in return .generic } |> mapToSignal { preview -> Signal in var primaryAndSecondaryLocalizations: [Signal] = [] - primaryAndSecondaryLocalizations.append(downloadLocalization(network: network, languageCode: preview.languageCode)) + primaryAndSecondaryLocalizations.append(_internal_downloadLocalization(network: network, languageCode: preview.languageCode)) if let secondaryCode = preview.baseLanguageCode { - primaryAndSecondaryLocalizations.append(downloadLocalization(network: network, languageCode: secondaryCode)) + primaryAndSecondaryLocalizations.append(_internal_downloadLocalization(network: network, languageCode: secondaryCode)) } return combineLatest(primaryAndSecondaryLocalizations) |> mapError { _ -> DownloadAndApplyLocalizationError in diff --git a/submodules/TelegramCore/Sources/SuggestedLocalizationEntry.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/SuggestedLocalizationEntry.swift similarity index 83% rename from submodules/TelegramCore/Sources/SuggestedLocalizationEntry.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Localization/SuggestedLocalizationEntry.swift index 6ba5d1d739..f5e225ab4c 100644 --- a/submodules/TelegramCore/Sources/SuggestedLocalizationEntry.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/SuggestedLocalizationEntry.swift @@ -4,7 +4,7 @@ import SwiftSignalKit import SyncCore -public func markSuggestedLocalizationAsSeenInteractively(postbox: Postbox, languageCode: String) -> Signal { +func _internal_markSuggestedLocalizationAsSeenInteractively(postbox: Postbox, languageCode: String) -> Signal { return postbox.transaction { transaction -> Void in transaction.updatePreferencesEntry(key: PreferencesKeys.suggestedLocalization, { current in if let current = current as? SuggestedLocalizationEntry { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Localization/TelegramEngineLocalization.swift b/submodules/TelegramCore/Sources/TelegramEngine/Localization/TelegramEngineLocalization.swift index 3f35e99178..699ffb7b3f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Localization/TelegramEngineLocalization.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Localization/TelegramEngineLocalization.swift @@ -1,5 +1,6 @@ import SwiftSignalKit import Postbox +import SyncCore public extension TelegramEngine { final class Localization { @@ -12,6 +13,26 @@ public extension TelegramEngine { public func getCountriesList(accountManager: AccountManager, langCode: String?, forceUpdate: Bool = false) -> Signal<[Country], NoError> { return _internal_getCountriesList(accountManager: accountManager, network: self.account.network, langCode: langCode, forceUpdate: forceUpdate) } + + public func markSuggestedLocalizationAsSeenInteractively(languageCode: String) -> Signal { + return _internal_markSuggestedLocalizationAsSeenInteractively(postbox: self.account.postbox, languageCode: languageCode) + } + + public func synchronizedLocalizationListState() -> Signal { + return _internal_synchronizedLocalizationListState(postbox: self.account.postbox, network: self.account.network) + } + + public func suggestedLocalizationInfo(languageCode: String, extractKeys: [String]) -> Signal { + return _internal_suggestedLocalizationInfo(network: self.account.network, languageCode: languageCode, extractKeys: extractKeys) + } + + public func requestLocalizationPreview(identifier: String) -> Signal { + return _internal_requestLocalizationPreview(network: self.account.network, identifier: identifier) + } + + public func downloadAndApplyLocalization(accountManager: AccountManager, languageCode: String) -> Signal { + return _internal_downloadAndApplyLocalization(accountManager: accountManager, postbox: self.account.postbox, network: self.account.network, languageCode: languageCode) + } } } @@ -26,5 +47,17 @@ public extension TelegramEngineUnauthorized { public func getCountriesList(accountManager: AccountManager, langCode: String?, forceUpdate: Bool = false) -> Signal<[Country], NoError> { return _internal_getCountriesList(accountManager: accountManager, network: self.account.network, langCode: langCode, forceUpdate: forceUpdate) } + + public func markSuggestedLocalizationAsSeenInteractively(languageCode: String) -> Signal { + return _internal_markSuggestedLocalizationAsSeenInteractively(postbox: self.account.postbox, languageCode: languageCode) + } + + public func currentlySuggestedLocalization(extractKeys: [String]) -> Signal { + return _internal_currentlySuggestedLocalization(network: self.account.network, extractKeys: extractKeys) + } + + public func downloadAndApplyLocalization(accountManager: AccountManager, languageCode: String) -> Signal { + return _internal_downloadAndApplyLocalization(accountManager: accountManager, postbox: self.account.postbox, network: self.account.network, languageCode: languageCode) + } } } diff --git a/submodules/TelegramCore/Sources/ApplyMaxReadIndexInteractively.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift similarity index 96% rename from submodules/TelegramCore/Sources/ApplyMaxReadIndexInteractively.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift index c00e1ca67f..ea804adba5 100644 --- a/submodules/TelegramCore/Sources/ApplyMaxReadIndexInteractively.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ApplyMaxReadIndexInteractively.swift @@ -5,13 +5,13 @@ import SwiftSignalKit import SyncCore -public func applyMaxReadIndexInteractively(postbox: Postbox, stateManager: AccountStateManager, index: MessageIndex) -> Signal { +func _internal_applyMaxReadIndexInteractively(postbox: Postbox, stateManager: AccountStateManager, index: MessageIndex) -> Signal { return postbox.transaction { transaction -> Void in - applyMaxReadIndexInteractively(transaction: transaction, stateManager: stateManager, index: index) + _internal_applyMaxReadIndexInteractively(transaction: transaction, stateManager: stateManager, index: index) } } -func applyMaxReadIndexInteractively(transaction: Transaction, stateManager: AccountStateManager, index: MessageIndex) { +func _internal_applyMaxReadIndexInteractively(transaction: Transaction, stateManager: AccountStateManager, index: MessageIndex) { let messageIds = transaction.applyInteractiveReadMaxIndex(index) if index.id.peerId.namespace == Namespaces.Peer.SecretChat { let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) diff --git a/submodules/TelegramCore/Sources/ClearCloudDrafts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift similarity index 96% rename from submodules/TelegramCore/Sources/ClearCloudDrafts.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift index 7a5038ce2e..4f1942760b 100644 --- a/submodules/TelegramCore/Sources/ClearCloudDrafts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift @@ -5,7 +5,7 @@ import TelegramApi import SyncCore -public func clearCloudDraftsInteractively(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal { +func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal { return network.request(Api.functions.messages.getAllDrafts()) |> retryRequest |> mapToSignal { updates -> Signal in diff --git a/submodules/TelegramCore/Sources/DeleteMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessages.swift similarity index 89% rename from submodules/TelegramCore/Sources/DeleteMessages.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessages.swift index 787659c8e4..fc69b68f80 100644 --- a/submodules/TelegramCore/Sources/DeleteMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessages.swift @@ -23,7 +23,7 @@ func addMessageMediaResourceIdsToRemove(message: Message, resourceIds: inout [Wr } } -public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) { +func _internal_deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) { var resourceIds: [WrappedMediaResourceId] = [] if deleteMedia { for id in ids { @@ -57,7 +57,7 @@ public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [M }) } -public func deleteAllMessagesWithAuthor(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { +func _internal_deleteAllMessagesWithAuthor(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { var resourceIds: [WrappedMediaResourceId] = [] transaction.removeAllMessagesWithAuthor(peerId, authorId: authorId, namespace: namespace, forEachMedia: { media in addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) @@ -67,7 +67,7 @@ public func deleteAllMessagesWithAuthor(transaction: Transaction, mediaBox: Medi } } -public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, forwardAuthorId: PeerId, namespace: MessageId.Namespace) { +func _internal_deleteAllMessagesWithForwardAuthor(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, forwardAuthorId: PeerId, namespace: MessageId.Namespace) { var resourceIds: [WrappedMediaResourceId] = [] transaction.removeAllMessagesWithForwardAuthor(peerId, forwardAuthorId: forwardAuthorId, namespace: namespace, forEachMedia: { media in addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) @@ -77,7 +77,7 @@ public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, mediaBo } } -public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, namespaces: MessageIdNamespaces) { +func _internal_clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, namespaces: MessageIdNamespaces) { if peerId.namespace == Namespaces.Peer.SecretChat { var resourceIds: [WrappedMediaResourceId] = [] transaction.withAllMessages(peerId: peerId, { message in @@ -96,7 +96,7 @@ public enum ClearCallHistoryError { case generic } -public func clearCallHistory(account: Account, forEveryone: Bool) -> Signal { +func _internal_clearCallHistory(account: Account, forEveryone: Bool) -> Signal { return account.postbox.transaction { transaction -> Signal in var flags: Int32 = 0 if forEveryone { @@ -146,7 +146,7 @@ public enum SetChatMessageAutoremoveTimeoutError { case generic } -public func setChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal { +func _internal_setChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) } diff --git a/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift similarity index 87% rename from submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift index 64e3051ae1..4dd24abec2 100644 --- a/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift @@ -6,7 +6,7 @@ import MtProtoKit import SyncCore -public func deleteMessagesInteractively(account: Account, messageIds: [MessageId], type: InteractiveMessagesDeletionType, deleteAllInGroup: Bool = false) -> Signal { +func _internal_deleteMessagesInteractively(account: Account, messageIds: [MessageId], type: InteractiveMessagesDeletionType, deleteAllInGroup: Bool = false) -> Signal { return account.postbox.transaction { transaction -> Void in deleteMessagesInteractively(transaction: transaction, stateManager: account.stateManager, postbox: account.postbox, messageIds: messageIds, type: type, removeIfPossiblyDelivered: true) } @@ -88,7 +88,7 @@ func deleteMessagesInteractively(transaction: Transaction, stateManager: Account } } } - deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: messageIds) + _internal_deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: messageIds) stateManager?.notifyDeletedMessages(messageIds: messageIds) @@ -97,22 +97,22 @@ func deleteMessagesInteractively(transaction: Transaction, stateManager: Account } } -public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: InteractiveHistoryClearingType) -> Signal { +func _internal_clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: InteractiveHistoryClearingType) -> Signal { return postbox.transaction { transaction -> Void in if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel { cloudChatAddClearHistoryOperation(transaction: transaction, peerId: peerId, explicitTopMessageId: nil, type: CloudChatClearHistoryType(type)) if type == .scheduledMessages { - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .just(Namespaces.Message.allScheduled)) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .just(Namespaces.Message.allScheduled)) } else { var topIndex: MessageIndex? if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) { topIndex = topMessage.index } - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .not(Namespaces.Message.allScheduled)) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .not(Namespaces.Message.allScheduled)) if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference { cloudChatAddClearHistoryOperation(transaction: transaction, peerId: migrationReference.maxMessageId.peerId, explicitTopMessageId: MessageId(peerId: migrationReference.maxMessageId.peerId, namespace: migrationReference.maxMessageId.namespace, id: migrationReference.maxMessageId.id + 1), type: CloudChatClearHistoryType(type)) - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId, namespaces: .all) } if let topIndex = topIndex { if peerId.namespace == Namespaces.Peer.CloudUser { @@ -123,7 +123,7 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In } } } else if peerId.namespace == Namespaces.Peer.SecretChat { - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .all) + _internal_clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId, namespaces: .all) if let state = transaction.getPeerChatState(peerId) as? SecretChatState { var layer: SecretChatLayer? @@ -147,7 +147,7 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In } } -public func clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerId) -> Signal { +func _internal_clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let memberPeer = transaction.getPeer(memberId), let inputChannel = apiInputChannel(peer), let inputUser = apiInputUser(memberPeer) { @@ -178,7 +178,7 @@ public func clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerI |> `catch` { success -> Signal in if success { return account.postbox.transaction { transaction -> Void in - deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: account.postbox.mediaBox, peerId: peerId, authorId: memberId, namespace: Namespaces.Message.Cloud) + _internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: account.postbox.mediaBox, peerId: peerId, authorId: memberId, namespace: Namespaces.Message.Cloud) } } else { return .complete() diff --git a/submodules/TelegramCore/Sources/RequestMessageActionCallback.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestMessageActionCallback.swift similarity index 94% rename from submodules/TelegramCore/Sources/RequestMessageActionCallback.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestMessageActionCallback.swift index edfeaa6777..614c827368 100644 --- a/submodules/TelegramCore/Sources/RequestMessageActionCallback.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestMessageActionCallback.swift @@ -24,7 +24,7 @@ public enum MessageActionCallbackError { case userBlocked } -public func requestMessageActionCallbackPasswordCheck(account: Account, messageId: MessageId, isGame: Bool, data: MemoryBuffer?) -> Signal { +func _internal_requestMessageActionCallbackPasswordCheck(account: Account, messageId: MessageId, isGame: Bool, data: MemoryBuffer?) -> Signal { return account.postbox.loadedPeerWithId(messageId.peerId) |> castError(MessageActionCallbackError.self) |> take(1) @@ -72,7 +72,7 @@ public func requestMessageActionCallbackPasswordCheck(account: Account, messageI } } -public func requestMessageActionCallback(account: Account, messageId: MessageId, isGame :Bool, password: String?, data: MemoryBuffer?) -> Signal { +func _internal_requestMessageActionCallback(account: Account, messageId: MessageId, isGame :Bool, password: String?, data: MemoryBuffer?) -> Signal { return account.postbox.loadedPeerWithId(messageId.peerId) |> castError(MessageActionCallbackError.self) |> take(1) @@ -179,7 +179,7 @@ public enum MessageActionUrlSubject { case url(String) } -public func requestMessageActionUrlAuth(account: Account, subject: MessageActionUrlSubject) -> Signal { +func _internal_requestMessageActionUrlAuth(account: Account, subject: MessageActionUrlSubject) -> Signal { let request: Signal var flags: Int32 = 0 switch subject { @@ -221,7 +221,7 @@ public func requestMessageActionUrlAuth(account: Account, subject: MessageAction } } -public func acceptMessageActionUrlAuth(account: Account, subject: MessageActionUrlSubject, allowWriteAccess: Bool) -> Signal { +func _internal_acceptMessageActionUrlAuth(account: Account, subject: MessageActionUrlSubject, allowWriteAccess: Bool) -> Signal { var flags: Int32 = 0 if allowWriteAccess { flags |= Int32(1 << 0) diff --git a/submodules/TelegramCore/Sources/ScheduledMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ScheduledMessages.swift similarity index 98% rename from submodules/TelegramCore/Sources/ScheduledMessages.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/ScheduledMessages.swift index f8500bb722..65d6906e20 100644 --- a/submodules/TelegramCore/Sources/ScheduledMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ScheduledMessages.swift @@ -5,7 +5,7 @@ import TelegramApi import SyncCore -public func sendScheduledMessageNowInteractively(postbox: Postbox, messageId: MessageId) -> Signal { +func _internal_sendScheduledMessageNowInteractively(postbox: Postbox, messageId: MessageId) -> Signal { return postbox.transaction { transaction -> Void in transaction.setPendingMessageAction(type: .sendScheduledMessageImmediately, id: messageId, action: SendScheduledMessageImmediatelyAction()) } diff --git a/submodules/TelegramCore/Sources/SearchMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift similarity index 98% rename from submodules/TelegramCore/Sources/SearchMessages.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift index 21c73f7386..0d70dc6986 100644 --- a/submodules/TelegramCore/Sources/SearchMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift @@ -184,7 +184,7 @@ private func mergedResult(_ state: SearchMessagesState) -> SearchMessagesResult return SearchMessagesResult(messages: messages, readStates: readStates, totalCount: state.main.totalCount + (state.additional?.totalCount ?? 0), completed: state.main.completed && (state.additional?.completed ?? true)) } -public func searchMessages(account: Account, location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> { +func _internal_searchMessages(account: Account, location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> { let remoteSearchResult: Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> switch location { case let .peer(peerId, fromId, tags, topMsgId, minDate, maxDate): @@ -379,7 +379,7 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q } } -public func downloadMessage(postbox: Postbox, network: Network, messageId: MessageId) -> Signal { +func _internal_downloadMessage(postbox: Postbox, network: Network, messageId: MessageId) -> Signal { return postbox.transaction { transaction -> Message? in return transaction.getMessage(messageId) } |> mapToSignal { message in @@ -562,7 +562,7 @@ func fetchRemoteMessage(postbox: Postbox, source: FetchMessageHistoryHoleSource, } } -public func searchMessageIdByTimestamp(account: Account, peerId: PeerId, threadId: Int64?, timestamp: Int32) -> Signal { +func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, threadId: Int64?, timestamp: Int32) -> Signal { return account.postbox.transaction { transaction -> Signal in if peerId.namespace == Namespaces.Peer.SecretChat { return .single(transaction.findClosestMessageIdByTimestamp(peerId: peerId, timestamp: timestamp)) @@ -672,7 +672,7 @@ public enum UpdatedRemotePeerError { case generic } -public func updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerReference) -> Signal { +func _internal_updatedRemotePeer(postbox: Postbox, network: Network, peer: PeerReference) -> Signal { if let inputUser = peer.inputUser { return network.request(Api.functions.users.getUsers(id: [inputUser])) |> mapError { _ -> UpdatedRemotePeerError in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift new file mode 100644 index 0000000000..df12d4c2db --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -0,0 +1,89 @@ +import SwiftSignalKit +import Postbox +import SyncCore + +public extension TelegramEngine { + final class Messages { + private let account: Account + + init(account: Account) { + self.account = account + } + + public func clearCloudDraftsInteractively() -> Signal { + return _internal_clearCloudDraftsInteractively(postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId) + } + + public func applyMaxReadIndexInteractively(index: MessageIndex) -> Signal { + return _internal_applyMaxReadIndexInteractively(postbox: self.account.postbox, stateManager: self.account.stateManager, index: index) + } + + public func sendScheduledMessageNowInteractively(messageId: MessageId) -> Signal { + return _internal_sendScheduledMessageNowInteractively(postbox: self.account.postbox, messageId: messageId) + } + + public func requestMessageActionCallbackPasswordCheck(messageId: MessageId, isGame: Bool, data: MemoryBuffer?) -> Signal { + return _internal_requestMessageActionCallbackPasswordCheck(account: self.account, messageId: messageId, isGame: isGame, data: data) + } + + public func requestMessageActionCallback(messageId: MessageId, isGame: Bool, password: String?, data: MemoryBuffer?) -> Signal { + return _internal_requestMessageActionCallback(account: self.account, messageId: messageId, isGame: isGame, password: password, data: data) + } + + public func requestMessageActionUrlAuth(subject: MessageActionUrlSubject) -> Signal { + _internal_requestMessageActionUrlAuth(account: self.account, subject: subject) + } + + public func acceptMessageActionUrlAuth(subject: MessageActionUrlSubject, allowWriteAccess: Bool) -> Signal { + return _internal_acceptMessageActionUrlAuth(account: self.account, subject: subject, allowWriteAccess: allowWriteAccess) + } + + public func searchMessages(location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> { + return _internal_searchMessages(account: self.account, location: location, query: query, state: state, limit: limit) + } + + public func downloadMessage(messageId: MessageId) -> Signal { + return _internal_downloadMessage(postbox: self.account.postbox, network: self.account.network, messageId: messageId) + } + + public func searchMessageIdByTimestamp(peerId: PeerId, threadId: Int64?, timestamp: Int32) -> Signal { + return _internal_searchMessageIdByTimestamp(account: self.account, peerId: peerId, threadId: threadId, timestamp: timestamp) + } + + public func deleteMessages(transaction: Transaction, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) { + return _internal_deleteMessages(transaction: transaction, mediaBox: self.account.postbox.mediaBox, ids: ids, deleteMedia: deleteMedia, manualAddMessageThreadStatsDifference: manualAddMessageThreadStatsDifference) + } + + public func deleteAllMessagesWithAuthor(transaction: Transaction, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { + return _internal_deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, authorId: authorId, namespace: namespace) + } + + public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, peerId: PeerId, forwardAuthorId: PeerId, namespace: MessageId.Namespace) { + return _internal_deleteAllMessagesWithForwardAuthor(transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, forwardAuthorId: forwardAuthorId, namespace: namespace) + } + + public func clearCallHistory(forEveryone: Bool) -> Signal { + return _internal_clearCallHistory(account: self.account, forEveryone: forEveryone) + } + + public func deleteMessagesInteractively(messageIds: [MessageId], type: InteractiveMessagesDeletionType, deleteAllInGroup: Bool = false) -> Signal { + return _internal_deleteMessagesInteractively(account: self.account, messageIds: messageIds, type: type, deleteAllInGroup: deleteAllInGroup) + } + + public func clearHistoryInteractively(peerId: PeerId, type: InteractiveHistoryClearingType) -> Signal { + return _internal_clearHistoryInteractively(postbox: self.account.postbox, peerId: peerId, type: type) + } + + public func clearAuthorHistory(peerId: PeerId, memberId: PeerId) -> Signal { + return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId) + } + + public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { + return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) + } + + public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal { + return _internal_requestEditLiveLocation(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, messageId: messageId, stop: stop, coordinate: coordinate, heading: heading, proximityNotificationRadius: proximityNotificationRadius) + } + } +} diff --git a/submodules/TelegramCore/Sources/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift similarity index 96% rename from submodules/TelegramCore/Sources/BotPaymentForm.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index df130abd8f..b5a7c60e04 100644 --- a/submodules/TelegramCore/Sources/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -174,7 +174,7 @@ extension BotPaymentRequestedInfo { } } -public func fetchBotPaymentForm(postbox: Postbox, network: Network, messageId: MessageId, themeParams: [String: Any]?) -> Signal { +func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, messageId: MessageId, themeParams: [String: Any]?) -> Signal { return postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) } @@ -269,7 +269,7 @@ extension BotPaymentShippingOption { } } -public func validateBotPaymentForm(account: Account, saveInfo: Bool, messageId: MessageId, formInfo: BotPaymentRequestedInfo) -> Signal { +func _internal_validateBotPaymentForm(account: Account, saveInfo: Bool, messageId: MessageId, formInfo: BotPaymentRequestedInfo) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) } @@ -347,7 +347,7 @@ public enum SendBotPaymentResult { case externalVerificationRequired(url: String) } -public func sendBotPaymentForm(account: Account, messageId: MessageId, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal { +func _internal_sendBotPaymentForm(account: Account, messageId: MessageId, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) } @@ -461,7 +461,7 @@ public enum RequestBotPaymentReceiptError { case generic } -public func requestBotPaymentReceipt(account: Account, messageId: MessageId) -> Signal { +func _internal_requestBotPaymentReceipt(account: Account, messageId: MessageId) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) } @@ -545,7 +545,7 @@ public struct BotPaymentInfo: OptionSet { public static let shippingInfo = BotPaymentInfo(rawValue: 1 << 1) } -public func clearBotPaymentInfo(network: Network, info: BotPaymentInfo) -> Signal { +func _internal_clearBotPaymentInfo(network: Network, info: BotPaymentInfo) -> Signal { var flags: Int32 = 0 if info.contains(.paymentInfo) { flags |= (1 << 0) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index a64a33be17..7bde71b986 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -1,4 +1,5 @@ import SwiftSignalKit +import Postbox public extension TelegramEngine { final class Payments { @@ -11,5 +12,25 @@ public extension TelegramEngine { public func getBankCardInfo(cardNumber: String) -> Signal { return _internal_getBankCardInfo(account: self.account, cardNumber: cardNumber) } + + public func fetchBotPaymentForm(messageId: MessageId, themeParams: [String: Any]?) -> Signal { + return _internal_fetchBotPaymentForm(postbox: self.account.postbox, network: self.account.network, messageId: messageId, themeParams: themeParams) + } + + public func validateBotPaymentForm(saveInfo: Bool, messageId: MessageId, formInfo: BotPaymentRequestedInfo) -> Signal { + return _internal_validateBotPaymentForm(account: self.account, saveInfo: saveInfo, messageId: messageId, formInfo: formInfo) + } + + public func sendBotPaymentForm(messageId: MessageId, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal { + return _internal_sendBotPaymentForm(account: self.account, messageId: messageId, formId: formId, validatedInfoId: validatedInfoId, shippingOptionId: shippingOptionId, tipAmount: tipAmount, credentials: credentials) + } + + public func requestBotPaymentReceipt(messageId: MessageId) -> Signal { + return _internal_requestBotPaymentReceipt(account: self.account, messageId: messageId) + } + + public func clearBotPaymentInfo(info: BotPaymentInfo) -> Signal { + return _internal_clearBotPaymentInfo(network: self.account.network, info: info) + } } } diff --git a/submodules/TelegramCore/Sources/ChatOnlineMembers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatOnlineMembers.swift similarity index 86% rename from submodules/TelegramCore/Sources/ChatOnlineMembers.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatOnlineMembers.swift index 6be97c6046..aeb9e8593e 100644 --- a/submodules/TelegramCore/Sources/ChatOnlineMembers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatOnlineMembers.swift @@ -3,7 +3,7 @@ import SwiftSignalKit import Postbox import TelegramApi -public func chatOnlineMembers(postbox: Postbox, network: Network, peerId: PeerId) -> Signal { +func _internal_chatOnlineMembers(postbox: Postbox, network: Network, peerId: PeerId) -> Signal { return postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) } diff --git a/submodules/TelegramCore/Sources/ConvertGroupToSupergroup.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ConvertGroupToSupergroup.swift similarity index 95% rename from submodules/TelegramCore/Sources/ConvertGroupToSupergroup.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/ConvertGroupToSupergroup.swift index cce0ed0147..2edaf4434c 100644 --- a/submodules/TelegramCore/Sources/ConvertGroupToSupergroup.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ConvertGroupToSupergroup.swift @@ -9,7 +9,7 @@ public enum ConvertGroupToSupergroupError { case tooManyChannels } -public func convertGroupToSupergroup(account: Account, peerId: PeerId) -> Signal { +func _internal_convertGroupToSupergroup(account: Account, peerId: PeerId) -> Signal { return account.network.request(Api.functions.messages.migrateChat(chatId: peerId.id._internalGetInt32Value())) |> mapError { error -> ConvertGroupToSupergroupError in if error.errorDescription == "CHANNELS_TOO_MUCH" { diff --git a/submodules/TelegramCore/Sources/CreateGroup.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateGroup.swift similarity index 93% rename from submodules/TelegramCore/Sources/CreateGroup.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateGroup.swift index ec68df3240..4245f6cb52 100644 --- a/submodules/TelegramCore/Sources/CreateGroup.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateGroup.swift @@ -13,7 +13,7 @@ public enum CreateGroupError { case serverProvided(String) } -public func createGroup(account: Account, title: String, peerIds: [PeerId]) -> Signal { +func _internal_createGroup(account: Account, title: String, peerIds: [PeerId]) -> Signal { return account.postbox.transaction { transaction -> Signal in var inputUsers: [Api.InputUser] = [] for peerId in peerIds { diff --git a/submodules/TelegramCore/Sources/CreateSecretChat.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateSecretChat.swift similarity index 96% rename from submodules/TelegramCore/Sources/CreateSecretChat.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateSecretChat.swift index 9ce1c2b48b..7d57209fb7 100644 --- a/submodules/TelegramCore/Sources/CreateSecretChat.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/CreateSecretChat.swift @@ -9,7 +9,7 @@ public enum CreateSecretChatError { case limitExceeded } -public func createSecretChat(account: Account, peerId: PeerId) -> Signal { +func _internal_createSecretChat(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) { return validatedEncryptionConfig(postbox: account.postbox, network: account.network) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 2a65d8f46e..4ce9e85463 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -1,5 +1,6 @@ import SwiftSignalKit import Postbox +import SyncCore public enum AddressNameValidationStatus: Equatable { case checking @@ -69,5 +70,29 @@ public extension TelegramEngine { public func searchPeers(query: String) -> Signal<([FoundPeer], [FoundPeer]), NoError> { return _internal_searchPeers(account: self.account, query: query) } + + public func updatedRemotePeer(peer: PeerReference) -> Signal { + return _internal_updatedRemotePeer(postbox: self.account.postbox, network: self.account.network, peer: peer) + } + + public func chatOnlineMembers(peerId: PeerId) -> Signal { + return _internal_chatOnlineMembers(postbox: self.account.postbox, network: self.account.network, peerId: peerId) + } + + public func convertGroupToSupergroup(peerId: PeerId) -> Signal { + return _internal_convertGroupToSupergroup(account: self.account, peerId: peerId) + } + + public func createGroup(title: String, peerIds: [PeerId]) -> Signal { + return _internal_createGroup(account: self.account, title: title, peerIds: peerIds) + } + + public func createSecretChat(peerId: PeerId) -> Signal { + return _internal_createSecretChat(account: self.account, peerId: peerId) + } + + public func setChatMessageAutoremoveTimeoutInteractively(peerId: PeerId, timeout: Int32?) -> Signal { + return _internal_setChatMessageAutoremoveTimeoutInteractively(account: self.account, peerId: peerId, timeout: timeout) + } } } diff --git a/submodules/TelegramCore/Sources/StickerSetInstallation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift similarity index 95% rename from submodules/TelegramCore/Sources/StickerSetInstallation.swift rename to submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift index 0abcf37729..18318676ee 100644 --- a/submodules/TelegramCore/Sources/StickerSetInstallation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift @@ -24,7 +24,7 @@ public enum RequestStickerSetResult { } } -public func requestStickerSet(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal { +func _internal_requestStickerSet(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal { let collectionId: ItemCollectionId? let input: Api.InputStickerSet @@ -133,7 +133,7 @@ public final class CoveredStickerSet : Equatable { } } -public func installStickerSetInteractively(account: Account, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal { +func _internal_installStickerSetInteractively(account: Account, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal { return account.network.request(Api.functions.messages.installStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash), archived: .boolFalse)) |> mapError { _ -> InstallStickerSetError in return .generic } |> mapToSignal { result -> Signal in @@ -198,7 +198,7 @@ public func installStickerSetInteractively(account: Account, info: StickerPackCo } -public func uninstallStickerSetInteractively(account: Account, info: StickerPackCollectionInfo) -> Signal { +func _internal_uninstallStickerSetInteractively(account: Account, info: StickerPackCollectionInfo) -> Signal { return account.network.request(Api.functions.messages.uninstallStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash))) |> `catch` { _ -> Signal in return .single(.boolFalse) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index 2389f19737..9fd8d6412e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -43,6 +43,10 @@ public final class TelegramEngine { public lazy var localization: Localization = { return Localization(account: self.account) }() + + public lazy var messages: Messages = { + return Messages(account: self.account) + }() } public final class TelegramEngineUnauthorized { diff --git a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift index 7e0c426020..56fb081c41 100644 --- a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift @@ -133,7 +133,7 @@ public func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId guard let view = views.views[.basicPeer(rawPeerId)] as? BasicPeerView else { return .complete() } - guard let peer = view.peer else { + guard let _ = view.peer else { return .complete() } return .single(true) diff --git a/submodules/TelegramCore/Sources/CanSendMessagesToPeer.swift b/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift similarity index 100% rename from submodules/TelegramCore/Sources/CanSendMessagesToPeer.swift rename to submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift diff --git a/submodules/TelegramCore/Sources/DecryptedResourceData.swift b/submodules/TelegramCore/Sources/Utils/DecryptedResourceData.swift similarity index 100% rename from submodules/TelegramCore/Sources/DecryptedResourceData.swift rename to submodules/TelegramCore/Sources/Utils/DecryptedResourceData.swift diff --git a/submodules/TelegramCore/Sources/ImageRepresentationsUtils.swift b/submodules/TelegramCore/Sources/Utils/ImageRepresentationsUtils.swift similarity index 100% rename from submodules/TelegramCore/Sources/ImageRepresentationsUtils.swift rename to submodules/TelegramCore/Sources/Utils/ImageRepresentationsUtils.swift diff --git a/submodules/TelegramCore/Sources/MD5.swift b/submodules/TelegramCore/Sources/Utils/MD5.swift similarity index 100% rename from submodules/TelegramCore/Sources/MD5.swift rename to submodules/TelegramCore/Sources/Utils/MD5.swift diff --git a/submodules/TelegramCore/Sources/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift similarity index 100% rename from submodules/TelegramCore/Sources/PeerUtils.swift rename to submodules/TelegramCore/Sources/Utils/PeerUtils.swift diff --git a/submodules/TelegramCore/Sources/StringFormat.swift b/submodules/TelegramCore/Sources/Utils/StringFormat.swift similarity index 100% rename from submodules/TelegramCore/Sources/StringFormat.swift rename to submodules/TelegramCore/Sources/Utils/StringFormat.swift diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 9642bf8b48..391f01676d 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -221,6 +221,7 @@ swift_library( "//submodules/PeerInfoAvatarListNode:PeerInfoAvatarListNode", "//submodules/DebugSettingsUI:DebugSettingsUI", "//submodules/ImportStickerPackUI:ImportStickerPackUI", + "//submodules/GradientBackground:GradientBackground", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Sources/AccountContext.swift b/submodules/TelegramUI/Sources/AccountContext.swift index 95fe8149b6..5e5e1ab5c3 100644 --- a/submodules/TelegramUI/Sources/AccountContext.swift +++ b/submodules/TelegramUI/Sources/AccountContext.swift @@ -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(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, viewTracker: account.viewTracker, stateManager: account.stateManager, locationManager: locationManager, inForeground: sharedContext.applicationBindings.applicationInForeground) + self.liveLocationManager = LiveLocationManagerImpl(account: account, locationManager: locationManager, inForeground: sharedContext.applicationBindings.applicationInForeground) } else { self.liveLocationManager = nil } @@ -295,7 +295,7 @@ public final class AccountContextImpl: AccountContext { public func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic, messageIndex: MessageIndex) { switch location { case .peer: - let _ = applyMaxReadIndexInteractively(postbox: self.account.postbox, stateManager: self.account.stateManager, index: messageIndex).start() + let _ = self.engine.messages.applyMaxReadIndexInteractively(index: messageIndex).start() case let .replyThread(data): let context = chatLocationContext(holder: contextHolder, account: self.account, data: data) context.applyMaxReadIndex(messageIndex: messageIndex) diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index fa1f30b5f8..9b35f62a39 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -1972,7 +1972,7 @@ final class SharedApplicationContext { |> deliverOnMainQueue |> mapToSignal { account -> Signal in if let messageId = messageIdFromNotification(peerId: peerId, notification: response.notification) { - let _ = applyMaxReadIndexInteractively(postbox: account.postbox, stateManager: account.stateManager, index: MessageIndex(id: messageId, timestamp: 0)).start() + let _ = TelegramEngine(account: account).messages.applyMaxReadIndexInteractively(index: MessageIndex(id: messageId, timestamp: 0)).start() } return enqueueMessages(account: account, peerId: peerId, messages: [EnqueueMessage.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> map { messageIds -> MessageId? in diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift index 4854c1d83d..4d6e9c69b4 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift @@ -110,7 +110,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail if let currentController = currentController { controller = currentController } else { - controller = AuthorizationSequenceSplashController(accountManager: self.sharedContext.accountManager, postbox: self.account.postbox, network: self.account.network, theme: self.presentationData.theme) + controller = AuthorizationSequenceSplashController(accountManager: self.sharedContext.accountManager, account: self.account, theme: self.presentationData.theme) controller.nextPressed = { [weak self] strings in if let strongSelf = self { if let strings = strings { diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceSplashController.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceSplashController.swift index 184601231f..26cc9a83cd 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceSplashController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceSplashController.swift @@ -17,8 +17,7 @@ final class AuthorizationSequenceSplashController: ViewController { } private let accountManager: AccountManager - private let postbox: Postbox - private let network: Network + private let account: UnauthorizedAccount private let theme: PresentationTheme private let controller: RMIntroViewController @@ -30,14 +29,13 @@ final class AuthorizationSequenceSplashController: ViewController { private let suggestedLocalization = Promise() private let activateLocalizationDisposable = MetaDisposable() - init(accountManager: AccountManager, postbox: Postbox, network: Network, theme: PresentationTheme) { + init(accountManager: AccountManager, account: UnauthorizedAccount, theme: PresentationTheme) { self.accountManager = accountManager - self.postbox = postbox - self.network = network + self.account = account self.theme = theme self.suggestedLocalization.set(.single(nil) - |> then(currentlySuggestedLocalization(network: network, extractKeys: ["Login.ContinueWithLocalization"]))) + |> then(TelegramEngineUnauthorized(account: self.account).localization.currentlySuggestedLocalization(extractKeys: ["Login.ContinueWithLocalization"]))) let suggestedLocalization = self.suggestedLocalization let localizationSignal = SSignal(generator: { subscriber in @@ -176,7 +174,7 @@ final class AuthorizationSequenceSplashController: ViewController { } if let suggestedCode = suggestedCode { - _ = markSuggestedLocalizationAsSeenInteractively(postbox: strongSelf.postbox, languageCode: suggestedCode).start() + _ = TelegramEngineUnauthorized(account: strongSelf.account).localization.markSuggestedLocalizationAsSeenInteractively(languageCode: suggestedCode).start() } if currentCode == code { @@ -186,9 +184,8 @@ final class AuthorizationSequenceSplashController: ViewController { strongSelf.controller.isEnabled = false let accountManager = strongSelf.accountManager - let postbox = strongSelf.postbox - strongSelf.activateLocalizationDisposable.set(downloadAndApplyLocalization(accountManager: accountManager, postbox: postbox, network: strongSelf.network, languageCode: code).start(completed: { + strongSelf.activateLocalizationDisposable.set(TelegramEngineUnauthorized(account: strongSelf.account).localization.downloadAndApplyLocalization(accountManager: accountManager, languageCode: code).start(completed: { let _ = (accountManager.transaction { transaction -> PresentationStrings? in let localizationSettings: LocalizationSettings? if let current = transaction.getSharedData(SharedDataKeys.localizationSettings) as? LocalizationSettings { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c3f0a7eea9..b3a1805c55 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1216,9 +1216,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - let account = strongSelf.context.account + let context = strongSelf.context if requiresPassword { - strongSelf.messageActionCallbackDisposable.set(((requestMessageActionCallbackPasswordCheck(account: account, messageId: messageId, isGame: isGame, data: data) + strongSelf.messageActionCallbackDisposable.set(((strongSelf.context.engine.messages.requestMessageActionCallbackPasswordCheck(messageId: messageId, isGame: isGame, data: data) |> afterDisposed { updateProgress() }) @@ -1226,7 +1226,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let controller = ownershipTransferController(context: context, initialError: error, present: { c, a in strongSelf.present(c, in: .window(.root), with: a) }, commit: { password in - return requestMessageActionCallback(account: account, messageId: messageId, isGame: isGame, password: password, data: data) + return context.engine.messages.requestMessageActionCallback(messageId: messageId, isGame: isGame, password: password, data: data) |> afterDisposed { updateProgress() } @@ -1236,7 +1236,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.present(controller, in: .window(.root)) })) } else { - strongSelf.messageActionCallbackDisposable.set(((requestMessageActionCallback(account: account, messageId: messageId, isGame: isGame, password: nil, data: data) + strongSelf.messageActionCallbackDisposable.set(((context.engine.messages.requestMessageActionCallback(messageId: messageId, isGame: isGame, password: nil, data: data) |> afterDisposed { updateProgress() }) @@ -1269,7 +1269,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return $0 } }) - strongSelf.messageActionUrlAuthDisposable.set(((combineLatest(strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId), requestMessageActionUrlAuth(account: strongSelf.context.account, subject: subject) |> afterDisposed { + strongSelf.messageActionUrlAuthDisposable.set(((combineLatest(strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId), strongSelf.context.engine.messages.requestMessageActionUrlAuth(subject: subject) |> afterDisposed { Queue.mainQueue().async { if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { @@ -1318,7 +1318,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - strongSelf.messageActionUrlAuthDisposable.set(((acceptMessageActionUrlAuth(account: strongSelf.context.account, subject: subject, allowWriteAccess: allowWriteAccess) |> afterDisposed { + strongSelf.messageActionUrlAuthDisposable.set(((strongSelf.context.engine.messages.acceptMessageActionUrlAuth(subject: subject, allowWriteAccess: allowWriteAccess) |> afterDisposed { Queue.mainQueue().async { if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { @@ -2094,7 +2094,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) }, action: { [weak self] controller, f in if let strongSelf = self { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: [id], type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: [id], type: .forLocalPeer).start() } f(.dismissWithoutContent) }))) @@ -2325,7 +2325,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } return } else { - let _ = sendScheduledMessageNowInteractively(postbox: strongSelf.context.account.postbox, messageId: messageIds.first!).start() + let _ = strongSelf.context.engine.messages.sendScheduledMessageNowInteractively(messageId: messageIds.first!).start() } } }, editScheduledMessagesTime: { [weak self] messageIds in @@ -2346,7 +2346,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } } - strongSelf.editMessageDisposable.set((requestEditMessage(account: strongSelf.context.account, messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in + strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in }, error: { error in })) } @@ -2841,7 +2841,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> mapToSignal { isLarge -> Signal in if let isLarge = isLarge { if isLarge { - return context.peerChannelMemberCategoriesContextsManager.recentOnline(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnline(account: context.account, accountPeerId: context.account.peerId, peerId: peerId) |> map(Optional.init) } else { return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) @@ -4523,7 +4523,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { isScheduledMessages = false } - strongSelf.chatDisplayNode.containerLayoutUpdated(validLayout, navigationBarHeight: strongSelf.navigationHeight, transition: .animated(duration: strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? 0.5 : 0.4, curve: strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? .custom(0.33, 0.0, 0.0, 1.0) : .spring), listViewTransaction: { updateSizeAndInsets, _, _, _ in + strongSelf.chatDisplayNode.containerLayoutUpdated(validLayout, navigationBarHeight: strongSelf.navigationHeight, transition: .animated(duration: strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? 0.5 : 0.3, curve: strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? .custom(0.33, 0.0, 0.0, 1.0) : .spring), listViewTransaction: { updateSizeAndInsets, _, _, _ in var options = transition.options let _ = options.insert(.Synchronous) let _ = options.insert(.LowLatency) @@ -4995,9 +4995,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start() - let account = strongSelf.context.account - let _ = (strongSelf.context.account.postbox.transaction { transasction -> Void in - deleteAllMessagesWithForwardAuthor(transaction: transasction, mediaBox: account.postbox.mediaBox, peerId: message.id.peerId, forwardAuthorId: peer.id, namespace: Namespaces.Message.Cloud) + let context = strongSelf.context + let _ = (context.account.postbox.transaction { transasction -> Void in + context.engine.messages.deleteAllMessagesWithForwardAuthor(transaction: transasction, peerId: message.id.peerId, forwardAuthorId: peer.id, namespace: Namespaces.Message.Cloud) }).start() let _ = reportRepliesMessage(account: strongSelf.context.account, messageId: message.id, deleteMessage: true, deleteHistory: true, reportSpam: reportSpam).start() }) @@ -5028,10 +5028,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } if isAction && (actions.options == .deleteGlobally || actions.options == .deleteLocally) { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: actions.options == .deleteLocally ? .forLocalPeer : .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: actions.options == .deleteLocally ? .forLocalPeer : .forEveryone).start() completion(.dismissWithoutContent) } else if (messages.first?.flags.isSending ?? false) { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone, deleteAllInGroup: true).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone, deleteAllInGroup: true).start() completion(.dismissWithoutContent) } else { if actions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty { @@ -5325,7 +5325,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G threadId = makeMessageThreadId(replyThreadMessage.messageId) } - strongSelf.messageIndexDisposable.set((searchMessageIdByTimestamp(account: strongSelf.context.account, peerId: peerId, threadId: threadId, timestamp: timestamp) |> deliverOnMainQueue).start(next: { messageId in + strongSelf.messageIndexDisposable.set((strongSelf.context.engine.messages.searchMessageIdByTimestamp(peerId: peerId, threadId: threadId, timestamp: timestamp) |> deliverOnMainQueue).start(next: { messageId in if let strongSelf = self { strongSelf.loadingMessage.set(.single(nil)) if let messageId = messageId { @@ -7829,7 +7829,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) case .clearHistory: if case let .peer(peerId) = self.chatLocation { - let account = self.context.account + let context = self.context let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in guard let strongSelf = self else { @@ -7849,7 +7849,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: statusText), elevatedLayout: false, action: { value in if value == .commit { - let _ = clearHistoryInteractively(postbox: account.postbox, peerId: peerId, type: type).start(completed: { + let _ = context.engine.messages.clearHistoryInteractively(peerId: peerId, type: type).start(completed: { self?.chatDisplayNode.historyNode.historyAppearsCleared = false }) return true @@ -8374,7 +8374,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private func editMessageMediaWithLegacySignals(_ signals: [Any]) { let _ = (legacyAssetPickerEnqueueMessages(account: self.context.account, signals: signals) |> deliverOnMainQueue).start(next: { [weak self] messages in - self?.editMessageMediaWithMessages(messages) + self?.editMessageMediaWithMessages(messages.map { $0.message }) }) } @@ -8583,14 +8583,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G done(time) }) } - }, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in + }, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime, getAnimatedTransitionSource, completion in + guard let strongSelf = self else { + completion() + return + } if !inputText.string.isEmpty { //strongSelf.clearInputText() } if editMediaOptions != nil { - self?.editMessageMediaWithLegacySignals(signals!) + strongSelf.editMessageMediaWithLegacySignals(signals!) + completion() } else { - self?.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil) + strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil, getAnimatedTransitionSource: getAnimatedTransitionSource, completion: { + completion() + }) } }, selectRecentlyUsedInlineBot: { [weak self] peer in if let strongSelf = self, let addressName = peer.addressName { @@ -9531,11 +9538,32 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - private func enqueueMediaMessages(signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil) { + private func enqueueMediaMessages(signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil, getAnimatedTransitionSource: @escaping (String) -> UIView? = { _ in nil }, completion: @escaping () -> Void = {}) { self.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(account: self.context.account, signals: signals!) - |> deliverOnMainQueue).start(next: { [weak self] messages in + |> deliverOnMainQueue).start(next: { [weak self] items in if let strongSelf = self { - let messages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting, scheduleTime: scheduleTime) + var completionImpl: (() -> Void)? = completion + + var mappedMessages: [EnqueueMessage] = [] + for item in items { + var message = item.message + if let uniqueId = item.uniqueId { + let correlationId = Int64.random(in: 0 ..< Int64.max) + message = message.withUpdatedCorrelationId(correlationId) + + if items.count == 1 { + completionImpl = nil + strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .mediaInput(ChatMessageTransitionNode.Source.MediaInput(extractSnapshot: { + return getAnimatedTransitionSource(uniqueId) + })), initiated: { + completion() + }) + } + } + mappedMessages.append(message) + } + + let messages = strongSelf.transformEnqueueMessages(mappedMessages, silentPosting: silentPosting, scheduleTime: scheduleTime) let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { @@ -9543,7 +9571,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } + completionImpl?() }) + strongSelf.sendMessages(messages.map { $0.withUpdatedReplyToMessageId(replyMessageId) }) } })) @@ -10076,7 +10106,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.searchDisposable = searchDisposable } - let search = searchMessages(account: self.context.account, location: searchState.location, query: searchState.query, state: nil, limit: limit) + let search = self.context.engine.messages.searchMessages(location: searchState.location, query: searchState.query, state: nil, limit: limit) |> delay(0.2, queue: Queue.mainQueue()) self.searchResult.set(search |> map { (result, state) -> (SearchMessagesResult, SearchMessagesState, SearchMessagesLocation)? in @@ -10130,7 +10160,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G searchDisposable = MetaDisposable() self.searchDisposable = searchDisposable } - searchDisposable.set((searchMessages(account: self.context.account, location: searchState.location, query: searchState.query, state: loadMoreState, limit: limit) + searchDisposable.set((self.context.engine.messages.searchMessages(location: searchState.location, query: searchState.query, state: loadMoreState, limit: limit) |> delay(0.2, queue: Queue.mainQueue()) |> deliverOnMainQueue).start(next: { [weak self] results, updatedState in guard let strongSelf = self else { @@ -11613,13 +11643,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) if actions.contains(3) { - let mediaBox = strongSelf.context.account.postbox.mediaBox - let _ = strongSelf.context.account.postbox.transaction({ transaction -> Void in - deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: mediaBox, peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud) + let context = strongSelf.context + let _ = context.account.postbox.transaction({ transaction -> Void in + context.engine.messages.deleteAllMessagesWithAuthor(transaction: transaction, peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud) }).start() - let _ = clearAuthorHistory(account: strongSelf.context.account, peerId: peerId, memberId: author.id).start() + let _ = strongSelf.context.engine.messages.clearAuthorHistory(peerId: peerId, memberId: author.id).start() } else if actions.contains(0) { - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } if actions.contains(1) { let _ = removePeerMember(account: strongSelf.context.account, peerId: peerId, memberId: author.id).start() @@ -11657,7 +11687,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G actionSheet?.dismissAnimated() if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } })) } @@ -11684,7 +11714,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G contextItems.append(.action(ContextMenuActionItem(text: globalTitle, textColor: .destructive, icon: { _ in nil }, action: { [weak self] _, f in if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() f(.dismissWithoutContent) } }))) @@ -11692,7 +11722,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G actionSheet?.dismissAnimated() if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } })) } @@ -11714,7 +11744,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G contextItems.append(.action(ContextMenuActionItem(text: localOptionText, textColor: .destructive, icon: { _ in nil }, action: { [weak self] _, f in if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).start() f(.dismissWithoutContent) } }))) @@ -11722,7 +11752,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G actionSheet?.dismissAnimated() if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).start() } })) } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 53800e9a45..27ea7edb62 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -16,6 +16,7 @@ import TelegramUniversalVideoContent import ChatInterfaceState import FastBlur import ConfettiEffect +import GradientBackground final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { let itemNode: OverlayMediaItemNode @@ -300,6 +301,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } let backgroundNode: WallpaperBackgroundNode + let gradientBackgroundNode: GradientBackgroundNode? let backgroundImageDisposable = MetaDisposable() let historyNode: ChatHistoryListNode var blurredHistoryNode: ASImageNode? @@ -344,6 +346,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let navigateButtons: ChatHistoryNavigationButtons private var ignoreUpdateHeight = false + private var overrideUpdateTextInputHeightTransition: ContainedViewLayoutTransition? private var animateInAsOverlayCompletion: (() -> Void)? private var dismissAsOverlayCompletion: (() -> Void)? @@ -466,6 +469,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.backgroundNode = WallpaperBackgroundNode() self.backgroundNode.displaysAsynchronously = false + + if chatPresentationInterfaceState.chatWallpaper.isBuiltin { + self.gradientBackgroundNode = GradientBackgroundNode() + } else { + self.gradientBackgroundNode = nil + } self.titleAccessoryPanelContainer = ChatControllerTitlePanelNodeContainer() self.titleAccessoryPanelContainer.clipsToBounds = true @@ -506,8 +515,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.navigationBarSeparatorNode.backgroundColor = chatPresentationInterfaceState.theme.rootController.navigationBar.separatorColor var getContentAreaInScreenSpaceImpl: (() -> CGRect)? + var onTransitionEventImpl: ((ContainedViewLayoutTransition) -> Void)? self.messageTransitionNode = ChatMessageTransitionNode(listNode: self.historyNode, getContentAreaInScreenSpace: { return getContentAreaInScreenSpaceImpl?() ?? CGRect() + }, onTransitionEvent: { transition in + onTransitionEventImpl?(transition) }) super.init() @@ -519,6 +531,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { return strongSelf.view.convert(strongSelf.frameForVisibleArea(), to: nil) } + + onTransitionEventImpl = { [weak self] transition in + guard let strongSelf = self, let gradientBackgroundNode = strongSelf.gradientBackgroundNode else { + return + } + gradientBackgroundNode.animateEvent(transition: transition) + } self.controller?.presentationContext.topLevelSubview = { [weak self] in guard let strongSelf = self else { @@ -598,6 +617,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.enableExtractedBackgrounds = true self.addSubnode(self.backgroundNode) + if let gradientBackgroundNode = self.gradientBackgroundNode { + self.addSubnode(gradientBackgroundNode) + } self.addSubnode(self.historyNodeContainer) self.addSubnode(self.navigateButtons) self.addSubnode(self.titleAccessoryPanelContainer) @@ -626,7 +648,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.textInputPanelNode?.updateHeight = { [weak self] animated in if let strongSelf = self, let _ = strongSelf.inputPanelNode as? ChatTextInputPanelNode, !strongSelf.ignoreUpdateHeight { if strongSelf.scheduledLayoutTransitionRequest == nil { - strongSelf.scheduleLayoutTransitionRequest(animated ? .animated(duration: 0.1, curve: .easeInOut) : .immediate) + let transition: ContainedViewLayoutTransition + if !animated { + transition = .immediate + } else if let overrideUpdateTextInputHeightTransition = strongSelf.overrideUpdateTextInputHeightTransition { + transition = overrideUpdateTextInputHeightTransition + } else { + transition = .animated(duration: 0.1, curve: .easeInOut) + } + strongSelf.scheduleLayoutTransitionRequest(transition) } } } @@ -1282,6 +1312,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.updateFrame(node: self.backgroundNode, frame: contentBounds) self.backgroundNode.updateLayout(size: contentBounds.size, transition: transition) + + if let gradientBackgroundNode = self.gradientBackgroundNode { + transition.updateFrame(node: gradientBackgroundNode, frame: contentBounds) + gradientBackgroundNode.updateLayout(size: contentBounds.size, transition: transition) + } + transition.updateFrame(node: self.historyNodeContainer, frame: contentBounds) transition.updateBounds(node: self.historyNode, bounds: CGRect(origin: CGPoint(), size: contentBounds.size)) transition.updatePosition(node: self.historyNode, position: CGPoint(x: contentBounds.size.width / 2.0, y: contentBounds.size.height / 2.0)) @@ -1895,6 +1931,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let listBottomInset = self.historyNode.insets.top if let previousListBottomInset = previousListBottomInset, listBottomInset != previousListBottomInset { + if abs(listBottomInset - previousListBottomInset) > 80.0 { + self.gradientBackgroundNode?.animateEvent(transition: transition) + } //self.historyNode.didScrollWithOffset?(listBottomInset - previousListBottomInset, transition, nil) } @@ -1987,7 +2026,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } if let textInputPanelNode = self.textInputPanelNode, updateInputTextState { + let previous = self.overrideUpdateTextInputHeightTransition + self.overrideUpdateTextInputHeightTransition = transition textInputPanelNode.updateInputTextState(chatPresentationInterfaceState.interfaceState.effectiveInputState, keepSendButtonEnabled: keepSendButtonEnabled, extendedSearchLayout: extendedSearchLayout, accessoryItems: chatPresentationInterfaceState.inputTextPanelState.accessoryItems, animated: transition.isAnimated) + self.overrideUpdateTextInputHeightTransition = previous } else { self.textInputPanelNode?.updateKeepSendButtonEnabled(keepSendButtonEnabled: keepSendButtonEnabled, extendedSearchLayout: extendedSearchLayout, animated: transition.isAnimated) } diff --git a/submodules/TelegramUI/Sources/ChatHistorySearchContainerNode.swift b/submodules/TelegramUI/Sources/ChatHistorySearchContainerNode.swift index 7f99889553..bfdfe79955 100644 --- a/submodules/TelegramUI/Sources/ChatHistorySearchContainerNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistorySearchContainerNode.swift @@ -194,7 +194,7 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode { if let strongSelf = self { let signal: Signal<([ChatHistorySearchEntry], [MessageId: Message])?, NoError> if let query = query, !query.isEmpty { - let foundRemoteMessages: Signal<[Message], NoError> = searchMessages(account: context.account, location: .peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: nil, maxDate: nil), query: query, state: nil) + let foundRemoteMessages: Signal<[Message], NoError> = context.engine.messages.searchMessages(location: .peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: nil, maxDate: nil), query: query, state: nil) |> map { $0.0.messages } |> delay(0.2, queue: Queue.concurrentDefaultQueue()) diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index b627e0a544..59468a690d 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -35,6 +35,17 @@ private struct BubbleItemAttributes { var neighborSpacing: ChatMessageBubbleRelativePosition.NeighbourSpacing } +private final class ChatMessageBubbleClippingNode: ASDisplayNode { + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let result = self.view.hitTest(point, with: event) + if result === self.view { + return nil + } else { + return result + } + } +} + private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)], Bool) { var result: [(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)] = [] var skipText = false @@ -367,7 +378,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode private let backgroundWallpaperNode: ChatMessageBubbleBackdrop private let backgroundNode: ChatMessageBackground private let shadowNode: ChatMessageShadowNode - private var clippingNode: ASDisplayNode + private var clippingNode: ChatMessageBubbleClippingNode override var extractedBackgroundNode: ASDisplayNode? { return self.shadowNode @@ -431,7 +442,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode self.backgroundNode = ChatMessageBackground() self.shadowNode = ChatMessageShadowNode() - self.clippingNode = ASDisplayNode() + self.clippingNode = ChatMessageBubbleClippingNode() self.clippingNode.clipsToBounds = true self.messageAccessibilityArea = AccessibilityAreaNode() @@ -706,6 +717,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } return nil } + + func animateContentFromMediaInput(snapshotView: UIView, horizontalTransition: ContainedViewLayoutTransition, verticalTransition: ContainedViewLayoutTransition) { + self.mainContextSourceNode.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } override func didLoad() { super.didLoad() diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index 072496df97..4fec8deb0e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -182,7 +182,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { case let .fetchStatus(fetchStatus): if let context = self.context, let message = self.message, message.flags.isSending { let _ = context.account.postbox.transaction({ transaction -> Void in - deleteMessages(transaction: transaction, mediaBox: context.account.postbox.mediaBox, ids: [message.id]) + context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id]) }).start() } else { switch fetchStatus { diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift index d65ffa39ca..68466f689c 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift @@ -741,7 +741,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { if item.message.flags.isSending { let messageId = item.message.id let _ = item.context.account.postbox.transaction({ transaction -> Void in - deleteMessages(transaction: transaction, mediaBox: item.context.account.postbox.mediaBox, ids: [messageId]) + item.context.engine.messages.deleteMessages(transaction: transaction, ids: [messageId]) }).start() } else { messageMediaFileCancelInteractiveFetch(context: item.context, messageId: item.message.id, file: file) diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift index 1f0f32bcbb..2ec2cfbf08 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift @@ -299,7 +299,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio case .Fetching: if let context = self.context, let message = self.message, message.flags.isSending { let _ = context.account.postbox.transaction({ transaction -> Void in - deleteMessages(transaction: transaction, mediaBox: context.account.postbox.mediaBox, ids: [message.id]) + context.engine.messages.deleteMessages(transaction: transaction, ids: [message.id]) }).start() } else if let media = media, let context = self.context, let message = message { if let media = media as? TelegramMediaFile { diff --git a/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift index 4c5d935b5e..e3f6312f21 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift @@ -147,10 +147,19 @@ final class ChatMessageTransitionNode: ASDisplayNode { } } + final class MediaInput { + let extractSnapshot: () -> UIView? + + init(extractSnapshot: @escaping () -> UIView?) { + self.extractSnapshot = extractSnapshot + } + } + case textInput(textInput: TextInput, replyPanel: ReplyAccessoryPanelNode?) case stickerMediaInput(input: StickerInput, replyPanel: ReplyAccessoryPanelNode?) case audioMicInput(AudioMicInput) case videoMessage(VideoMessage) + case mediaInput(MediaInput) } private final class AnimatingItemNode: ASDisplayNode { @@ -203,7 +212,7 @@ final class ChatMessageTransitionNode: ASDisplayNode { updatedContentAreaInScreenSpace.origin.x = 0.0 updatedContentAreaInScreenSpace.size.width = self.clippingNode.bounds.width - let timingFunction = CAMediaTimingFunction(controlPoints: 0.33, 0.0, 0.0, 1.0) + //let timingFunction = CAMediaTimingFunction(controlPoints: 0.33, 0.0, 0.0, 1.0) let clippingOffset = updatedContentAreaInScreenSpace.minY - self.clippingNode.frame.minY self.clippingNode.frame = CGRect(origin: CGPoint(x: 0.0, y: updatedContentAreaInScreenSpace.minY), size: self.clippingNode.bounds.size) @@ -303,8 +312,6 @@ final class ChatMessageTransitionNode: ASDisplayNode { sourceReplyPanel = ReplyPanel(titleNode: replyPanel.titleNode, textNode: replyPanel.textNode, lineNode: replyPanel.lineNode, imageNode: replyPanel.imageNode, relativeSourceRect: replySourceAbsoluteFrame) } - self.itemNode.cancelInsertionAnimations() - let transition: ContainedViewLayoutTransition = .animated(duration: horizontalDuration, curve: .custom(0.33, 0.0, 0.0, 1.0)) if let itemNode = self.itemNode as? ChatMessageAnimatedStickerItemNode { @@ -410,6 +417,54 @@ final class ChatMessageTransitionNode: ASDisplayNode { itemNode.animateFromSnapshot(snapshotView: videoMessage.view, transition: transition) } + case let .mediaInput(mediaInput): + if let snapshotView = mediaInput.extractSnapshot() { + if let itemNode = self.itemNode as? ChatMessageBubbleItemNode { + itemNode.cancelInsertionAnimations() + + self.contextSourceNode.isExtractedToContextPreview = true + self.contextSourceNode.isExtractedToContextPreviewUpdated?(true) + + self.containerNode.addSubnode(self.contextSourceNode.contentNode) + + let targetAbsoluteRect = self.contextSourceNode.view.convert(self.contextSourceNode.contentRect, to: nil) + let sourceBackgroundAbsoluteRect = snapshotView.frame + let sourceAbsoluteRect = CGRect(origin: CGPoint(x: sourceBackgroundAbsoluteRect.midX - self.contextSourceNode.contentRect.size.width / 2.0, y: sourceBackgroundAbsoluteRect.midY - self.contextSourceNode.contentRect.size.height / 2.0), size: self.contextSourceNode.contentRect.size) + + let transition: ContainedViewLayoutTransition = .animated(duration: verticalDuration, curve: .custom(0.33, 0.0, 0.0, 1.0)) + let verticalTransition: ContainedViewLayoutTransition = .animated(duration: horizontalDuration, curve: .custom(0.33, 0.0, 0.0, 1.0)) + + if let itemNode = self.itemNode as? ChatMessageBubbleItemNode { + itemNode.animateContentFromMediaInput(snapshotView: snapshotView, horizontalTransition: verticalTransition, verticalTransition: transition) + } + + self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -self.contextSourceNode.contentRect.minX, dy: -self.contextSourceNode.contentRect.minY) + + snapshotView.center = targetAbsoluteRect.center.offsetBy(dx: -self.containerNode.frame.minX, dy: -self.containerNode.frame.minY) + self.containerNode.view.addSubview(snapshotView) + + self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size) + + self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: CAMediaTimingFunction(controlPoints: 0.33, 0.0, 0.0, 1.0), additive: true, force: true) + self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: CAMediaTimingFunction(controlPoints: 0.33, 0.0, 0.0, 1.0), additive: true, force: true, completion: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.endAnimation() + }) + + verticalTransition.animateTransformScale(node: self.contextSourceNode.contentNode, from: CGPoint(x: sourceBackgroundAbsoluteRect.width / targetAbsoluteRect.width, y: sourceBackgroundAbsoluteRect.height / targetAbsoluteRect.height)) + + verticalTransition.updateTransformScale(layer: snapshotView.layer, scale: CGPoint(x: 1.0 / (sourceBackgroundAbsoluteRect.width / targetAbsoluteRect.width), y: 1.0 / (sourceBackgroundAbsoluteRect.height / targetAbsoluteRect.height))) + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + + self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.minX - targetAbsoluteRect.minX, y: 0.0), .custom(0.33, 0.0, 0.0, 1.0), horizontalDuration) + self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.maxY - targetAbsoluteRect.maxY), .custom(0.33, 0.0, 0.0, 1.0), verticalDuration) + } + } } } @@ -455,6 +510,7 @@ final class ChatMessageTransitionNode: ASDisplayNode { private let listNode: ChatHistoryListNode private let getContentAreaInScreenSpace: () -> CGRect + private let onTransitionEvent: (ContainedViewLayoutTransition) -> Void private var currentPendingItem: (Int64, Source, () -> Void)? @@ -464,9 +520,10 @@ final class ChatMessageTransitionNode: ASDisplayNode { return self.currentPendingItem != nil } - init(listNode: ChatHistoryListNode, getContentAreaInScreenSpace: @escaping () -> CGRect) { + init(listNode: ChatHistoryListNode, getContentAreaInScreenSpace: @escaping () -> CGRect, onTransitionEvent: @escaping (ContainedViewLayoutTransition) -> Void) { self.listNode = listNode self.getContentAreaInScreenSpace = getContentAreaInScreenSpace + self.onTransitionEvent = onTransitionEvent super.init() @@ -505,7 +562,7 @@ final class ChatMessageTransitionNode: ASDisplayNode { self.animatingItemNodes.append(animatingItemNode) switch source { - case .audioMicInput, .videoMessage: + case .audioMicInput, .videoMessage, .mediaInput: let overlayController = OverlayTransitionContainerController() overlayController.displayNode.addSubnode(animatingItemNode) animatingItemNode.overlayController = overlayController @@ -527,6 +584,8 @@ final class ChatMessageTransitionNode: ASDisplayNode { animatingItemNode.frame = self.bounds animatingItemNode.beginAnimation() + + self.onTransitionEvent(.animated(duration: 0.5, curve: .custom(0.33, 0.0, 0.0, 1.0))) } } diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index 645f19bec5..5a42e01f36 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -256,7 +256,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe private func loadMore() { self.isLoadingMore = true - self.loadMoreDisposable.set((searchMessages(account: self.context.account, location: self.location, query: self.searchQuery, state: self.searchState) + self.loadMoreDisposable.set((self.context.engine.messages.searchMessages(location: self.location, query: self.searchQuery, state: self.searchState) |> deliverOnMainQueue).start(next: { [weak self] (updatedResult, updatedState) in guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Sources/ComposeController.swift b/submodules/TelegramUI/Sources/ComposeController.swift index b172d964ee..60ca4c40fa 100644 --- a/submodules/TelegramUI/Sources/ComposeController.swift +++ b/submodules/TelegramUI/Sources/ComposeController.swift @@ -161,7 +161,7 @@ public class ComposeControllerImpl: ViewController, ComposeController { if let strongSelf = self, let (contactPeers, _) = result, case let .peer(peer, _, _) = contactPeers.first { controller?.dismissSearch() controller?.displayNavigationActivity = true - strongSelf.createActionDisposable.set((createSecretChat(account: strongSelf.context.account, peerId: peer.id) |> deliverOnMainQueue).start(next: { peerId in + strongSelf.createActionDisposable.set((strongSelf.context.engine.peers.createSecretChat(peerId: peer.id) |> deliverOnMainQueue).start(next: { peerId in if let strongSelf = self, let controller = controller { controller.displayNavigationActivity = false (controller.navigationController as? NavigationController)?.replaceAllButRootController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: true) diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index 7e34633f85..98bb6cf961 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -425,7 +425,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] let createSignal: Signal switch mode { case .generic: - createSignal = createGroup(account: context.account, title: title, peerIds: peerIds) + createSignal = context.engine.peers.createGroup(title: title, peerIds: peerIds) case .supergroup: createSignal = createSupergroup(account: context.account, title: title, description: nil) |> map(Optional.init) diff --git a/submodules/TelegramUI/Sources/LegacyCamera.swift b/submodules/TelegramUI/Sources/LegacyCamera.swift index c253078988..6a92bb8726 100644 --- a/submodules/TelegramUI/Sources/LegacyCamera.swift +++ b/submodules/TelegramUI/Sources/LegacyCamera.swift @@ -123,7 +123,10 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocation: Ch controller.finishedWithResults = { [weak menuController, weak legacyController] overlayController, selectionContext, editingContext, currentItem, silentPosting, scheduleTime in if let selectionContext = selectionContext, let editingContext = editingContext { - let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedPhotos && !isSecretChat, saveEditedPhotos: saveCapturedPhotos && !isSecretChat, descriptionGenerator: legacyAssetPickerItemGenerator()) + let nativeGenerator = legacyAssetPickerItemGenerator() + let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedPhotos && !isSecretChat, saveEditedPhotos: saveCapturedPhotos && !isSecretChat, descriptionGenerator: { _1, _2, _3, _4 in + nativeGenerator(_1, _2, _3, _4, nil) + }) sendMessagesWithSignals(signals, silentPosting, scheduleTime) } @@ -139,7 +142,7 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocation: Ch if let timer = timer { description["timer"] = timer } - if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil) { + if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil, nil) { sendMessagesWithSignals([SSignal.single(item)], false, 0) } } @@ -164,7 +167,7 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocation: Ch if let timer = timer { description["timer"] = timer } - if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil) { + if let item = legacyAssetPickerItemGenerator()(description, caption, entities, nil, nil) { sendMessagesWithSignals([SSignal.single(item)], false, 0) } } @@ -217,16 +220,19 @@ func presentedLegacyShortcutCamera(context: AccountContext, saveCapturedMedia: B controller.finishedWithResults = { [weak controller, weak parentController, weak legacyController] overlayController, selectionContext, editingContext, currentItem, _, _ in if let selectionContext = selectionContext, let editingContext = editingContext { - let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedMedia, saveEditedPhotos: saveEditedPhotos, descriptionGenerator: legacyAssetPickerItemGenerator()) + let nativeGenerator = legacyAssetPickerItemGenerator() + let signals = TGCameraController.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, storeAssets: saveCapturedMedia, saveEditedPhotos: saveEditedPhotos, descriptionGenerator: { _1, _2, _3, _4 in + nativeGenerator(_1, _2, _3, _4, nil) + }) if let parentController = parentController { parentController.present(ShareController(context: context, subject: .fromExternal({ peerIds, text, account in return legacyAssetPickerEnqueueMessages(account: account, signals: signals!) - |> `catch` { _ -> Signal<[EnqueueMessage], NoError> in + |> `catch` { _ -> Signal<[LegacyAssetPickerEnqueueMessage], NoError> in return .single([]) } |> mapToSignal { messages -> Signal in let resultSignals = peerIds.map({ peerId in - return enqueueMessages(account: account, peerId: peerId, messages: messages) + return enqueueMessages(account: account, peerId: peerId, messages: messages.map { $0.message }) |> mapToSignal { _ -> Signal in return .complete() } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index b9ff945628..0e4be25a38 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -688,7 +688,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen |> mapToSignal { isLarge -> Signal in if let isLarge = isLarge { if isLarge { - return context.peerChannelMemberCategoriesContextsManager.recentOnline(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnline(account: context.account, accountPeerId: context.account.peerId, peerId: peerId) |> map(Optional.init) } else { return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 4e78bd5780..0755dbe75a 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1807,7 +1807,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD c.dismiss(completion: { if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } }) }))) @@ -1826,7 +1826,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD c.dismiss(completion: { if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forLocalPeer).start() } }) }))) @@ -1941,7 +1941,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD c.dismiss(completion: { if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } }) }))) @@ -1960,7 +1960,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD c.dismiss(completion: { if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forLocalPeer).start() } }) }))) @@ -3113,7 +3113,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD strongSelf.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(account: strongSelf.context.account, signals: signals!) |> deliverOnMainQueue).start(next: { [weak self] messages in if let strongSelf = self { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.peerId, messages: messages).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.peerId, messages: messages.map { $0.message }).start() } })) } @@ -3836,7 +3836,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD guard let strongSelf = self else { return } - var createSignal = createSecretChat(account: strongSelf.context.account, peerId: peerId) + var createSignal = strongSelf.context.engine.peers.createSecretChat(peerId: peerId) var cancelImpl: (() -> Void)? let progressSignal = Signal { subscriber in if let strongSelf = self { @@ -5605,7 +5605,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD actionSheet?.dismissAnimated() if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forEveryone).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).start() } })) } @@ -5622,7 +5622,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD actionSheet?.dismissAnimated() if let strongSelf = self { strongSelf.headerNode.navigationButtonContainer.performAction?(.selectionDone) - let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: Array(messageIds), type: .forLocalPeer).start() + let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forLocalPeer).start() } })) } @@ -7149,7 +7149,7 @@ func presentAddMembers(context: AccountContext, parentController: ViewController }) return .complete() case .groupFull: - let signal = convertGroupToSupergroup(account: context.account, peerId: groupPeer.id) + let signal = context.engine.peers.convertGroupToSupergroup(peerId: groupPeer.id) |> map(Optional.init) |> `catch` { error -> Signal in switch error { diff --git a/submodules/TelegramUI/Sources/SharedNotificationManager.swift b/submodules/TelegramUI/Sources/SharedNotificationManager.swift index 77d8ea8fa5..603a877a6f 100644 --- a/submodules/TelegramUI/Sources/SharedNotificationManager.swift +++ b/submodules/TelegramUI/Sources/SharedNotificationManager.swift @@ -397,7 +397,7 @@ public final class SharedNotificationManager { if !messagesDeleted.isEmpty { let _ = account.postbox.transaction(ignoreDisabled: true, { transaction -> Void in - deleteMessages(transaction: transaction, mediaBox: account.postbox.mediaBox, ids: messagesDeleted) + TelegramEngine(account: account).messages.deleteMessages(transaction: transaction, ids: messagesDeleted) }).start() } diff --git a/submodules/TelegramVoip/Sources/GroupCallContext.swift b/submodules/TelegramVoip/Sources/GroupCallContext.swift index 8beb545dc0..a0387af49b 100644 --- a/submodules/TelegramVoip/Sources/GroupCallContext.swift +++ b/submodules/TelegramVoip/Sources/GroupCallContext.swift @@ -154,6 +154,12 @@ public final class OngoingGroupCallContext { case broadcast } + public enum VideoContentType { + case none + case generic + case screencast + } + public struct NetworkState: Equatable { public var isConnected: Bool public var isTransitioningFromBroadcastToRtc: Bool @@ -180,7 +186,7 @@ public final class OngoingGroupCallContext { private var broadcastPartsSource: BroadcastPartSource? - init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, enableVideo: Bool, enableNoiseSuppression: Bool) { + init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, videoContentType: VideoContentType, enableNoiseSuppression: Bool) { self.queue = queue var networkStateUpdatedImpl: ((GroupCallNetworkState) -> Void)? @@ -193,6 +199,16 @@ public final class OngoingGroupCallContext { let broadcastPartsSource = self.broadcastPartsSource + let _videoContentType: OngoingGroupCallVideoContentType + switch videoContentType { + case .generic: + _videoContentType = .generic + case .screencast: + _videoContentType = .screencast + case .none: + _videoContentType = .none + } + let videoSources = self.videoSources self.context = GroupCallThreadLocalContext( queue: ContextQueueImpl(queue: queue), @@ -223,7 +239,7 @@ public final class OngoingGroupCallContext { return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable) }, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit ?? 32, - enableVideo: enableVideo, + videoContentType: _videoContentType, enableNoiseSuppression: enableNoiseSuppression ) @@ -288,6 +304,10 @@ public final class OngoingGroupCallContext { return ssrc as NSNumber }) } + + func removeIncomingVideoSource(_ ssrc: UInt32) { + self.context.removeIncomingVideoSource(ssrc) + } func setVolume(ssrc: UInt32, volume: Double) { self.context.setVolumeForSsrc(ssrc, volume: volume) @@ -529,10 +549,10 @@ public final class OngoingGroupCallContext { } } - public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, enableVideo: Bool, enableNoiseSuppression: Bool) { + public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, videoContentType: VideoContentType, enableNoiseSuppression: Bool) { let queue = self.queue self.impl = QueueLocalObject(queue: queue, generate: { - return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, audioStreamData: audioStreamData, rejoinNeeded: rejoinNeeded, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, enableVideo: enableVideo, enableNoiseSuppression: enableNoiseSuppression) + return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, audioStreamData: audioStreamData, rejoinNeeded: rejoinNeeded, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, videoContentType: videoContentType, enableNoiseSuppression: enableNoiseSuppression) }) } @@ -593,6 +613,12 @@ public final class OngoingGroupCallContext { impl.removeSsrcs(ssrcs: ssrcs) } } + + public func removeIncomingVideoSource(_ ssrc: UInt32) { + self.impl.with { impl in + impl.removeIncomingVideoSource(ssrc) + } + } public func setVolume(ssrc: UInt32, volume: Double) { self.impl.with { impl in diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift index 2f5b294faf..39169aae5d 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift @@ -78,7 +78,7 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl { } } - func recentOnline(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, updated: @escaping (Int32) -> Void) -> Disposable { + func recentOnline(account: Account, accountPeerId: PeerId, peerId: PeerId, updated: @escaping (Int32) -> Void) -> Disposable { let context: PeerChannelMembersOnlineContext if let current = self.onlineContexts[peerId] { context = current @@ -88,7 +88,7 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl { self.onlineContexts[peerId] = context let signal = ( - chatOnlineMembers(postbox: postbox, network: network, peerId: peerId) + TelegramEngine(account: account).peers.chatOnlineMembers(peerId: peerId) |> then( .complete() |> delay(30.0, queue: .mainQueue()) @@ -483,7 +483,7 @@ public final class PeerChannelMemberCategoriesContextsManager { } } - public func recentOnline(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId) -> Signal { + public func recentOnline(account: Account, accountPeerId: PeerId, peerId: PeerId) -> Signal { return Signal { [weak self] subscriber in guard let strongSelf = self else { subscriber.putNext(0) @@ -491,7 +491,7 @@ public final class PeerChannelMemberCategoriesContextsManager { return EmptyDisposable } let disposable = strongSelf.impl.syncWith({ impl -> Disposable in - return impl.recentOnline(postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, updated: { value in + return impl.recentOnline(account: account, accountPeerId: accountPeerId, peerId: peerId, updated: { value in subscriber.putNext(value) }) }) diff --git a/submodules/TgVoipWebrtc/BUILD b/submodules/TgVoipWebrtc/BUILD index eb80e8dcc0..90a4c36cac 100644 --- a/submodules/TgVoipWebrtc/BUILD +++ b/submodules/TgVoipWebrtc/BUILD @@ -20,6 +20,9 @@ objc_library( "tgcalls/tgcalls/platform/darwin/VideoMetalViewMac.*", "tgcalls/tgcalls/platform/darwin/GLVideoViewMac.*", "tgcalls/tgcalls/platform/darwin/ScreenCapturer.*", + "tgcalls/tgcalls/platform/darwin/DesktopSharingCapturer.*", + "tgcalls/tgcalls/platform/darwin/DesktopCaptureSourceViewMac.*", + "tgcalls/tgcalls/platform/darwin/DesktopCaptureSourceView.*", "tgcalls/tgcalls/desktop_capturer/**", ]), hdrs = glob([ diff --git a/submodules/TgVoipWebrtc/PublicHeaders/TgVoipWebrtc/OngoingCallThreadLocalContext.h b/submodules/TgVoipWebrtc/PublicHeaders/TgVoipWebrtc/OngoingCallThreadLocalContext.h index 7a5856d170..f27af30947 100644 --- a/submodules/TgVoipWebrtc/PublicHeaders/TgVoipWebrtc/OngoingCallThreadLocalContext.h +++ b/submodules/TgVoipWebrtc/PublicHeaders/TgVoipWebrtc/OngoingCallThreadLocalContext.h @@ -183,6 +183,12 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) { OngoingGroupCallBroadcastPartStatusResyncNeeded }; +typedef NS_ENUM(int32_t, OngoingGroupCallVideoContentType) { + OngoingGroupCallVideoContentTypeNone, + OngoingGroupCallVideoContentTypeGeneric, + OngoingGroupCallVideoContentTypeScreencast, +}; + @interface OngoingGroupCallBroadcastPart : NSObject @property (nonatomic, readonly) int64_t timestampMilliseconds; @@ -196,7 +202,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) { @interface GroupCallThreadLocalContext : NSObject -- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit enableVideo:(bool)enableVideo enableNoiseSuppression:(bool)enableNoiseSuppression; +- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit videoContentType:(OngoingGroupCallVideoContentType)videoContentType enableNoiseSuppression:(bool)enableNoiseSuppression; - (void)stop; @@ -205,6 +211,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) { - (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion; - (void)setJoinResponsePayload:(NSString * _Nonnull)payload participants:(NSArray * _Nonnull)participants; - (void)removeSsrcs:(NSArray * _Nonnull)ssrcs; +- (void)removeIncomingVideoSource:(uint32_t)ssrc; - (void)addParticipants:(NSArray * _Nonnull)participants; - (void)setIsMuted:(bool)isMuted; - (void)setIsNoiseSuppressionEnabled:(bool)isNoiseSuppressionEnabled; diff --git a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm index 0496174e33..0ad2388c0c 100644 --- a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm +++ b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm @@ -859,7 +859,7 @@ private: @implementation GroupCallThreadLocalContext -- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit enableVideo:(bool)enableVideo enableNoiseSuppression:(bool)enableNoiseSuppression { +- (instancetype _Nonnull)initWithQueue:(id _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit videoContentType:(OngoingGroupCallVideoContentType)videoContentType enableNoiseSuppression:(bool)enableNoiseSuppression { self = [super init]; if (self != nil) { _queue = queue; @@ -867,6 +867,30 @@ private: _networkStateUpdated = [networkStateUpdated copy]; _videoCapturer = videoCapturer; + tgcalls::VideoContentType _videoContentType; + switch (videoContentType) { + case OngoingGroupCallVideoContentTypeGeneric: { + _videoContentType = tgcalls::VideoContentType::Generic; + break; + } + case OngoingGroupCallVideoContentTypeScreencast: { + _videoContentType = tgcalls::VideoContentType::Screencast; + break; + } + case OngoingGroupCallVideoContentTypeNone: { + _videoContentType = tgcalls::VideoContentType::None; + break; + } + default: { + _videoContentType = tgcalls::VideoContentType::None; + break; + } + } + + std::vector videoCodecPreferences; + videoCodecPreferences.push_back(tgcalls::VideoCodecName::VP8); + videoCodecPreferences.push_back(tgcalls::VideoCodecName::VP9); + __weak GroupCallThreadLocalContext *weakSelf = self; _instance.reset(new tgcalls::GroupInstanceCustomImpl((tgcalls::GroupInstanceDescriptor){ .threads = tgcalls::StaticThreads::getThreads(), @@ -944,7 +968,8 @@ private: return std::make_shared(task); }, .outgoingAudioBitrateKbit = outgoingAudioBitrateKbit, - .enableVideo = enableVideo, + .videoContentType = _videoContentType, + .videoCodecPreferences = videoCodecPreferences, .initialEnableNoiseSuppression = enableNoiseSuppression })); } @@ -1272,6 +1297,12 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn } } +- (void)removeIncomingVideoSource:(uint32_t)ssrc { + if (_instance) { + _instance->removeIncomingVideoSource(ssrc); + } +} + - (void)parseJsonIntoParticipant:(NSString *)payload participant:(tgcalls::GroupParticipantDescription &)participant { NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding]; if (payloadData == nil) { diff --git a/submodules/TgVoipWebrtc/tgcalls b/submodules/TgVoipWebrtc/tgcalls index e83f57813e..f000849f15 160000 --- a/submodules/TgVoipWebrtc/tgcalls +++ b/submodules/TgVoipWebrtc/tgcalls @@ -1 +1 @@ -Subproject commit e83f57813e0dd4b7abb2772f98c86ddf0ed47638 +Subproject commit f000849f159e255fabec70ea18312eb8ae6c69e0 diff --git a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift index 968fbc8eb3..d56763ddfd 100644 --- a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift +++ b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift @@ -123,7 +123,7 @@ final class WatchChatMessagesHandler: WatchRequestHandler { |> mapToSignal({ context -> Signal in if let context = context { let messageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId) - return applyMaxReadIndexInteractively(postbox: context.account.postbox, stateManager: context.account.stateManager, index: MessageIndex(id: messageId, timestamp: 0)) + return context.engine.messages.applyMaxReadIndexInteractively(index: MessageIndex(id: messageId, timestamp: 0)) } else { return .complete() } @@ -144,7 +144,7 @@ final class WatchChatMessagesHandler: WatchRequestHandler { |> take(1) |> mapToSignal({ context -> Signal<(Message, PresentationData)?, NoError> in if let context = context { - let messageSignal = downloadMessage(postbox: context.account.postbox, network: context.account.network, messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)) + let messageSignal = context.engine.messages.downloadMessage(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.messageId)) |> map { message -> (Message, PresentationData)? in if let message = message { return (message, context.sharedContext.currentPresentationData.with { $0 }) diff --git a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift index ab3e1d4267..d45a671e63 100644 --- a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift +++ b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift @@ -466,7 +466,7 @@ public func legacyEnqueueWebSearchMessages(_ selectionState: TGMediaSelectionCon } } - return legacyAssetPickerItemGenerator()(dict, nil, nil, nil) as Any + return legacyAssetPickerItemGenerator()(dict, nil, nil, nil, nil) as Any } else { return SSignal.complete() }