From df2354e9bb3099fb7fb03529ba1de5192ec5a030 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 14 Apr 2022 03:20:29 +0400 Subject: [PATCH] Various fixes --- submodules/Display/Source/NavigationBar.swift | 17 ++++--- .../Display/Source/NavigationButtonNode.swift | 1 + .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/InstantPageNavigationBar.swift | 7 +-- .../Sources/ItemListMaskAccessory.swift | 39 --------------- .../Sources/LegacyMediaPickerGallery.swift | 9 +++- .../MtProtoKit/Sources/MTApiEnvironment.m | 10 ++++ .../Sources/PasscodeEntryControllerNode.swift | 5 ++ .../Sources/PasscodeEntryLabelNode.swift | 9 ++-- .../Sources/ReactionContextNode.swift | 7 +-- .../Sources/ShareSearchContainerNode.swift | 50 +++++++++++++------ .../TranslateUI/Sources/TranslateScreen.swift | 16 +++++- 12 files changed, 93 insertions(+), 79 deletions(-) delete mode 100644 submodules/ItemListUI/Sources/ItemListMaskAccessory.swift diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 940d5b0f62..5c723deef3 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -534,11 +534,11 @@ open class NavigationBar: ASDisplayNode { self.previousItemListenerKey = itemValue.addSetTitleListener { [weak self] _, _ in if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem { if let customBackButtonText = strongSelf.customBackButtonText { - strongSelf.backButtonNode.updateManualText(customBackButtonText) + strongSelf.backButtonNode.updateManualText(customBackButtonText, isBack: true) } else if let backBarButtonItem = itemValue.backBarButtonItem { - strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "") + strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "", isBack: true) } else { - strongSelf.backButtonNode.updateManualText(itemValue.title ?? "") + strongSelf.backButtonNode.updateManualText(itemValue.title ?? "", isBack: true) } strongSelf.invalidateCalculatedLayout() strongSelf.requestLayout() @@ -548,11 +548,11 @@ open class NavigationBar: ASDisplayNode { self.previousItemBackListenerKey = itemValue.addSetBackBarButtonItemListener { [weak self] _, _, _ in if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem { if let customBackButtonText = strongSelf.customBackButtonText { - strongSelf.backButtonNode.updateManualText(customBackButtonText) + strongSelf.backButtonNode.updateManualText(customBackButtonText, isBack: true) } else if let backBarButtonItem = itemValue.backBarButtonItem { - strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "") + strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "", isBack: true) } else { - strongSelf.backButtonNode.updateManualText(itemValue.title ?? "") + strongSelf.backButtonNode.updateManualText(itemValue.title ?? "", isBack: true) } strongSelf.invalidateCalculatedLayout() strongSelf.requestLayout() @@ -682,7 +682,7 @@ open class NavigationBar: ASDisplayNode { } if let backTitle = backTitle { - self.backButtonNode.updateManualText(backTitle) + self.backButtonNode.updateManualText(backTitle, isBack: true) if self.backButtonNode.supernode == nil { self.buttonsContainerNode.addSubnode(self.backButtonNode) self.buttonsContainerNode.addSubnode(self.backButtonArrow) @@ -861,12 +861,15 @@ open class NavigationBar: ASDisplayNode { self.titleNode.accessibilityTraits = .header self.backButtonNode = NavigationButtonNode() + self.backButtonNode.hitTestSlop = UIEdgeInsets(top: 0.0, left: -20.0, bottom: 0.0, right: 0.0) + self.badgeNode = NavigationBarBadgeNode(fillColor: self.presentationData.theme.buttonColor, strokeColor: self.presentationData.theme.buttonColor, textColor: self.presentationData.theme.badgeTextColor) self.badgeNode.isUserInteractionEnabled = false self.badgeNode.isHidden = true self.backButtonArrow = ASImageNode() self.backButtonArrow.displayWithoutProcessing = true self.backButtonArrow.displaysAsynchronously = false + self.backButtonArrow.isUserInteractionEnabled = false self.leftButtonNode = NavigationButtonNode() self.rightButtonNode = NavigationButtonNode() self.rightButtonNode.hitTestSlop = UIEdgeInsets(top: -4.0, left: -4.0, bottom: -4.0, right: -10.0) diff --git a/submodules/Display/Source/NavigationButtonNode.swift b/submodules/Display/Source/NavigationButtonNode.swift index 1fa03b0b78..dc7db05b37 100644 --- a/submodules/Display/Source/NavigationButtonNode.swift +++ b/submodules/Display/Source/NavigationButtonNode.swift @@ -426,6 +426,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode { node.bold = false node.isEnabled = true node.node = nil + node.hitTestSlop = isBack ? UIEdgeInsets(top: 0.0, left: -20.0, bottom: 0.0, right: 0.0) : UIEdgeInsets() if 1 < self.nodes.count { for i in 1 ..< self.nodes.count { diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 0beaa3ea52..89f2642a16 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -349,7 +349,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { let maxBarHeight: CGFloat if !layout.safeInsets.top.isZero { if let statusBarHeight = layout.statusBarHeight, statusBarHeight > 34.0 { - maxBarHeight = statusBarHeight + 34.0 + maxBarHeight = statusBarHeight + 44.0 } else { maxBarHeight = layout.safeInsets.top + 34.0 } diff --git a/submodules/InstantPageUI/Sources/InstantPageNavigationBar.swift b/submodules/InstantPageUI/Sources/InstantPageNavigationBar.swift index b2d6bb5283..127327ec9b 100644 --- a/submodules/InstantPageUI/Sources/InstantPageNavigationBar.swift +++ b/submodules/InstantPageUI/Sources/InstantPageNavigationBar.swift @@ -167,12 +167,7 @@ final class InstantPageNavigationBar: ASDisplayNode { } func updateLayout(size: CGSize, minHeight: CGFloat, maxHeight: CGFloat, topInset: CGFloat, leftInset: CGFloat, rightInset: CGFloat, title: String?, pageProgress: CGFloat, transition: ContainedViewLayoutTransition) { - let progressHeight: CGFloat - if !topInset.isZero { - progressHeight = size.height - topInset + 11.0 - UIScreenPixel - } else { - progressHeight = size.height - } + let progressHeight = size.height transition.updateFrame(node: self.pageProgressNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - progressHeight), size: CGSize(width: floorToScreenPixels(size.width * pageProgress), height: progressHeight))) let transitionFactor = (size.height - minHeight) / (maxHeight - minHeight) diff --git a/submodules/ItemListUI/Sources/ItemListMaskAccessory.swift b/submodules/ItemListUI/Sources/ItemListMaskAccessory.swift deleted file mode 100644 index 11300794df..0000000000 --- a/submodules/ItemListUI/Sources/ItemListMaskAccessory.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Foundation -import UIKit -import Display -import AsyncDisplayKit - -final class ItemListMaskAccessoryItem: ListViewAccessoryItem { - private let sectionId: Int32 - - init(sectionId: Int32) { - self.sectionId = sectionId - } - - func isEqualToItem(_ other: ListViewAccessoryItem) -> Bool { - if case let other as ItemListMaskAccessoryItem = other { - return self.sectionId == other.sectionId - } - - return false - } - - func node(synchronous: Bool) -> ListViewAccessoryItemNode { - let node = ItemListMaskAccessoryItemItemNode() - node.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0)) - return node - } -} - -final class ItemListMaskAccessoryItemItemNode: ListViewAccessoryItemNode { - let node: ASDisplayNode - - override init() { - self.node = ASDisplayNode() - self.node.backgroundColor = .red - - super.init() - - self.addSubnode(self.node) - } -} diff --git a/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift b/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift index 004b0a73b1..21f9f73cbc 100644 --- a/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift +++ b/submodules/MediaPickerUI/Sources/LegacyMediaPickerGallery.swift @@ -109,7 +109,14 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, (items, focusItem) = gallerySelectionItems(item: item, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail) } - let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: true, allowCaptionEntities: true, hasTimer: hasTimer, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: true, hasCamera: false, recipientName: peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))! + let recipientName: String? + if peer?.id == context.account.peerId { + recipientName = presentationData.strings.DialogList_SavedMessages + } else { + recipientName = peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + } + + let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: true, allowCaptionEntities: true, hasTimer: hasTimer, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: true, hasCamera: false, recipientName: recipientName)! model.stickersContext = paintStickersContext controller.model = model model.controller = controller diff --git a/submodules/MtProtoKit/Sources/MTApiEnvironment.m b/submodules/MtProtoKit/Sources/MTApiEnvironment.m index 8f973423e2..4cec9e1793 100644 --- a/submodules/MtProtoKit/Sources/MTApiEnvironment.m +++ b/submodules/MtProtoKit/Sources/MTApiEnvironment.m @@ -596,6 +596,8 @@ NSString *suffix = @""; return @"iPhone 13 Mini"; if ([platform isEqualToString:@"iPhone14,5"]) return @"iPhone 13"; + if ([platform isEqualToString:@"iPhone14,6"]) + return @"iPhone SE (3rd gen)"; if ([platform hasPrefix:@"iPod1"]) return @"iPod touch 1G"; @@ -727,6 +729,14 @@ NSString *suffix = @""; [platform isEqualToString:@"iPad13,10"] || [platform isEqualToString:@"iPad13,11"]) return @"iPad Pro 12.9 inch (5th gen)"; + + if ([platform isEqualToString:@"iPad13,16"] || + [platform isEqualToString:@"iPad13,17"]) + return @"iPad Air (5th gen)"; + + if ([platform isEqualToString:@"iPad14,1"] || + [platform isEqualToString:@"iPad14,2"]) + return @"iPad mini (6th gen)"; if ([platform hasPrefix:@"iPhone"]) return @"Unknown iPhone"; diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift index c019e6c76a..6011d9ca07 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift @@ -401,6 +401,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode { Queue.mainQueue().after(1.5, { self.titleNode.setAttributedText(NSAttributedString(string: self.strings.EnterPasscode_EnterPasscode, font: titleFont, textColor: .white), animation: .crossFade) + if let validLayout = self.validLayout { + self.containerLayoutUpdated(validLayout, navigationBarHeight: 0.0, transition: .animated(duration: 0.5, curve: .easeInOut)) + } }) completion() @@ -471,6 +474,8 @@ final class PasscodeEntryControllerNode: ASDisplayNode { if layout.size.width == 320.0 || (isLandscape && keyboardHidden) { self.iconNode.alpha = 0.0 + } else { + self.iconNode.alpha = 1.0 } let passcodeLayout = PasscodeLayout(layout: layout, modalPresentation: self.modalPresentation) diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryLabelNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryLabelNode.swift index d5b1783263..2eb440cdfb 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryLabelNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryLabelNode.swift @@ -11,7 +11,7 @@ enum PasscodeEntryTitleAnimation { final class PasscodeEntryLabelNode: ASDisplayNode { private let wrapperNode: ASDisplayNode - private let textNode: ASTextNode + private let textNode: ImmediateTextNode private var validLayout: CGSize? @@ -19,10 +19,11 @@ final class PasscodeEntryLabelNode: ASDisplayNode { self.wrapperNode = ASDisplayNode() self.wrapperNode.clipsToBounds = true - self.textNode = ASTextNode() + self.textNode = ImmediateTextNode() self.textNode.isLayerBacked = false self.textNode.textAlignment = .center self.textNode.displaysAsynchronously = false + self.textNode.maximumNumberOfLines = 2 super.init() @@ -56,9 +57,9 @@ final class PasscodeEntryLabelNode: ASDisplayNode { snapshotView.frame = self.textNode.frame self.textNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.textNode.view) self.textNode.alpha = 0.0 + self.textNode.attributedText = text snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in snapshotView?.removeFromSuperview() - self.textNode.attributedText = text self.textNode.alpha = 1.0 self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { _ in completion() @@ -81,7 +82,7 @@ final class PasscodeEntryLabelNode: ASDisplayNode { func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { self.validLayout = size - let textSize = self.textNode.measure(size) + let textSize = self.textNode.updateLayout(size) let textFrame = CGRect(x: floor((size.width - textSize.width) / 2.0), y: 0.0, width: textSize.width, height: textSize.height) transition.updateFrame(node: self.wrapperNode, frame: textFrame) transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(), size: textSize)) diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 9d5681fa61..9dae1e28e3 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -702,6 +702,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { return nil } + private let longPressDuration: Double = 1.5 @objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) { switch recognizer.state { case .began: @@ -709,7 +710,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { if let itemNode = self.reactionItemNode(at: point) { self.highlightedReaction = itemNode.item.reaction if #available(iOS 13.0, *) { - self.continuousHaptic = try? ContinuousHaptic(duration: 2.5) + self.continuousHaptic = try? ContinuousHaptic(duration: longPressDuration) } if self.hapticFeedback == nil { @@ -717,11 +718,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .animated(duration: 2.5, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .animated(duration: longPressDuration, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } self.longPressTimer?.invalidate() - self.longPressTimer = SwiftSignalKit.Timer(timeout: 2.5, repeat: false, completion: { [weak self] in + self.longPressTimer = SwiftSignalKit.Timer(timeout: longPressDuration, repeat: false, completion: { [weak self] in guard let strongSelf = self else { return } diff --git a/submodules/ShareController/Sources/ShareSearchContainerNode.swift b/submodules/ShareController/Sources/ShareSearchContainerNode.swift index 5c3bcfa6ec..3c7c79f916 100644 --- a/submodules/ShareController/Sources/ShareSearchContainerNode.swift +++ b/submodules/ShareController/Sources/ShareSearchContainerNode.swift @@ -138,16 +138,17 @@ private struct ShareSearchGridTransaction { let insertions: [GridNodeInsertItem] let updates: [GridNodeUpdateItem] let animated: Bool + let crossFade: Bool } -private func preparedGridEntryTransition(context: AccountContext, from fromEntries: [ShareSearchPeerEntry], to toEntries: [ShareSearchPeerEntry], interfaceInteraction: ShareControllerInteraction) -> ShareSearchGridTransaction { +private func preparedGridEntryTransition(context: AccountContext, from fromEntries: [ShareSearchPeerEntry], to toEntries: [ShareSearchPeerEntry], interfaceInteraction: ShareControllerInteraction, crossFade: Bool) -> ShareSearchGridTransaction { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interfaceInteraction: interfaceInteraction), previousIndex: $0.2) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, interfaceInteraction: interfaceInteraction)) } - return ShareSearchGridTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: false) + return ShareSearchGridTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: false, crossFade: crossFade) } private func preparedRecentEntryTransition(context: AccountContext, from fromEntries: [ShareSearchRecentEntry], to toEntries: [ShareSearchRecentEntry], interfaceInteraction: ShareControllerInteraction) -> ShareSearchGridTransaction { @@ -157,7 +158,7 @@ private func preparedRecentEntryTransition(context: AccountContext, from fromEnt let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interfaceInteraction: interfaceInteraction), previousIndex: $0.2) } let updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, interfaceInteraction: interfaceInteraction)) } - return ShareSearchGridTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: false) + return ShareSearchGridTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: false, crossFade: false) } final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { @@ -236,8 +237,8 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) - let foundItems = searchQuery.get() - |> mapToSignal { query -> Signal<[ShareSearchPeerEntry]?, NoError> in + let foundItems = self.searchQuery.get() + |> mapToSignal { query -> Signal<([ShareSearchPeerEntry]?, Bool), NoError> in if !query.isEmpty { let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1) let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased()) @@ -251,7 +252,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { ) return combineLatest(accountPeer, foundLocalPeers, foundRemotePeers) - |> map { accountPeer, foundLocalPeers, foundRemotePeers -> [ShareSearchPeerEntry]? in + |> map { accountPeer, foundLocalPeers, foundRemotePeers -> ([ShareSearchPeerEntry]?, Bool) in var entries: [ShareSearchPeerEntry] = [] var index: Int32 = 0 @@ -276,7 +277,9 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { } } + var isPlaceholder = false if foundRemotePeers.2 { + isPlaceholder = true for _ in 0 ..< 4 { entries.append(ShareSearchPeerEntry(index: index, peer: nil, presence: nil, theme: theme, strings: strings)) index += 1 @@ -301,26 +304,29 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { } } - return entries + return (entries, isPlaceholder) } } else { - return .single(nil) + return .single((nil, false)) } } - let previousSearchItems = Atomic<[ShareSearchPeerEntry]?>(value: nil) + let previousSearchItemsAndIsPlaceholder = Atomic<([ShareSearchPeerEntry]?, Bool)>(value: (nil, false)) self.searchDisposable.set((foundItems - |> deliverOnMainQueue).start(next: { [weak self] entries in + |> deliverOnMainQueue).start(next: { [weak self] entriesAndIsPlaceholder in if let strongSelf = self { - let previousEntries = previousSearchItems.swap(entries) + let (entries, isPlaceholder) = entriesAndIsPlaceholder + let previousEntries = previousSearchItemsAndIsPlaceholder.swap(entriesAndIsPlaceholder) strongSelf.entries = entries ?? [] + + let firstTime = previousEntries.0 == nil + let crossFade = !firstTime && previousEntries.1 && !isPlaceholder - let firstTime = previousEntries == nil - let transition = preparedGridEntryTransition(context: context, from: previousEntries ?? [], to: entries ?? [], interfaceInteraction: controllerInteraction) + let transition = preparedGridEntryTransition(context: context, from: previousEntries.0 ?? [], to: entries ?? [], interfaceInteraction: controllerInteraction, crossFade: crossFade) strongSelf.enqueueTransition(transition, firstTime: firstTime) - if (previousEntries == nil) != (entries == nil) { - if previousEntries == nil { + if (previousEntries.0 == nil) != (entries == nil) { + if previousEntries.0 == nil { strongSelf.recentGridNode.isHidden = true strongSelf.contentGridNode.isHidden = false strongSelf.transitionToContentGridLayout() @@ -584,11 +590,23 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { private func dequeueTransition() { if let (transition, _) = self.enqueuedTransitions.first { self.enqueuedTransitions.remove(at: 0) - + var itemTransition: ContainedViewLayoutTransition = .immediate if transition.animated { itemTransition = .animated(duration: 0.3, curve: .spring) } + + if transition.crossFade { + if let snapshotView = self.contentGridNode.view.snapshotView(afterScreenUpdates: false) { + self.contentGridNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.contentGridNode.view) + snapshotView.frame = self.contentGridNode.frame + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } + } + self.contentGridNode.transaction(GridNodeTransaction(deleteItems: transition.deletions, insertItems: transition.insertions, updateItems: transition.updates, scrollToItem: nil, updateLayout: nil, itemTransition: itemTransition, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, synchronousLoads: true), completion: { _ in }) } } diff --git a/submodules/TranslateUI/Sources/TranslateScreen.swift b/submodules/TranslateUI/Sources/TranslateScreen.swift index b192d583f7..da8dfe58c5 100644 --- a/submodules/TranslateUI/Sources/TranslateScreen.swift +++ b/submodules/TranslateUI/Sources/TranslateScreen.swift @@ -240,7 +240,12 @@ private final class TranslateScreenComponent: CombinedComponent { let itemSpacing: CGFloat = 16.0 let itemHeight: CGFloat = 44.0 - let locale = Locale(identifier: environment.strings.baseLanguageCode) + var languageCode = environment.strings.baseLanguageCode + let rawSuffix = "-raw" + if languageCode.hasSuffix(rawSuffix) { + languageCode = String(languageCode.dropLast(rawSuffix.count)) + } + let locale = Locale(identifier: languageCode) let fromLanguage: String if let languageCode = state.fromLanguage { fromLanguage = locale.localizedString(forLanguageCode: languageCode) ?? "" @@ -984,7 +989,14 @@ 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 } - var toLanguage = toLanguage ?? presentationData.strings.baseLanguageCode + + var baseLanguageCode = presentationData.strings.baseLanguageCode + let rawSuffix = "-raw" + if baseLanguageCode.hasSuffix(rawSuffix) { + baseLanguageCode = String(baseLanguageCode.dropLast(rawSuffix.count)) + } + + var toLanguage = toLanguage ?? baseLanguageCode if toLanguage == fromLanguage { toLanguage = "en"