mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Various fixes
This commit is contained in:
parent
97392afb9e
commit
df2354e9bb
@ -534,11 +534,11 @@ open class NavigationBar: ASDisplayNode {
|
|||||||
self.previousItemListenerKey = itemValue.addSetTitleListener { [weak self] _, _ in
|
self.previousItemListenerKey = itemValue.addSetTitleListener { [weak self] _, _ in
|
||||||
if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem {
|
if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem {
|
||||||
if let customBackButtonText = strongSelf.customBackButtonText {
|
if let customBackButtonText = strongSelf.customBackButtonText {
|
||||||
strongSelf.backButtonNode.updateManualText(customBackButtonText)
|
strongSelf.backButtonNode.updateManualText(customBackButtonText, isBack: true)
|
||||||
} else if let backBarButtonItem = itemValue.backBarButtonItem {
|
} else if let backBarButtonItem = itemValue.backBarButtonItem {
|
||||||
strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "")
|
strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "", isBack: true)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.backButtonNode.updateManualText(itemValue.title ?? "")
|
strongSelf.backButtonNode.updateManualText(itemValue.title ?? "", isBack: true)
|
||||||
}
|
}
|
||||||
strongSelf.invalidateCalculatedLayout()
|
strongSelf.invalidateCalculatedLayout()
|
||||||
strongSelf.requestLayout()
|
strongSelf.requestLayout()
|
||||||
@ -548,11 +548,11 @@ open class NavigationBar: ASDisplayNode {
|
|||||||
self.previousItemBackListenerKey = itemValue.addSetBackBarButtonItemListener { [weak self] _, _, _ in
|
self.previousItemBackListenerKey = itemValue.addSetBackBarButtonItemListener { [weak self] _, _, _ in
|
||||||
if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem {
|
if let strongSelf = self, let previousItem = strongSelf.previousItem, case let .item(itemValue) = previousItem {
|
||||||
if let customBackButtonText = strongSelf.customBackButtonText {
|
if let customBackButtonText = strongSelf.customBackButtonText {
|
||||||
strongSelf.backButtonNode.updateManualText(customBackButtonText)
|
strongSelf.backButtonNode.updateManualText(customBackButtonText, isBack: true)
|
||||||
} else if let backBarButtonItem = itemValue.backBarButtonItem {
|
} else if let backBarButtonItem = itemValue.backBarButtonItem {
|
||||||
strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "")
|
strongSelf.backButtonNode.updateManualText(backBarButtonItem.title ?? "", isBack: true)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.backButtonNode.updateManualText(itemValue.title ?? "")
|
strongSelf.backButtonNode.updateManualText(itemValue.title ?? "", isBack: true)
|
||||||
}
|
}
|
||||||
strongSelf.invalidateCalculatedLayout()
|
strongSelf.invalidateCalculatedLayout()
|
||||||
strongSelf.requestLayout()
|
strongSelf.requestLayout()
|
||||||
@ -682,7 +682,7 @@ open class NavigationBar: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let backTitle = backTitle {
|
if let backTitle = backTitle {
|
||||||
self.backButtonNode.updateManualText(backTitle)
|
self.backButtonNode.updateManualText(backTitle, isBack: true)
|
||||||
if self.backButtonNode.supernode == nil {
|
if self.backButtonNode.supernode == nil {
|
||||||
self.buttonsContainerNode.addSubnode(self.backButtonNode)
|
self.buttonsContainerNode.addSubnode(self.backButtonNode)
|
||||||
self.buttonsContainerNode.addSubnode(self.backButtonArrow)
|
self.buttonsContainerNode.addSubnode(self.backButtonArrow)
|
||||||
@ -861,12 +861,15 @@ open class NavigationBar: ASDisplayNode {
|
|||||||
self.titleNode.accessibilityTraits = .header
|
self.titleNode.accessibilityTraits = .header
|
||||||
|
|
||||||
self.backButtonNode = NavigationButtonNode()
|
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 = NavigationBarBadgeNode(fillColor: self.presentationData.theme.buttonColor, strokeColor: self.presentationData.theme.buttonColor, textColor: self.presentationData.theme.badgeTextColor)
|
||||||
self.badgeNode.isUserInteractionEnabled = false
|
self.badgeNode.isUserInteractionEnabled = false
|
||||||
self.badgeNode.isHidden = true
|
self.badgeNode.isHidden = true
|
||||||
self.backButtonArrow = ASImageNode()
|
self.backButtonArrow = ASImageNode()
|
||||||
self.backButtonArrow.displayWithoutProcessing = true
|
self.backButtonArrow.displayWithoutProcessing = true
|
||||||
self.backButtonArrow.displaysAsynchronously = false
|
self.backButtonArrow.displaysAsynchronously = false
|
||||||
|
self.backButtonArrow.isUserInteractionEnabled = false
|
||||||
self.leftButtonNode = NavigationButtonNode()
|
self.leftButtonNode = NavigationButtonNode()
|
||||||
self.rightButtonNode = NavigationButtonNode()
|
self.rightButtonNode = NavigationButtonNode()
|
||||||
self.rightButtonNode.hitTestSlop = UIEdgeInsets(top: -4.0, left: -4.0, bottom: -4.0, right: -10.0)
|
self.rightButtonNode.hitTestSlop = UIEdgeInsets(top: -4.0, left: -4.0, bottom: -4.0, right: -10.0)
|
||||||
|
|||||||
@ -426,6 +426,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
|
|||||||
node.bold = false
|
node.bold = false
|
||||||
node.isEnabled = true
|
node.isEnabled = true
|
||||||
node.node = nil
|
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 {
|
if 1 < self.nodes.count {
|
||||||
for i in 1 ..< self.nodes.count {
|
for i in 1 ..< self.nodes.count {
|
||||||
|
|||||||
@ -349,7 +349,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
let maxBarHeight: CGFloat
|
let maxBarHeight: CGFloat
|
||||||
if !layout.safeInsets.top.isZero {
|
if !layout.safeInsets.top.isZero {
|
||||||
if let statusBarHeight = layout.statusBarHeight, statusBarHeight > 34.0 {
|
if let statusBarHeight = layout.statusBarHeight, statusBarHeight > 34.0 {
|
||||||
maxBarHeight = statusBarHeight + 34.0
|
maxBarHeight = statusBarHeight + 44.0
|
||||||
} else {
|
} else {
|
||||||
maxBarHeight = layout.safeInsets.top + 34.0
|
maxBarHeight = layout.safeInsets.top + 34.0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
func updateLayout(size: CGSize, minHeight: CGFloat, maxHeight: CGFloat, topInset: CGFloat, leftInset: CGFloat, rightInset: CGFloat, title: String?, pageProgress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let progressHeight: CGFloat
|
let progressHeight = size.height
|
||||||
if !topInset.isZero {
|
|
||||||
progressHeight = size.height - topInset + 11.0 - UIScreenPixel
|
|
||||||
} else {
|
|
||||||
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)))
|
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)
|
let transitionFactor = (size.height - minHeight) / (maxHeight - minHeight)
|
||||||
|
|||||||
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -109,7 +109,14 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
|||||||
(items, focusItem) = gallerySelectionItems(item: item, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail)
|
(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
|
model.stickersContext = paintStickersContext
|
||||||
controller.model = model
|
controller.model = model
|
||||||
model.controller = controller
|
model.controller = controller
|
||||||
|
|||||||
@ -596,6 +596,8 @@ NSString *suffix = @"";
|
|||||||
return @"iPhone 13 Mini";
|
return @"iPhone 13 Mini";
|
||||||
if ([platform isEqualToString:@"iPhone14,5"])
|
if ([platform isEqualToString:@"iPhone14,5"])
|
||||||
return @"iPhone 13";
|
return @"iPhone 13";
|
||||||
|
if ([platform isEqualToString:@"iPhone14,6"])
|
||||||
|
return @"iPhone SE (3rd gen)";
|
||||||
|
|
||||||
if ([platform hasPrefix:@"iPod1"])
|
if ([platform hasPrefix:@"iPod1"])
|
||||||
return @"iPod touch 1G";
|
return @"iPod touch 1G";
|
||||||
@ -728,6 +730,14 @@ NSString *suffix = @"";
|
|||||||
[platform isEqualToString:@"iPad13,11"])
|
[platform isEqualToString:@"iPad13,11"])
|
||||||
return @"iPad Pro 12.9 inch (5th gen)";
|
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"])
|
if ([platform hasPrefix:@"iPhone"])
|
||||||
return @"Unknown iPhone";
|
return @"Unknown iPhone";
|
||||||
if ([platform hasPrefix:@"iPod"])
|
if ([platform hasPrefix:@"iPod"])
|
||||||
|
|||||||
@ -401,6 +401,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
Queue.mainQueue().after(1.5, {
|
Queue.mainQueue().after(1.5, {
|
||||||
self.titleNode.setAttributedText(NSAttributedString(string: self.strings.EnterPasscode_EnterPasscode, font: titleFont, textColor: .white), animation: .crossFade)
|
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()
|
completion()
|
||||||
@ -471,6 +474,8 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
if layout.size.width == 320.0 || (isLandscape && keyboardHidden) {
|
if layout.size.width == 320.0 || (isLandscape && keyboardHidden) {
|
||||||
self.iconNode.alpha = 0.0
|
self.iconNode.alpha = 0.0
|
||||||
|
} else {
|
||||||
|
self.iconNode.alpha = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let passcodeLayout = PasscodeLayout(layout: layout, modalPresentation: self.modalPresentation)
|
let passcodeLayout = PasscodeLayout(layout: layout, modalPresentation: self.modalPresentation)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ enum PasscodeEntryTitleAnimation {
|
|||||||
|
|
||||||
final class PasscodeEntryLabelNode: ASDisplayNode {
|
final class PasscodeEntryLabelNode: ASDisplayNode {
|
||||||
private let wrapperNode: ASDisplayNode
|
private let wrapperNode: ASDisplayNode
|
||||||
private let textNode: ASTextNode
|
private let textNode: ImmediateTextNode
|
||||||
|
|
||||||
private var validLayout: CGSize?
|
private var validLayout: CGSize?
|
||||||
|
|
||||||
@ -19,10 +19,11 @@ final class PasscodeEntryLabelNode: ASDisplayNode {
|
|||||||
self.wrapperNode = ASDisplayNode()
|
self.wrapperNode = ASDisplayNode()
|
||||||
self.wrapperNode.clipsToBounds = true
|
self.wrapperNode.clipsToBounds = true
|
||||||
|
|
||||||
self.textNode = ASTextNode()
|
self.textNode = ImmediateTextNode()
|
||||||
self.textNode.isLayerBacked = false
|
self.textNode.isLayerBacked = false
|
||||||
self.textNode.textAlignment = .center
|
self.textNode.textAlignment = .center
|
||||||
self.textNode.displaysAsynchronously = false
|
self.textNode.displaysAsynchronously = false
|
||||||
|
self.textNode.maximumNumberOfLines = 2
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -56,9 +57,9 @@ final class PasscodeEntryLabelNode: ASDisplayNode {
|
|||||||
snapshotView.frame = self.textNode.frame
|
snapshotView.frame = self.textNode.frame
|
||||||
self.textNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.textNode.view)
|
self.textNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.textNode.view)
|
||||||
self.textNode.alpha = 0.0
|
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.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
snapshotView?.removeFromSuperview()
|
snapshotView?.removeFromSuperview()
|
||||||
self.textNode.attributedText = text
|
|
||||||
self.textNode.alpha = 1.0
|
self.textNode.alpha = 1.0
|
||||||
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { _ in
|
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, completion: { _ in
|
||||||
completion()
|
completion()
|
||||||
@ -81,7 +82,7 @@ final class PasscodeEntryLabelNode: ASDisplayNode {
|
|||||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||||
self.validLayout = size
|
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)
|
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.wrapperNode, frame: textFrame)
|
||||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(), size: textSize))
|
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(), size: textSize))
|
||||||
|
|||||||
@ -702,6 +702,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let longPressDuration: Double = 1.5
|
||||||
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
|
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
|
||||||
switch recognizer.state {
|
switch recognizer.state {
|
||||||
case .began:
|
case .began:
|
||||||
@ -709,7 +710,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if let itemNode = self.reactionItemNode(at: point) {
|
if let itemNode = self.reactionItemNode(at: point) {
|
||||||
self.highlightedReaction = itemNode.item.reaction
|
self.highlightedReaction = itemNode.item.reaction
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
self.continuousHaptic = try? ContinuousHaptic(duration: 2.5)
|
self.continuousHaptic = try? ContinuousHaptic(duration: longPressDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.hapticFeedback == nil {
|
if self.hapticFeedback == nil {
|
||||||
@ -717,11 +718,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
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?.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 {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,16 +138,17 @@ private struct ShareSearchGridTransaction {
|
|||||||
let insertions: [GridNodeInsertItem]
|
let insertions: [GridNodeInsertItem]
|
||||||
let updates: [GridNodeUpdateItem]
|
let updates: [GridNodeUpdateItem]
|
||||||
let animated: Bool
|
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 (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||||
|
|
||||||
let deletions = deleteIndices
|
let deletions = deleteIndices
|
||||||
let insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interfaceInteraction: interfaceInteraction), previousIndex: $0.2) }
|
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)) }
|
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 {
|
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 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)) }
|
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 {
|
final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||||
@ -236,8 +237,8 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
|||||||
|
|
||||||
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
||||||
|
|
||||||
let foundItems = searchQuery.get()
|
let foundItems = self.searchQuery.get()
|
||||||
|> mapToSignal { query -> Signal<[ShareSearchPeerEntry]?, NoError> in
|
|> mapToSignal { query -> Signal<([ShareSearchPeerEntry]?, Bool), NoError> in
|
||||||
if !query.isEmpty {
|
if !query.isEmpty {
|
||||||
let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1)
|
let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1)
|
||||||
let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased())
|
let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased())
|
||||||
@ -251,7 +252,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return combineLatest(accountPeer, foundLocalPeers, foundRemotePeers)
|
return combineLatest(accountPeer, foundLocalPeers, foundRemotePeers)
|
||||||
|> map { accountPeer, foundLocalPeers, foundRemotePeers -> [ShareSearchPeerEntry]? in
|
|> map { accountPeer, foundLocalPeers, foundRemotePeers -> ([ShareSearchPeerEntry]?, Bool) in
|
||||||
var entries: [ShareSearchPeerEntry] = []
|
var entries: [ShareSearchPeerEntry] = []
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
|
|
||||||
@ -276,7 +277,9 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPlaceholder = false
|
||||||
if foundRemotePeers.2 {
|
if foundRemotePeers.2 {
|
||||||
|
isPlaceholder = true
|
||||||
for _ in 0 ..< 4 {
|
for _ in 0 ..< 4 {
|
||||||
entries.append(ShareSearchPeerEntry(index: index, peer: nil, presence: nil, theme: theme, strings: strings))
|
entries.append(ShareSearchPeerEntry(index: index, peer: nil, presence: nil, theme: theme, strings: strings))
|
||||||
index += 1
|
index += 1
|
||||||
@ -301,26 +304,29 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return (entries, isPlaceholder)
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
self.searchDisposable.set((foundItems
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] entries in
|
|> deliverOnMainQueue).start(next: { [weak self] entriesAndIsPlaceholder in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let previousEntries = previousSearchItems.swap(entries)
|
let (entries, isPlaceholder) = entriesAndIsPlaceholder
|
||||||
|
let previousEntries = previousSearchItemsAndIsPlaceholder.swap(entriesAndIsPlaceholder)
|
||||||
strongSelf.entries = entries ?? []
|
strongSelf.entries = entries ?? []
|
||||||
|
|
||||||
let firstTime = previousEntries == nil
|
let firstTime = previousEntries.0 == nil
|
||||||
let transition = preparedGridEntryTransition(context: context, from: previousEntries ?? [], to: entries ?? [], interfaceInteraction: controllerInteraction)
|
let crossFade = !firstTime && previousEntries.1 && !isPlaceholder
|
||||||
|
|
||||||
|
let transition = preparedGridEntryTransition(context: context, from: previousEntries.0 ?? [], to: entries ?? [], interfaceInteraction: controllerInteraction, crossFade: crossFade)
|
||||||
strongSelf.enqueueTransition(transition, firstTime: firstTime)
|
strongSelf.enqueueTransition(transition, firstTime: firstTime)
|
||||||
|
|
||||||
if (previousEntries == nil) != (entries == nil) {
|
if (previousEntries.0 == nil) != (entries == nil) {
|
||||||
if previousEntries == nil {
|
if previousEntries.0 == nil {
|
||||||
strongSelf.recentGridNode.isHidden = true
|
strongSelf.recentGridNode.isHidden = true
|
||||||
strongSelf.contentGridNode.isHidden = false
|
strongSelf.contentGridNode.isHidden = false
|
||||||
strongSelf.transitionToContentGridLayout()
|
strongSelf.transitionToContentGridLayout()
|
||||||
@ -589,6 +595,18 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
|||||||
if transition.animated {
|
if transition.animated {
|
||||||
itemTransition = .animated(duration: 0.3, curve: .spring)
|
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 })
|
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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -240,7 +240,12 @@ private final class TranslateScreenComponent: CombinedComponent {
|
|||||||
let itemSpacing: CGFloat = 16.0
|
let itemSpacing: CGFloat = 16.0
|
||||||
let itemHeight: CGFloat = 44.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
|
let fromLanguage: String
|
||||||
if let languageCode = state.fromLanguage {
|
if let languageCode = state.fromLanguage {
|
||||||
fromLanguage = locale.localizedString(forLanguageCode: languageCode) ?? ""
|
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) {
|
public convenience init(context: AccountContext, text: String, fromLanguage: String?, toLanguage: String? = nil, isExpanded: Bool = false) {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
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 {
|
if toLanguage == fromLanguage {
|
||||||
toLanguage = "en"
|
toLanguage = "en"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user