diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 95647dc58e..105864f977 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7778,6 +7778,7 @@ Sorry for the inconvenience."; "WebApp.Settings" = "Settings"; "Bot.AccepRecurrentInfo" = "I accept the [Terms of Service]() of **%1$@**"; +"Bot.AcceptTermsInfo" = "I accept the [Terms of Service]() of **%1$@**"; "Chat.AudioTranscriptionRateAction" = "Rate Transcription"; "Chat.AudioTranscriptionFeedbackTip" = "Thank you for your feedback."; diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index dfe138a708..900d33e343 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -559,7 +559,7 @@ private final class RecurrentConfirmationNode: ASDisplayNode { return super.hitTest(point, with: event) } - func update(presentationData: PresentationData, botName: String, width: CGFloat, sideInset: CGFloat) -> CGFloat { + func update(presentationData: PresentationData, botName: String, isRecurrent: Bool, width: CGFloat, sideInset: CGFloat) -> CGFloat { let spacing: CGFloat = 16.0 let topInset: CGFloat = 8.0 @@ -580,7 +580,7 @@ private final class RecurrentConfirmationNode: ASDisplayNode { self.textNode.linkHighlightColor = presentationData.theme.list.itemAccentColor.withAlphaComponent(0.2) let attributedText = parseMarkdownIntoAttributedString( - presentationData.strings.Bot_AccepRecurrentInfo(botName).string, + isRecurrent ? presentationData.strings.Bot_AccepRecurrentInfo(botName).string : presentationData.strings.Bot_AcceptTermsInfo(botName).string, attributes: MarkdownAttributes( body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: presentationData.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: presentationData.theme.list.freeTextColor), @@ -619,7 +619,7 @@ private final class ActionButtonPanelNode: ASDisplayNode { var height = max(layout.intrinsicInsets.bottom, layout.inputHeight ?? 0.0) + bottomPanelVerticalInset * 2.0 + BotCheckoutActionButton.height var actionButtonOffset: CGFloat = bottomPanelVerticalInset - if let invoice = invoice, let recurrentInfo = invoice.recurrentInfo, let botName = botName { + if let invoice = invoice, let termsInfo = invoice.termsInfo, let botName = botName { let recurrentConfirmationNode: RecurrentConfirmationNode if let current = self.recurrentConfirmationNode { recurrentConfirmationNode = current @@ -637,9 +637,7 @@ private final class ActionButtonPanelNode: ASDisplayNode { self.addSubnode(recurrentConfirmationNode) } - let _ = recurrentInfo - - let recurrentConfirmationHeight = recurrentConfirmationNode.update(presentationData: presentationData, botName: botName, width: layout.size.width, sideInset: layout.safeInsets.left + 33.0) + let recurrentConfirmationHeight = recurrentConfirmationNode.update(presentationData: presentationData, botName: botName, isRecurrent: termsInfo.isRecurrent, width: layout.size.width, sideInset: layout.safeInsets.left + 33.0) recurrentConfirmationNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: recurrentConfirmationHeight)) actionButtonOffset += recurrentConfirmationHeight @@ -776,10 +774,10 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz } self.actionButtonPanelNode.openRecurrentTerms = { [weak self] in - guard let strongSelf = self, let paymentForm = strongSelf.paymentFormValue, let recurrentInfo = paymentForm.invoice.recurrentInfo else { + guard let strongSelf = self, let paymentForm = strongSelf.paymentFormValue, let termsInfo = paymentForm.invoice.termsInfo else { return } - strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: recurrentInfo.termsUrl, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: { + strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: termsInfo.termsUrl, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: { self?.view.endEditing(true) }) } @@ -1191,7 +1189,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz if let paymentForm = self.paymentFormValue, totalAmount > 0 { payString = self.presentationData.strings.Checkout_PayPrice(formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency)).string - if let _ = paymentForm.invoice.recurrentInfo { + if let _ = paymentForm.invoice.termsInfo { if !self.actionButtonPanelNode.isAccepted { isButtonEnabled = false } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 3f9d6152d1..5c79361281 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1288,7 +1288,9 @@ public final class ChatListNode: ListView { super.init() - //self.useMainQueueTransactions = true + if case .internal = context.sharedContext.applicationBindings.appBuildType { + self.useMainQueueTransactions = true + } self.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor self.verticalScrollIndicatorFollowsOverscroll = true diff --git a/submodules/Display/Source/Navigation/NavigationContainer.swift b/submodules/Display/Source/Navigation/NavigationContainer.swift index 683547b170..95b2dd99d7 100644 --- a/submodules/Display/Source/Navigation/NavigationContainer.swift +++ b/submodules/Display/Source/Navigation/NavigationContainer.swift @@ -225,14 +225,19 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega return } - topController.viewWillDisappear(true) + topController.beginAppearanceTransition(false, animated: true) + //topController.viewWillDisappear(true) + let topNode = topController.displayNode var bottomControllerLayout = layout if bottomController.view.disableAutomaticKeyboardHandling.isEmpty { bottomControllerLayout = bottomControllerLayout.withUpdatedInputHeight(nil) } bottomController.containerLayoutUpdated(bottomControllerLayout, transition: .immediate) - bottomController.viewWillAppear(true) + + bottomController.beginAppearanceTransition(true, animated: true) + //bottomController.viewWillAppear(true) + let bottomNode = bottomController.displayNode let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, isFlat: self.isFlat, container: self, topNode: topNode, topNavigationBar: topController.transitionNavigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.transitionNavigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in @@ -291,9 +296,12 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega return } strongSelf.state.transition = nil - - top.value.viewDidAppear(true) - transition.previous.value.viewDidDisappear(true) + + top.value.endAppearanceTransition() + //top.value.viewDidAppear(true) + + transition.previous.value.endAppearanceTransition() + //transition.previous.value.viewDidDisappear(true) }) } } @@ -452,8 +460,13 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega } fromValue.value.viewWillLeaveNavigation() - fromValue.value.viewWillDisappear(true) - toValue.value.viewWillAppear(true) + + fromValue.value.beginAppearanceTransition(false, animated: true) + //fromValue.value.viewWillDisappear(true) + + toValue.value.beginAppearanceTransition(true, animated: true) + //toValue.value.viewWillAppear(true) + toValue.value.setIgnoreAppearanceMethodInvocations(true) if let layout = self.state.layout { toValue.value.displayNode.frame = CGRect(origin: CGPoint(), size: layout.size) @@ -517,11 +530,16 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega topTransition.previous.value.displayNode.removeFromSupernode() topTransition.previous.value.setIgnoreAppearanceMethodInvocations(false) } - topTransition.previous.value.viewDidDisappear(true) + + topTransition.previous.value.endAppearanceTransition() + //topTransition.previous.value.viewDidDisappear(true) + if let toValue = strongSelf.state.top, let layout = strongSelf.state.layout { toValue.value.displayNode.frame = CGRect(origin: CGPoint(), size: layout.size) strongSelf.applyLayout(layout: layout, to: toValue, isMaster: true, transition: .immediate) - toValue.value.viewDidAppear(true) + + toValue.value.endAppearanceTransition() + //toValue.value.viewDidAppear(true) } strongSelf.ignoreInputHeight = false @@ -533,24 +551,33 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega } fromValue.value.viewWillLeaveNavigation() - fromValue.value.viewWillDisappear(false) + + fromValue.value.beginAppearanceTransition(false, animated: false) + //fromValue.value.viewWillDisappear(false) self.keyboardViewManager?.dismissEditingWithoutAnimation(view: fromValue.value.view) fromValue.value.setIgnoreAppearanceMethodInvocations(true) fromValue.value.displayNode.removeFromSupernode() fromValue.value.setIgnoreAppearanceMethodInvocations(false) - fromValue.value.viewDidDisappear(false) + + fromValue.value.endAppearanceTransition() + //fromValue.value.viewDidDisappear(false) } if let toValue = toValue { self.applyLayout(layout: layout, to: toValue, isMaster: true, transition: .immediate) toValue.value.displayNode.frame = CGRect(origin: CGPoint(), size: layout.size) - toValue.value.viewWillAppear(false) + + toValue.value.beginAppearanceTransition(true, animated: false) + //toValue.value.viewWillAppear(false) + toValue.value.setIgnoreAppearanceMethodInvocations(true) self.addSubnode(toValue.value.displayNode) toValue.value.setIgnoreAppearanceMethodInvocations(false) toValue.value.displayNode.recursivelyEnsureDisplaySynchronously(true) - toValue.value.viewDidAppear(false) + + toValue.value.endAppearanceTransition() + //toValue.value.viewDidAppear(false) } self.ignoreInputHeight = false } diff --git a/submodules/TelegramCore/Sources/Account/Account.swift b/submodules/TelegramCore/Sources/Account/Account.swift index 4d9405f28c..c776913d72 100644 --- a/submodules/TelegramCore/Sources/Account/Account.swift +++ b/submodules/TelegramCore/Sources/Account/Account.swift @@ -1188,13 +1188,13 @@ public class Account { }, self.pendingPeerMediaUploadManager.uploadingPeerMedia |> map { uploadingPeerMedia in if !uploadingPeerMedia.isEmpty { - print("updatingMessageMedia: true") + print("uploadingPeerMedia: true") } return !uploadingPeerMedia.isEmpty ? AccountRunningImportantTasks.pendingMessages : [] }, self.accountPresenceManager.isPerformingUpdate() |> map { presenceUpdate in if presenceUpdate { - print("updatingMessageMedia: true") + print("accountPresenceManager isPerformingUpdate: true") return [] } return presenceUpdate ? AccountRunningImportantTasks.other : [] diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index d2e452f107..12926a2549 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -47,6 +47,7 @@ public struct BotPaymentInvoice : Equatable { public struct RecurrentInfo: Equatable { public var termsUrl: String + public var isRecurrent: Bool } public let isTest: Bool @@ -54,7 +55,7 @@ public struct BotPaymentInvoice : Equatable { public let currency: String public let prices: [BotPaymentPrice] public let tip: Tip? - public let recurrentInfo: RecurrentInfo? + public let termsInfo: RecurrentInfo? } public struct BotPaymentNativeProvider : Equatable { @@ -144,7 +145,7 @@ public enum BotPaymentFormRequestError { extension BotPaymentInvoice { init(apiInvoice: Api.Invoice) { switch apiInvoice { - case let .invoice(flags, currency, prices, maxTipAmount, suggestedTipAmounts, recurrentTermsUrl): + case let .invoice(flags, currency, prices, maxTipAmount, suggestedTipAmounts, termsUrl): var fields = BotPaymentInvoiceFields() if (flags & (1 << 1)) != 0 { fields.insert(.name) @@ -167,9 +168,10 @@ extension BotPaymentInvoice { if (flags & (1 << 7)) != 0 { fields.insert(.emailAvailableToProvider) } - var recurrentInfo: BotPaymentInvoice.RecurrentInfo? - if let recurrentTermsUrl = recurrentTermsUrl { - recurrentInfo = BotPaymentInvoice.RecurrentInfo(termsUrl: recurrentTermsUrl) + let isRecurrent = (flags & (1 << 9)) != 0 + var termsInfo: BotPaymentInvoice.RecurrentInfo? + if let termsUrl = termsUrl { + termsInfo = BotPaymentInvoice.RecurrentInfo(termsUrl: termsUrl, isRecurrent: isRecurrent) } var parsedTip: BotPaymentInvoice.Tip? if let maxTipAmount = maxTipAmount, let suggestedTipAmounts = suggestedTipAmounts { @@ -180,7 +182,7 @@ extension BotPaymentInvoice { case let .labeledPrice(label, amount): return BotPaymentPrice(label: label, amount: amount) } - }, tip: parsedTip, recurrentInfo: recurrentInfo) + }, tip: parsedTip, termsInfo: termsInfo) } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index dbc9671013..30f3d260b9 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -381,6 +381,8 @@ private final class StoryContainerScreenComponent: Component { private let sharedViewListsContext = StoryItemSetViewListComponent.SharedListsContext() + private var didAnimateIn: Bool = false + private var isAnimatingOut: Bool = false private var didAnimateOut: Bool = false private var isDismissedExlusively: Bool = false @@ -429,25 +431,6 @@ private final class StoryContainerScreenComponent: Component { }) self.addGestureRecognizer(horizontalPanRecognizer) - //TODO:move dismiss pan - /*let verticalPanRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.dismissPanGesture(_:)), allowedDirections: { [weak self] point in - guard let self, let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else { - return [] - } - if let environment = self.environment, case .regular = environment.metrics.widthClass { - } else { - if !itemSetComponentView.isPointInsideContentArea(point: self.convert(point, to: itemSetComponentView)) { - return [] - } - } - if !itemSetComponentView.allowsVerticalPanGesture() { - return [] - } - - return [.down] - }) - self.addGestureRecognizer(verticalPanRecognizer)*/ - let longPressRecognizer = StoryLongPressRecognizer(target: self, action: #selector(self.longPressGesture(_:))) longPressRecognizer.delegate = self longPressRecognizer.updateIsTracking = { [weak self] point in @@ -809,74 +792,6 @@ private final class StoryContainerScreenComponent: Component { } } - /*@objc private func dismissPanGesture(_ recognizer: UIPanGestureRecognizer) { - switch recognizer.state { - case .began: - self.dismissAllTooltips() - - if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] { - if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View { - if itemSetComponentView.hasActiveDeactivateableInput() { - itemSetComponentView.deactivateInput() - recognizer.isEnabled = false - recognizer.isEnabled = true - return - } - } - } - - self.verticalPanState = ItemSetPanState(fraction: 0.0, didBegin: true) - self.state?.updated(transition: .immediate) - case .changed: - let translation = recognizer.translation(in: self) - self.verticalPanState = ItemSetPanState(fraction: max(-1.0, min(1.0, translation.y / self.bounds.height)), didBegin: true) - self.state?.updated(transition: .immediate) - - if translation.y < -40.0 { - if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] { - if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View { - if let activateInputWhileDragging = itemSetComponentView.activateInputWhileDragging() { - activateInputWhileDragging() - - self.verticalPanState = nil - recognizer.state = .cancelled - self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) - } - } - } - } - case .cancelled, .ended: - if self.verticalPanState != nil { - let translation = recognizer.translation(in: self) - let velocity = recognizer.velocity(in: self) - - self.verticalPanState = nil - var updateState = true - - if translation.y > 200.0 || (translation.y > 5.0 && velocity.y > 200.0) { - self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) - self.environment?.controller()?.dismiss() - } else if translation.y < -200.0 || (translation.y < -100.0 && velocity.y < -100.0) { - if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] { - if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View { - if itemSetComponentView.activateInput() { - updateState = false - } - } - } - - if updateState || "".isEmpty { - self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) - } - } else { - self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) - } - } - default: - break - } - }*/ - @objc private func longPressGesture(_ recognizer: StoryLongPressRecognizer) { switch recognizer.state { case .began: @@ -963,13 +878,33 @@ private final class StoryContainerScreenComponent: Component { if let transitionIn = self.component?.transitionIn, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] { if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View { - itemSetComponentView.animateIn(transitionIn: transitionIn) + itemSetComponentView.animateIn(transitionIn: transitionIn, completion: { [weak self] in + guard let self else { + return + } + + self.didAnimateIn = true + self.state?.updated(transition: .immediate) + }) + } else { + self.didAnimateIn = true + self.state?.updated(transition: .immediate) } + } else { + self.didAnimateIn = true + self.state?.updated(transition: .immediate) } } else { self.layer.allowsGroupOpacity = true self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { [weak self] _ in - self?.layer.allowsGroupOpacity = false + guard let self else { + return + } + + self.layer.allowsGroupOpacity = false + + self.didAnimateIn = true + self.state?.updated(transition: .immediate) }) } @@ -1416,6 +1351,15 @@ private final class StoryContainerScreenComponent: Component { } } + if self.didAnimateIn && self.itemSetPanState == nil { + if i == focusedIndex - 1 { + isItemVisible = true + } + if i == focusedIndex + 1 { + isItemVisible = true + } + } + if isItemVisible { validIds.append(slice.peer.id) @@ -1449,6 +1393,8 @@ private final class StoryContainerScreenComponent: Component { } itemSetView.view.parentState = self.state + + let startTime = CFAbsoluteTimeGetCurrent() let _ = itemSetView.view.update( transition: itemSetTransition, component: AnyComponent(StoryItemSetContainerComponent( @@ -1592,6 +1538,7 @@ private final class StoryContainerScreenComponent: Component { if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View { if itemSetView.superview == nil { self.addSubview(itemSetView) + print("init time: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms") } if itemSetComponentView.superview == nil { itemSetView.tintLayer.isDoubleSided = false diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 68a5406eb8..3192122e0e 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -1937,7 +1937,7 @@ public final class StoryItemSetContainerComponent: Component { return nil } - func animateIn(transitionIn: StoryContainerScreen.TransitionIn) { + func animateIn(transitionIn: StoryContainerScreen.TransitionIn, completion: @escaping () -> Void) { if let inputPanelView = self.inputPanel.view { inputPanelView.layer.animatePosition( from: CGPoint(x: 0.0, y: self.bounds.height - inputPanelView.frame.minY), @@ -1998,7 +1998,9 @@ public final class StoryItemSetContainerComponent: Component { if let closeFriendIcon = self.privacyIcon?.view { closeFriendIcon.layer.animateAlpha(from: 0.0, to: closeFriendIcon.alpha, duration: 0.25) } - self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) + self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { _ in + completion() + }) self.topContentGradientView.layer.animateAlpha(from: 0.0, to: self.topContentGradientView.alpha, duration: 0.25) @@ -2057,6 +2059,8 @@ public final class StoryItemSetContainerComponent: Component { ) visibleItemView.layer.animateScale(from: innerScale, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) } + } else { + completion() } } @@ -3998,6 +4002,13 @@ public final class StoryItemSetContainerComponent: Component { self.captionItem = captionItem } + var enableEntities = true + if case .user = component.slice.peer { + if !component.slice.peer.isService && !component.slice.peer.isPremium { + enableEntities = false + } + } + let captionSize = captionItem.view.update( transition: captionItemTransition, component: AnyComponent(StoryContentCaptionComponent( @@ -4006,7 +4017,7 @@ public final class StoryItemSetContainerComponent: Component { strings: component.strings, theme: component.theme, text: component.slice.item.storyItem.text, - entities: component.slice.peer.isPremium ? component.slice.item.storyItem.entities : [], + entities: enableEntities ? component.slice.item.storyItem.entities : [], entityFiles: component.slice.item.entityFiles, action: { [weak self] action in guard let self, let component = self.component else { diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 335b1ce473..5209d4f40b 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -1476,6 +1476,15 @@ private func extractAccountManagerState(records: AccountRecordsView 1 * 1024 * 1024 { + previousReportedMemoryConsumption = value + Logger.shared.log("App \(self.episodeId)", "Memory consumption: \(value / (1024 * 1024)) MB") + } + }) + return true } @@ -2834,3 +2843,22 @@ private func downloadHTTPData(url: URL) -> Signal { } } } + +private func getMemoryConsumption() -> Int { + guard let memory_offset = MemoryLayout.offset(of: \task_vm_info_data_t.min_address) else { + return 0 + } + let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) + let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(memory_offset / MemoryLayout.size) + var info = task_vm_info_data_t() + var count = TASK_VM_INFO_COUNT + let kr = withUnsafeMutablePointer(to: &info) { infoPtr in + infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in + task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count) + } + } + guard kr == KERN_SUCCESS, count >= TASK_VM_INFO_REV1_COUNT else { + return 0 + } + return Int(info.phys_footprint) +}