diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index 655396d0dd..2ef790f35d 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -255,7 +255,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { let topInset: CGFloat = edgeTopInset var dismissing = false - if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 600.0) { + if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) { self.interactivelyDismissed?() dismissing = true } else if self.isExpanded { diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index 64431c8fbc..3d6ea10739 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -279,6 +279,9 @@ public class AttachmentController: ViewController { } @objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) { + guard !self.isDismissing else { + return + } if case .ended = recognizer.state { if let controller = self.currentControllers.last { controller.requestDismiss(completion: { [weak self] in diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index 23b4e0af15..05a27ec5d9 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -354,7 +354,10 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { case .speak: let _ = speakText(string) case .translate: - translateText(context: strongSelf.context, text: string) + if let parentController = strongSelf.baseNavigationController()?.topViewController as? ViewController { + let controller = TranslateScreen(context: strongSelf.context, text: string, fromLanguage: nil) + parentController.present(controller, in: .window(.root)) + } } }) recognizedContentNode.barcodeAction = { [weak self] payload, rect in diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index fc3d291219..7b0521d624 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1048,8 +1048,9 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, ignoredLanguages: translationSettings.ignoredLanguages) if canTranslate { - actions.append(ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuTranslate, accessibilityLabel: strings.Conversation_ContextMenuTranslate), action: { - translateText(context: context, text: text, fromLang: language) + actions.append(ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuTranslate, accessibilityLabel: strings.Conversation_ContextMenuTranslate), action: { [weak self] in + let controller = TranslateScreen(context: context, text: text, fromLanguage: language) + self?.present(controller, nil) })) } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 7fa0134d7d..2e1be985f3 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -21,8 +21,6 @@ import SparseItemGrid import UndoUI import PresentationDataUtils -let overflowInset: CGFloat = 0.0 - final class MediaPickerInteraction { let openMedia: (PHFetchResult, Int, UIImage?) -> Void let openSelectedMedia: (TGMediaSelectableItem, UIImage?) -> Void @@ -326,7 +324,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { if self.controller?.collection != nil { self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in - return point.x > 44.0 + overflowInset + return point.x > 44.0 } } @@ -381,7 +379,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } } if self.controller?.collection != nil { - self.selectionGesture?.sideInset = 44.0 + overflowInset + self.selectionGesture?.sideInset = 44.0 } } @@ -853,7 +851,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { insets.top += navigationBarHeight let bounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: layout.size.height)) - let innerBounds = CGRect(origin: CGPoint(x: -overflowInset, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height)) + let innerBounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: layout.size.height)) let itemsPerRow: Int if case .compact = layout.metrics.widthClass { @@ -960,7 +958,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { transition.updateFrame(node: self.backgroundNode, frame: innerBounds) self.backgroundNode.update(size: bounds.size, transition: transition) - transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(x: overflowInset, y: 0.0), size: CGSize(width: bounds.width - overflowInset * 2.0, height: bounds.height))) + transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: bounds.height))) self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: bounds.size, insets: gridInsets, scrollIndicatorInsets: nil, preloadSize: itemWidth, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemWidth), fillWidth: true, lineSpacing: itemSpacing, itemSpacing: itemSpacing), cutout: cameraRect), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, updateOpaqueState: nil, synchronousLoads: false), completion: { [weak self] _ in guard let strongSelf = self else { @@ -1065,6 +1063,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } private let groupedPromise = ValuePromise(true) + private var isDismissing = false + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer?, chatLocation: ChatLocation?, bannedSendMedia: (Int32, Bool)?, collection: PHAssetCollection? = nil, editingContext: TGMediaEditingContext? = nil, selectionContext: TGMediaSelectionContext? = nil) { self.context = context @@ -1165,7 +1165,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } } }, sendSelected: { [weak self] currentItem, silently, scheduleTime, animated, completion in - if let strongSelf = self, let selectionState = strongSelf.interaction?.selectionState { + if let strongSelf = self, let selectionState = strongSelf.interaction?.selectionState, !strongSelf.isDismissing { + strongSelf.isDismissing = true if let currentItem = currentItem { selectionState.setItem(currentItem, selected: true) } @@ -1314,12 +1315,16 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { public func requestDismiss(completion: @escaping () -> Void) { if let selectionState = self.interaction?.selectionState, selectionState.count() > 0 { + self.isDismissing = true let controller = textAlertController(context: self.context, title: nil, text: self.presentationData.strings.Attachment_CancelSelectionAlertText, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Attachment_CancelSelectionAlertNo, action: { }), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Attachment_CancelSelectionAlertYes, action: { [weak self] in self?.dismissAllTooltips() completion() })]) + controller.dismissed = { [weak self] in + self?.isDismissing = false + } self.present(controller, in: .window(.root)) } else { completion() diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 9447819a6e..63193090a1 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -5029,8 +5029,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, ignoredLanguages: translationSettings.ignoredLanguages) if canTranslate { - actions.append(ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuTranslate, accessibilityLabel: presentationData.strings.Conversation_ContextMenuTranslate), action: { - translateText(context: context, text: text, fromLang: language) + actions.append(ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuTranslate, accessibilityLabel: presentationData.strings.Conversation_ContextMenuTranslate), action: { [weak self] in + + let controller = TranslateScreen(context: context, text: text, fromLanguage: language) + self?.controller?.present(controller, in: .window(.root)) })) } diff --git a/submodules/TranslateUI/Sources/TranslateScreen.swift b/submodules/TranslateUI/Sources/TranslateScreen.swift index dbba4f9e4f..1bf9889561 100644 --- a/submodules/TranslateUI/Sources/TranslateScreen.swift +++ b/submodules/TranslateUI/Sources/TranslateScreen.swift @@ -588,50 +588,31 @@ public class TranslateScreen: ViewController { private var isDismissing = false func animateIn() { - guard let (layout, _) = self.currentLayout else { - return - } + ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 1.0) - if case .regular = layout.metrics.widthClass { - ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 0.1) - } else { - ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 1.0) - - let targetPosition = self.containerView.center - let startPosition = targetPosition.offsetBy(dx: 0.0, dy: self.bounds.height) - - self.containerView.center = startPosition - let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) - transition.animateView(allowUserInteraction: true, { - self.containerView.center = targetPosition - }, completion: { _ in - }) - } + let targetPosition = self.containerView.center + let startPosition = targetPosition.offsetBy(dx: 0.0, dy: self.bounds.height) + + self.containerView.center = startPosition + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + transition.animateView(allowUserInteraction: true, { + self.containerView.center = targetPosition + }, completion: { _ in + }) } func animateOut(completion: @escaping () -> Void = {}) { self.isDismissing = true - guard let (layout, _) = self.currentLayout else { - return - } + let positionTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) + positionTransition.updatePosition(layer: self.containerView.layer, position: CGPoint(x: self.containerView.center.x, y: self.bounds.height + self.containerView.bounds.height / 2.0), completion: { [weak self] _ in + self?.controller?.dismiss(animated: false, completion: completion) + }) + let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) + alphaTransition.updateAlpha(node: self.dim, alpha: 0.0) - if case .regular = layout.metrics.widthClass { - self.layer.allowsGroupOpacity = true - self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak self] _ in - self?.controller?.dismiss(animated: false, completion: completion) - }) - } else { - let positionTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) - positionTransition.updatePosition(layer: self.containerView.layer, position: CGPoint(x: self.containerView.center.x, y: self.bounds.height + self.containerView.bounds.height / 2.0), completion: { [weak self] _ in - self?.controller?.dismiss(animated: false, completion: completion) - }) - let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) - alphaTransition.updateAlpha(node: self.dim, alpha: 0.0) - - if !self.temporaryDismiss { - self.controller?.updateModalStyleOverlayTransitionFactor(0.0, transition: positionTransition) - } + if !self.temporaryDismiss { + self.controller?.updateModalStyleOverlayTransitionFactor(0.0, transition: positionTransition) } } @@ -668,6 +649,7 @@ public class TranslateScreen: ViewController { let clipFrame: CGRect if layout.metrics.widthClass == .compact { + self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.25) if isLandscape { self.containerView.layer.cornerRadius = 0.0 } else { @@ -701,13 +683,19 @@ public class TranslateScreen: ViewController { clipFrame = CGRect(x: containerFrame.minX, y: containerFrame.minY, width: containerFrame.width, height: containerFrame.height) } } else { - let unscaledFrame = CGRect(origin: CGPoint(), size: layout.size) - clipFrame = unscaledFrame + self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.4) + self.containerView.layer.cornerRadius = 10.0 + + let verticalInset: CGFloat = 44.0 + + let maxSide = max(layout.size.width, layout.size.height) + let minSide = min(layout.size.width, layout.size.height) + let containerSize = CGSize(width: min(layout.size.width - 20.0, floor(maxSide / 2.0)), height: min(layout.size.height, minSide) - verticalInset * 2.0) + clipFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - containerSize.width) / 2.0), y: floor((layout.size.height - containerSize.height) / 2.0)), size: containerSize) } transition.setFrame(view: self.containerView, frame: clipFrame) transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: clipFrame.size), completion: nil) - transition.setFrame(view: self.hostView, frame: CGRect(origin: CGPoint(), size: clipFrame.size), completion: nil) let environment = ViewControllerComponentContainer.Environment( statusBarHeight: 0.0, @@ -729,6 +717,7 @@ public class TranslateScreen: ViewController { forceUpdate: true, containerSize: CGSize(width: clipFrame.size.width, height: 10000.0) ) + transition.setFrame(view: self.hostView, frame: CGRect(origin: CGPoint(), size: contentSize), completion: nil) self.scrollView.contentSize = contentSize } @@ -892,7 +881,7 @@ public class TranslateScreen: ViewController { let topInset: CGFloat = edgeTopInset var dismissing = false - if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 600.0) { + if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) { self.controller?.dismiss(animated: true, completion: nil) dismissing = true } else if self.isExpanded { @@ -981,7 +970,11 @@ public class TranslateScreen: ViewController { public convenience init(context: AccountContext, text: String, fromLanguage: String?, toLanguage: String? = nil, isExpanded: Bool = false) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let toLanguage = toLanguage ?? presentationData.strings.baseLanguageCode + var toLanguage = toLanguage ?? presentationData.strings.baseLanguageCode + + if toLanguage == fromLanguage { + toLanguage = "en" + } var copyTranslationImpl: ((String) -> Void)? var changeLanguageImpl: ((String, String, @escaping (String, String) -> Void) -> Void)? @@ -1084,11 +1077,22 @@ public class TranslateScreen: ViewController { override public func updateNavigationBarLayout(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { var navigationLayout = self.navigationLayout(layout: layout) var navigationFrame = navigationLayout.navigationFrame + + var layout = layout + if case .regular = layout.metrics.widthClass { + let verticalInset: CGFloat = 44.0 + let maxSide = max(layout.size.width, layout.size.height) + let minSide = min(layout.size.width, layout.size.height) + let containerSize = CGSize(width: min(layout.size.width - 20.0, floor(maxSide / 2.0)), height: min(layout.size.height, minSide) - verticalInset * 2.0) + let clipFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - containerSize.width) / 2.0), y: floor((layout.size.height - containerSize.height) / 2.0)), size: containerSize) + navigationFrame.size.width = clipFrame.width + layout.size = clipFrame.size + } + navigationFrame.size.height = 56.0 navigationLayout.navigationFrame = navigationFrame navigationLayout.defaultContentHeight = 56.0 - var layout = layout layout.statusBarHeight = nil self.applyNavigationBarLayout(layout, navigationLayout: navigationLayout, additionalBackgroundHeight: 0.0, transition: transition)