Attachment menu improvements

This commit is contained in:
Ilya Laktyushin 2022-03-04 17:19:34 +04:00
parent 43cb778ef5
commit f0e55a0e0a
13 changed files with 152 additions and 53 deletions

View File

@ -8,7 +8,7 @@ import DirectionalPanGesture
import TelegramPresentationData import TelegramPresentationData
import MapKit import MapKit
private let overflowInset: CGFloat = 70.0 private let overflowInset: CGFloat = 0.0
final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
let wrappingNode: ASDisplayNode let wrappingNode: ASDisplayNode
@ -406,7 +406,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
intrinsicInsets.left += overflowInset intrinsicInsets.left += overflowInset
intrinsicInsets.right += overflowInset intrinsicInsets.right += overflowInset
containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width + overflowInset * 2.0, height: layout.size.height - containerTopInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: intrinsicInsets.left, bottom: layout.intrinsicInsets.bottom, right: intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: safeInsets.left, bottom: safeInsets.bottom, right: safeInsets.right), additionalInsets: layout.additionalInsets, statusBarHeight: effectiveStatusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver) containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width + overflowInset * 2.0, height: layout.size.height - containerTopInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: intrinsicInsets.left, bottom: intrinsicInsets.bottom, right: intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: safeInsets.left, bottom: safeInsets.bottom, right: safeInsets.right), additionalInsets: layout.additionalInsets, statusBarHeight: effectiveStatusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
let unscaledFrame = CGRect(origin: CGPoint(x: 0.0, y: containerTopInset - coveredByModalTransition * 10.0), size: containerLayout.size) let unscaledFrame = CGRect(origin: CGPoint(x: 0.0, y: containerTopInset - coveredByModalTransition * 10.0), size: containerLayout.size)
let maxScale: CGFloat = (containerLayout.size.width - 16.0 * 2.0) / containerLayout.size.width let maxScale: CGFloat = (containerLayout.size.width - 16.0 * 2.0) / containerLayout.size.width
containerScale = 1.0 * (1.0 - coveredByModalTransition) + maxScale * coveredByModalTransition containerScale = 1.0 * (1.0 - coveredByModalTransition) + maxScale * coveredByModalTransition
@ -417,7 +417,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
clipFrame = CGRect(x: containerFrame.minX + overflowInset, y: containerFrame.minY, width: containerFrame.width - overflowInset * 2.0, height: containerFrame.height) clipFrame = CGRect(x: containerFrame.minX + overflowInset, y: containerFrame.minY, width: containerFrame.width - overflowInset * 2.0, height: containerFrame.height)
} }
} else { } else {
containerLayout = ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: layout.inVoiceOver) containerLayout = ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: layout.inVoiceOver)
let unscaledFrame = CGRect(origin: CGPoint(), size: containerLayout.size) let unscaledFrame = CGRect(origin: CGPoint(), size: containerLayout.size)
containerScale = 1.0 containerScale = 1.0

View File

@ -157,6 +157,7 @@ public class AttachmentController: ViewController {
self.dim.backgroundColor = UIColor(white: 0.0, alpha: 0.25) self.dim.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
self.shadowNode = ASImageNode() self.shadowNode = ASImageNode()
self.shadowNode.isUserInteractionEnabled = false
self.wrapperNode = ASDisplayNode() self.wrapperNode = ASDisplayNode()
self.wrapperNode.clipsToBounds = true self.wrapperNode.clipsToBounds = true
@ -200,7 +201,9 @@ public class AttachmentController: ViewController {
self.panel.selectionChanged = { [weak self] type, ascending in self.panel.selectionChanged = { [weak self] type, ascending in
if let strongSelf = self { if let strongSelf = self {
strongSelf.switchToController(type, ascending) return strongSelf.switchToController(type, ascending)
} else {
return false
} }
} }
@ -258,7 +261,7 @@ public class AttachmentController: ViewController {
self.dim.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.dim.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:))))
self.switchToController(.gallery, false) let _ = self.switchToController(.gallery, false)
} }
private func updateSelectionCount(_ count: Int) { private func updateSelectionCount(_ count: Int) {
@ -274,16 +277,16 @@ public class AttachmentController: ViewController {
} }
} }
func switchToController(_ type: AttachmentButtonType, _ ascending: Bool) { func switchToController(_ type: AttachmentButtonType, _ ascending: Bool) -> Bool {
guard !self.animating else {
return false
}
guard self.currentType != type else { guard self.currentType != type else {
if self.animating {
return
}
if let controller = self.currentControllers.last { if let controller = self.currentControllers.last {
controller.scrollToTopWithTabBar?() controller.scrollToTopWithTabBar?()
controller.requestAttachmentMenuExpansion() controller.requestAttachmentMenuExpansion()
} }
return return true
} }
let previousType = self.currentType let previousType = self.currentType
self.currentType = type self.currentType = type
@ -317,28 +320,10 @@ public class AttachmentController: ViewController {
} }
} }
let previousController = strongSelf.currentControllers.last let previousController = strongSelf.currentControllers.last
let animateTransition = previousType != nil
strongSelf.currentControllers = [controller] strongSelf.currentControllers = [controller]
if animateTransition, let snapshotView = strongSelf.container.container.view.snapshotView(afterScreenUpdates: false) { if previousType != nil {
snapshotView.frame = strongSelf.container.container.frame strongSelf.animateSwitchTransition(controller, previousController: previousController)
strongSelf.container.clipNode.view.addSubview(snapshotView)
let _ = (controller.ready.get()
|> filter {
$0
}
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self, weak snapshotView] _ in
guard let strongSelf = self else {
return
}
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: ascending ? 70.0 : -70.0, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
snapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
previousController?.resetForReuse()
})
})
} }
if let layout = strongSelf.validLayout { if let layout = strongSelf.validLayout {
@ -350,6 +335,46 @@ public class AttachmentController: ViewController {
strongSelf.mediaPickerContext = mediaPickerContext strongSelf.mediaPickerContext = mediaPickerContext
} }
}) })
return true
}
private func animateSwitchTransition(_ controller: AttachmentContainable, previousController: AttachmentContainable?) {
guard let snapshotView = self.container.container.view.snapshotView(afterScreenUpdates: false) else {
return
}
snapshotView.frame = self.container.container.frame
self.container.clipNode.view.addSubview(snapshotView)
self.animating = true
let _ = (controller.ready.get()
|> filter {
$0
}
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self, weak snapshotView] _ in
guard let strongSelf = self, let layout = strongSelf.validLayout else {
return
}
if case .compact = layout.metrics.widthClass {
let offset = strongSelf.container.isExpanded ? 10.0 : 24.0
strongSelf.container.clipNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -offset), duration: 0.18, removeOnCompletion: false, additive: true, completion: { [weak self] _ in
if let strongSelf = self {
strongSelf.container.clipNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 0.0, y: 0.0)), to: NSValue(cgPoint: CGPoint(x: 0.0, y: offset)), keyPath: "position", duration: 0.55, delay: 0.0, initialVelocity: 0.0, damping: 70.0, removeOnCompletion: false, additive: true, completion: { [weak self] _ in
self?.container.clipNode.layer.removeAllAnimations()
self?.animating = false
})
}
})
}
snapshotView?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
previousController?.resetForReuse()
})
})
} }
private var animating = false private var animating = false

View File

@ -174,7 +174,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
private var validLayout: ContainerViewLayout? private var validLayout: ContainerViewLayout?
private var scrollLayout: (width: CGFloat, contentSize: CGSize)? private var scrollLayout: (width: CGFloat, contentSize: CGSize)?
var selectionChanged: (AttachmentButtonType, Bool) -> Void = { _, _ in } var selectionChanged: (AttachmentButtonType, Bool) -> Bool = { _, _ in return false }
var beganTextEditing: () -> Void = {} var beganTextEditing: () -> Void = {}
var textUpdated: (NSAttributedString) -> Void = { _ in } var textUpdated: (NSAttributedString) -> Void = { _ in }
var sendMessagePressed: (AttachmentTextInputPanelSendMode) -> Void = { _ in } var sendMessagePressed: (AttachmentTextInputPanelSendMode) -> Void = { _ in }
@ -481,9 +481,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
action: { [weak self] in action: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let ascending = i > strongSelf.selectedIndex let ascending = i > strongSelf.selectedIndex
strongSelf.selectedIndex = i if strongSelf.selectionChanged(type, ascending) {
strongSelf.selectionChanged(type, ascending) strongSelf.selectedIndex = i
strongSelf.updateViews(transition: .init(animation: .curve(duration: 0.2, curve: .spring))) strongSelf.updateViews(transition: .init(animation: .curve(duration: 0.2, curve: .spring)))
}
} }
}) })
), ),

View File

@ -208,7 +208,7 @@ private struct WrappedGridItemNode: Hashable {
} }
open class GridNode: GridNodeScroller, UIScrollViewDelegate { open class GridNode: GridNodeScroller, UIScrollViewDelegate {
private var gridLayout = GridNodeLayout(size: CGSize(), insets: UIEdgeInsets(), preloadSize: 0.0, type: .fixed(itemSize: CGSize(), fillWidth: nil, lineSpacing: 0.0, itemSpacing: nil)) public private(set) var gridLayout = GridNodeLayout(size: CGSize(), insets: UIEdgeInsets(), preloadSize: 0.0, type: .fixed(itemSize: CGSize(), fillWidth: nil, lineSpacing: 0.0, itemSpacing: nil))
private var firstIndexInSectionOffset: Int = 0 private var firstIndexInSectionOffset: Int = 0
public private(set) var items: [GridItem] = [] public private(set) var items: [GridItem] = []
private var itemNodes: [Int: GridItemNode] = [:] private var itemNodes: [Int: GridItemNode] = [:]

View File

@ -112,7 +112,7 @@ final class NavigationModalFrame: ASDisplayNode {
let cornerRadius: CGFloat = 9.0 let cornerRadius: CGFloat = 9.0
let initialCornerRadius: CGFloat let initialCornerRadius: CGFloat
if !layout.safeInsets.top.isZero { if !layout.safeInsets.top.isZero {
initialCornerRadius = 40.0 initialCornerRadius = layout.deviceMetrics.screenCornerRadius
} else { } else {
initialCornerRadius = 0.0 initialCornerRadius = 0.0
} }

View File

@ -45,6 +45,12 @@
- (NSOrderedSet *)selectedItemsIdentifiers; - (NSOrderedSet *)selectedItemsIdentifiers;
- (NSArray *)selectedItems; - (NSArray *)selectedItems;
- (void)saveState;
- (void)restoreState;
- (void)clearSavedState;
- (NSUInteger)savedStateDifference;
- (NSUInteger)count; - (NSUInteger)count;
+ (SSignal *)combinedSelectionChangedSignalForContexts:(NSArray *)contexts; + (SSignal *)combinedSelectionChangedSignalForContexts:(NSArray *)contexts;

View File

@ -9,6 +9,8 @@
@interface TGMediaSelectionContext () @interface TGMediaSelectionContext ()
{ {
NSMutableArray *_savedSelectedIdentifiers;
NSMutableArray *_selectedIdentifiers; NSMutableArray *_selectedIdentifiers;
NSMutableDictionary *_selectionMap; NSMutableDictionary *_selectionMap;
@ -74,9 +76,6 @@
NSString *identifier = item.uniqueIdentifier; NSString *identifier = item.uniqueIdentifier;
if (selected) if (selected)
{ {
if (_selectionMap[identifier] != nil)
return false;
if (_selectedIdentifiers.count >= _selectionLimit) { if (_selectedIdentifiers.count >= _selectionLimit) {
if (_selectionLimitExceeded) { if (_selectionLimitExceeded) {
_selectionLimitExceeded(); _selectionLimitExceeded();
@ -92,7 +91,6 @@
if (_selectionMap[identifier] == nil) if (_selectionMap[identifier] == nil)
return false; return false;
[_selectionMap removeObjectForKey:identifier];
[_selectedIdentifiers removeObject:identifier]; [_selectedIdentifiers removeObject:identifier];
} }
@ -186,9 +184,13 @@
if (enumerationBlock == nil) if (enumerationBlock == nil)
return; return;
NSArray *items = [_selectionMap allValues]; for (NSArray *identifier in _selectedIdentifiers)
for (id<TGMediaSelectableItem> item in items) {
enumerationBlock(item); NSObject<TGMediaSelectableItem> *item = _selectionMap[identifier];
if (item != nil) {
enumerationBlock(item);
}
}
} }
- (NSOrderedSet *)selectedItemsIdentifiers - (NSOrderedSet *)selectedItemsIdentifiers
@ -213,6 +215,31 @@
return _selectedIdentifiers.count; return _selectedIdentifiers.count;
} }
- (void)saveState {
if (_savedSelectedIdentifiers == nil) {
_savedSelectedIdentifiers = [_selectedIdentifiers mutableCopy];
}
}
- (void)restoreState {
_selectedIdentifiers = _savedSelectedIdentifiers;
_savedSelectedIdentifiers = nil;
_pipe.sink([TGMediaSelectionChange changeWithItem:nil selected:false animated:false sender:nil]);
}
- (void)clearSavedState {
_savedSelectedIdentifiers = nil;
}
- (NSUInteger)savedStateDifference {
if (_savedSelectedIdentifiers != nil) {
return _savedSelectedIdentifiers.count - _selectedIdentifiers.count;
} else {
return 0;
}
}
#pragma mark - #pragma mark -
- (void)setItemSourceUpdatedSignal:(SSignal *)signal - (void)setItemSourceUpdatedSignal:(SSignal *)signal

View File

@ -38,6 +38,8 @@ swift_library(
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode", "//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
"//submodules/WebSearchUI:WebSearchUI", "//submodules/WebSearchUI:WebSearchUI",
"//submodules/ChatMessageBackground:ChatMessageBackground", "//submodules/ChatMessageBackground:ChatMessageBackground",
"//submodules/SparseItemGrid:SparseItemGrid",
"//submodules/UndoUI:UndoUI",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -119,7 +119,7 @@ final class MediaPickerMoreButtonNode: ASDisplayNode {
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize { override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
let animationSize = CGSize(width: 30.0, height: 30.0) let animationSize = CGSize(width: 30.0, height: 30.0)
let inset: CGFloat = 0.0 let inset: CGFloat = 0.0
self.iconNode.frame = CGRect(origin: CGPoint(x: inset + 4.0, y: floor((constrainedSize.height - animationSize.height) / 2.0)), size: animationSize) self.iconNode.frame = CGRect(origin: CGPoint(x: inset + 6.0, y: floor((constrainedSize.height - animationSize.height) / 2.0) + 1.0), size: animationSize)
let size = CGSize(width: animationSize.width + inset * 2.0, height: constrainedSize.height) let size = CGSize(width: animationSize.width + inset * 2.0, height: constrainedSize.height)
let bounds = CGRect(origin: CGPoint(), size: size) let bounds = CGRect(origin: CGPoint(), size: size)

View File

@ -753,6 +753,8 @@ final class SparseItemGridScrollingIndicatorComponent: CombinedComponent {
let textYear = Child(RollingText.self) let textYear = Child(RollingText.self)
return { context in return { context in
context.view.clipsToBounds = true
let date = context.component.date let date = context.component.date
let components = date.0.components(separatedBy: " ") let components = date.0.components(separatedBy: " ")
@ -1099,7 +1101,7 @@ public final class SparseItemGridScrollingArea: ASDisplayNode {
self.updateLineIndicator(transition: transition) self.updateLineIndicator(transition: transition)
} }
func feedbackTap() { public func feedbackTap() {
self.hapticFeedback.tap() self.hapticFeedback.tap()
} }

View File

@ -10353,7 +10353,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let inputText = self.presentationInterfaceState.interfaceState.effectiveInputState.inputText let inputText = self.presentationInterfaceState.interfaceState.effectiveInputState.inputText
let currentMediaController = Atomic<AttachmentContainable?>(value: nil) let currentMediaController = Atomic<MediaPickerScreen?>(value: nil)
let currentFilesController = Atomic<AttachmentContainable?>(value: nil) let currentFilesController = Atomic<AttachmentContainable?>(value: nil)
let currentLocationController = Atomic<AttachmentContainable?>(value: nil) let currentLocationController = Atomic<AttachmentContainable?>(value: nil)
@ -10367,7 +10367,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.controllerNavigationDisposable.set(nil) strongSelf.controllerNavigationDisposable.set(nil)
let existingController = currentMediaController.with { $0 } let existingController = currentMediaController.with { $0 }
if let controller = existingController { if let controller = existingController {
completion(controller, nil) completion(controller, controller.mediaPickerContext)
controller.prepareForReuse() controller.prepareForReuse()
return return
} }
@ -11023,7 +11023,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.present(actionSheet, in: .window(.root)) self.present(actionSheet, in: .window(.root))
} }
private func presentMediaPicker(bannedSendMedia: (Int32, Bool)?, present: @escaping (AttachmentContainable, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?) -> Void) { private func presentMediaPicker(bannedSendMedia: (Int32, Bool)?, present: @escaping (MediaPickerScreen, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?) -> Void) {
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else { guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return return
} }

View File

@ -49,7 +49,11 @@ public enum UndoOverlayAction {
public final class UndoOverlayController: ViewController { public final class UndoOverlayController: ViewController {
private let presentationData: PresentationData private let presentationData: PresentationData
public let content: UndoOverlayContent public var content: UndoOverlayContent {
didSet {
(self.displayNode as! UndoOverlayControllerNode).updateContent(self.content)
}
}
private let elevatedLayout: Bool private let elevatedLayout: Bool
private let animateInAsReplacement: Bool private let animateInAsReplacement: Bool
private var action: (UndoOverlayAction) -> Bool private var action: (UndoOverlayAction) -> Bool

View File

@ -24,6 +24,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
private let timerTextNode: ImmediateTextNode private let timerTextNode: ImmediateTextNode
private let avatarNode: AvatarNode? private let avatarNode: AvatarNode?
private let iconNode: ASImageNode? private let iconNode: ASImageNode?
private var iconImageSize: CGSize?
private let iconCheckNode: RadialStatusNode? private let iconCheckNode: RadialStatusNode?
private let animationNode: AnimationNode? private let animationNode: AnimationNode?
private var animatedStickerNode: AnimatedStickerNode? private var animatedStickerNode: AnimatedStickerNode?
@ -41,7 +42,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
private let action: (UndoOverlayAction) -> Bool private let action: (UndoOverlayAction) -> Bool
private let dismiss: () -> Void private let dismiss: () -> Void
private let content: UndoOverlayContent private var content: UndoOverlayContent
private let effectView: UIView private let effectView: UIView
@ -752,7 +753,11 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
case let .image(image, text): case let .image(image, text):
self.avatarNode = nil self.avatarNode = nil
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
self.iconNode?.clipsToBounds = true
self.iconNode?.contentMode = .scaleAspectFill
self.iconNode?.image = image self.iconNode?.image = image
self.iconNode?.cornerRadius = 4.0
self.iconImageSize = CGSize(width: 32.0, height: 32.0)
self.iconCheckNode = nil self.iconCheckNode = nil
self.animationNode = nil self.animationNode = nil
self.animatedStickerNode = nil self.animatedStickerNode = nil
@ -892,6 +897,24 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.checkTimer() self.checkTimer()
} }
func updateContent(_ content: UndoOverlayContent) {
self.content = content
switch content {
case let .image(image, text):
self.iconNode?.image = image
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white)
default:
break
}
self.renewWithCurrentContent()
if let validLayout = self.validLayout {
self.containerLayoutUpdated(layout: validLayout, transition: .immediate)
}
}
func containerLayoutUpdated(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { func containerLayoutUpdated(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
let firstLayout = self.validLayout == nil let firstLayout = self.validLayout == nil
self.validLayout = layout self.validLayout = layout
@ -979,7 +1002,16 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset, y: textContentOrigin), size: titleSize)) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset, y: textContentOrigin), size: titleSize))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: leftInset, y: textContentOrigin + textOffset), size: textSize)) transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: leftInset, y: textContentOrigin + textOffset), size: textSize))
if let iconNode = self.iconNode, let iconSize = iconNode.image?.size { if let iconNode = self.iconNode {
let iconSize: CGSize
if let size = self.iconImageSize {
iconSize = size
} else if let size = iconNode.image?.size {
iconSize = size
} else {
iconSize = CGSize()
}
let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0) + verticalOffset), size: iconSize) let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0) + verticalOffset), size: iconSize)
transition.updateFrame(node: iconNode, frame: iconFrame) transition.updateFrame(node: iconNode, frame: iconFrame)