mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Attachment menu improvements
This commit is contained in:
parent
43cb778ef5
commit
f0e55a0e0a
@ -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
|
||||||
|
@ -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.currentType != type else {
|
guard !self.animating else {
|
||||||
if self.animating {
|
return false
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
guard self.currentType != type else {
|
||||||
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
|
||||||
|
@ -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,10 +481,11 @@ 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
|
||||||
|
if strongSelf.selectionChanged(type, ascending) {
|
||||||
strongSelf.selectedIndex = i
|
strongSelf.selectedIndex = i
|
||||||
strongSelf.selectionChanged(type, ascending)
|
|
||||||
strongSelf.updateViews(transition: .init(animation: .curve(duration: 0.2, curve: .spring)))
|
strongSelf.updateViews(transition: .init(animation: .curve(duration: 0.2, curve: .spring)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
environment: {},
|
environment: {},
|
||||||
|
@ -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] = [:]
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
{
|
||||||
|
NSObject<TGMediaSelectableItem> *item = _selectionMap[identifier];
|
||||||
|
if (item != nil) {
|
||||||
enumerationBlock(item);
|
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
|
||||||
|
@ -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",
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user