Attachment menu improvements

This commit is contained in:
Ilya Laktyushin 2022-02-22 07:04:41 +03:00
parent e70f17ff2d
commit 59595cb027
9 changed files with 62 additions and 34 deletions

View File

@ -6,6 +6,7 @@ import UIKitRuntimeUtils
import Display import Display
import DirectionalPanGesture import DirectionalPanGesture
import TelegramPresentationData import TelegramPresentationData
import MapKit
final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
let wrappingNode: ASDisplayNode let wrappingNode: ASDisplayNode
@ -86,6 +87,9 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer { if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer {
if let _ = otherGestureRecognizer.view?.superview as? MKMapView {
return false
}
return true return true
} }
return false return false
@ -116,6 +120,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
case .began: case .began:
let point = recognizer.location(in: self.view) let point = recognizer.location(in: self.view)
let currentHitView = self.hitTest(point, with: nil) let currentHitView = self.hitTest(point, with: nil)
let scrollViewAndListNode = self.findScrollView(view: currentHitView) let scrollViewAndListNode = self.findScrollView(view: currentHitView)
let scrollView = scrollViewAndListNode?.0 let scrollView = scrollViewAndListNode?.0
let listNode = scrollViewAndListNode?.1 let listNode = scrollViewAndListNode?.1
@ -183,12 +188,14 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
let translation = recognizer.translation(in: self.view).y let translation = recognizer.translation(in: self.view).y
var velocity = recognizer.velocity(in: self.view) var velocity = recognizer.velocity(in: self.view)
if case let .known(value) = visibleContentOffset, value > 0.0 { if self.isExpanded {
velocity = CGPoint() if case let .known(value) = visibleContentOffset, value > 0.1 {
} else if case .unknown = visibleContentOffset { velocity = CGPoint()
velocity = CGPoint() } else if case .unknown = visibleContentOffset {
} else if contentOffset > 0.0 { velocity = CGPoint()
velocity = CGPoint() } else if contentOffset > 0.1 {
velocity = CGPoint()
}
} }
var bounds = self.bounds var bounds = self.bounds
@ -226,7 +233,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
self.interactivelyDismissed?() self.interactivelyDismissed?()
dismissing = true dismissing = true
} else if (velocity.y < -300.0 || offset < topInset / 2.0) { } else if (velocity.y < -300.0 || offset < topInset / 2.0) {
if velocity.y > -2200.0, let listNode = listNode { if velocity.y > -2200.0 && velocity.y < -300.0, let listNode = listNode {
DispatchQueue.main.async { DispatchQueue.main.async {
listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} }

View File

@ -166,9 +166,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
private var interfaceInteraction: ChatPanelInterfaceInteraction? private var interfaceInteraction: ChatPanelInterfaceInteraction?
private let containerNode: ASDisplayNode private let containerNode: ASDisplayNode
private var effectView: UIVisualEffectView? private let backgroundNode: NavigationBackgroundNode
private let scrollNode: ASScrollNode private let scrollNode: ASScrollNode
private let backgroundNode: ASDisplayNode
private let separatorNode: ASDisplayNode private let separatorNode: ASDisplayNode
private var buttonViews: [Int: ComponentHostView<Empty>] = [:] private var buttonViews: [Int: ComponentHostView<Empty>] = [:]
@ -200,11 +199,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
self.containerNode.clipsToBounds = true self.containerNode.clipsToBounds = true
self.scrollNode = ASScrollNode() self.scrollNode = ASScrollNode()
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = self.presentationData.theme.actionSheet.itemBackgroundColor
self.backgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.tabBar.backgroundColor)
self.separatorNode = ASDisplayNode() self.separatorNode = ASDisplayNode()
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor self.separatorNode.backgroundColor = self.presentationData.theme.rootController.tabBar.separatorColor
super.init() super.init()
@ -385,8 +383,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
if let strongSelf = self { if let strongSelf = self {
strongSelf.presentationData = presentationData strongSelf.presentationData = presentationData
strongSelf.backgroundNode.backgroundColor = presentationData.theme.actionSheet.itemBackgroundColor strongSelf.backgroundNode.updateColor(color: presentationData.theme.rootController.tabBar.backgroundColor, transition: .immediate)
strongSelf.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor strongSelf.separatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor
strongSelf.updateChatPresentationInterfaceState({ $0.updatedTheme(presentationData.theme) }) strongSelf.updateChatPresentationInterfaceState({ $0.updatedTheme(presentationData.theme) })
@ -410,18 +408,6 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
self.scrollNode.view.delegate = self self.scrollNode.view.delegate = self
self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false
self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsVerticalScrollIndicator = false
let effect: UIVisualEffect
switch self.presentationData.theme.actionSheet.backgroundType {
case .light:
effect = UIBlurEffect(style: .light)
case .dark:
effect = UIBlurEffect(style: .dark)
}
let effectView = UIVisualEffectView(effect: effect)
effectView.frame = self.containerNode.bounds
self.effectView = effectView
self.containerNode.view.insertSubview(effectView, at: 0)
} }
func updateCaption(_ caption: NSAttributedString) { func updateCaption(_ caption: NSAttributedString) {
@ -647,10 +633,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
containerTransition.updateFrame(node: self.containerNode, frame: containerFrame) containerTransition.updateFrame(node: self.containerNode, frame: containerFrame)
containerTransition.updateFrame(node: self.backgroundNode, frame: containerBounds) containerTransition.updateFrame(node: self.backgroundNode, frame: containerBounds)
self.backgroundNode.update(size: containerBounds.size, transition: transition)
containerTransition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: UIScreenPixel))) containerTransition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: UIScreenPixel)))
if let effectView = self.effectView {
containerTransition.updateFrame(view: effectView, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: containerFrame.height + 44.0)))
}
let _ = self.updateScrollLayoutIfNeeded(force: isCollapsedUpdated || isSelectingUpdated, transition: containerTransition) let _ = self.updateScrollLayoutIfNeeded(force: isCollapsedUpdated || isSelectingUpdated, transition: containerTransition)

View File

@ -792,6 +792,12 @@ public func createPollController(context: AccountContext, updatedPresentationDat
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.Limits()) context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.Limits())
) )
|> map { presentationData, state, limitsConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, state, limitsConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in
var presentationData = presentationData
if presentationData.theme.list.blocksBackgroundColor.rgb == 0x000000 {
let updatedTheme = presentationData.theme.withInvertedBlocksBackground()
presentationData = presentationData.withUpdated(theme: updatedTheme)
}
var enabled = true var enabled = true
if processPollText(state.text).isEmpty { if processPollText(state.text).isEmpty {
enabled = false enabled = false

View File

@ -1456,7 +1456,8 @@ open class NavigationBar: ASDisplayNode {
return nil return nil
} }
if result == self.view || result == self.buttonsContainerNode.view { //result == self.view ||
if result == self.buttonsContainerNode.view {
return nil return nil
} }

View File

@ -293,6 +293,9 @@ public final class LocationPickerController: ViewController, AttachmentContainab
self.displayNode = LocationPickerControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, interaction: interaction, locationManager: self.locationManager) self.displayNode = LocationPickerControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, interaction: interaction, locationManager: self.locationManager)
self.displayNodeDidLoad() self.displayNodeDidLoad()
self.controllerNode.beganInteractiveDragging = { [weak self] in
self?.requestAttachmentMenuExpansion()
}
self.permissionDisposable = (DeviceAccess.authorizationStatus(subject: .location(.send)) self.permissionDisposable = (DeviceAccess.authorizationStatus(subject: .location(.send))
|> deliverOnMainQueue).start(next: { [weak self] next in |> deliverOnMainQueue).start(next: { [weak self] next in

View File

@ -269,6 +269,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)? private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
private var listOffset: CGFloat? private var listOffset: CGFloat?
var beganInteractiveDragging: () -> Void = {}
init(context: AccountContext, presentationData: PresentationData, mode: LocationPickerMode, interaction: LocationPickerInteraction, locationManager: LocationManager) { init(context: AccountContext, presentationData: PresentationData, mode: LocationPickerMode, interaction: LocationPickerInteraction, locationManager: LocationManager) {
self.context = context self.context = context
self.presentationData = presentationData self.presentationData = presentationData
@ -654,6 +656,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
strongSelf.beganInteractiveDragging()
strongSelf.updateState { state in strongSelf.updateState { state in
var state = state var state = state
state.displayingMapModeOptions = false state.displayingMapModeOptions = false

View File

@ -398,7 +398,9 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
guard let controller = self.controller, let interaction = self.interaction, let (layout, _) = self.validLayout else { guard let controller = self.controller, let interaction = self.interaction, let (layout, _) = self.validLayout else {
return return
} }
self.dismissInput() Queue.mainQueue().justDispatch {
self.dismissInput()
}
let index = fetchResult.count - index - 1 let index = fetchResult.count - index - 1
presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: true, updateHiddenMedia: { [weak self] id in presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: true, updateHiddenMedia: { [weak self] id in
@ -420,7 +422,9 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
guard let controller = self.controller, let interaction = self.interaction, let (layout, _) = self.validLayout else { guard let controller = self.controller, let interaction = self.interaction, let (layout, _) = self.validLayout else {
return return
} }
self.dismissInput() Queue.mainQueue().justDispatch {
self.dismissInput()
}
presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: true, updateHiddenMedia: { [weak self] id in presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: true, updateHiddenMedia: { [weak self] id in
self?.hiddenMediaId.set(.single(id)) self?.hiddenMediaId.set(.single(id))

View File

@ -1478,4 +1478,10 @@ public final class PresentationTheme: Equatable {
public func withUpdated(preview: Bool) -> PresentationTheme { public func withUpdated(preview: Bool) -> PresentationTheme {
return PresentationTheme(name: self.name, index: self.index, referenceTheme: self.referenceTheme, overallDarkAppearance: self.overallDarkAppearance, intro: self.intro, passcode: self.passcode, rootController: self.rootController, list: self.list, chatList: self.chatList, chat: self.chat, actionSheet: self.actionSheet, contextMenu: self.contextMenu, inAppNotification: self.inAppNotification, chart: self.chart, preview: preview) return PresentationTheme(name: self.name, index: self.index, referenceTheme: self.referenceTheme, overallDarkAppearance: self.overallDarkAppearance, intro: self.intro, passcode: self.passcode, rootController: self.rootController, list: self.list, chatList: self.chatList, chat: self.chat, actionSheet: self.actionSheet, contextMenu: self.contextMenu, inAppNotification: self.inAppNotification, chart: self.chart, preview: preview)
} }
public func withInvertedBlocksBackground() -> PresentationTheme {
let list = self.list.withUpdated(blocksBackgroundColor: self.list.itemBlocksBackgroundColor, itemBlocksBackgroundColor: self.list.blocksBackgroundColor)
return PresentationTheme(name: self.name, index: self.index, referenceTheme: self.referenceTheme, overallDarkAppearance: self.overallDarkAppearance, intro: self.intro, passcode: self.passcode, rootController: self.rootController, list: list, chatList: self.chatList, chat: self.chat, actionSheet: self.actionSheet, contextMenu: self.contextMenu, inAppNotification: self.inAppNotification, chart: self.chart, preview: self.preview)
}
} }

View File

@ -127,7 +127,11 @@ private enum AttachmentFileEntry: ItemListNodeEntry {
arguments.send(message) arguments.send(message)
return false return false
}, openMessageContextMenu: { _, _, _, _, _ in }, toggleMessagesSelection: { _, _ in }, openUrl: { _, _, _, _ in }, openInstantPage: { _, _ in }, longTap: { _, _ in }, getHiddenMedia: { return [:] }) }, openMessageContextMenu: { _, _, _, _, _ in }, toggleMessagesSelection: { _, _ in }, openUrl: { _, _, _, _ in }, openInstantPage: { _, _ in }, longTap: { _, _ in }, getHiddenMedia: { return [:] })
return ListMessageItem(presentationData: ChatPresentationData(presentationData: arguments.context.sharedContext.currentPresentationData.with({$0})), context: arguments.context, chatLocation: .peer(PeerId(0)), interaction: interaction, message: message, selection: .none, displayHeader: false, displayFileInfo: false, displayBackground: true, style: .blocks)
let dateTimeFormat = arguments.context.sharedContext.currentPresentationData.with({$0}).dateTimeFormat
let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .color(0)), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0, auxiliaryRadius: 0, mergeBubbleCorners: false))
return ListMessageItem(presentationData: chatPresentationData, context: arguments.context, chatLocation: .peer(PeerId(0)), interaction: interaction, message: message, selection: .none, displayHeader: false, displayFileInfo: false, displayBackground: true, style: .blocks)
} }
} }
} }
@ -212,8 +216,18 @@ public func attachmentFileController(context: AccountContext, updatedPresentatio
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let previousRecentDocuments = Atomic<[Message]?>(value: nil) let previousRecentDocuments = Atomic<[Message]?>(value: nil)
let signal = combineLatest(queue: Queue.mainQueue(), presentationData, recentDocuments, statePromise.get()) let signal = combineLatest(queue: Queue.mainQueue(),
presentationData,
recentDocuments,
statePromise.get()
)
|> map { presentationData, recentDocuments, state -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, recentDocuments, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
var presentationData = presentationData
if presentationData.theme.list.blocksBackgroundColor.rgb == 0x000000 {
let updatedTheme = presentationData.theme.withInvertedBlocksBackground()
presentationData = presentationData.withUpdated(theme: updatedTheme)
}
let previousRecentDocuments = previousRecentDocuments.swap(recentDocuments) let previousRecentDocuments = previousRecentDocuments.swap(recentDocuments)
let crossfade = previousRecentDocuments == nil && recentDocuments != nil let crossfade = previousRecentDocuments == nil && recentDocuments != nil
var animateChanges = false var animateChanges = false