mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Attachment menu improvements
This commit is contained in:
parent
e70f17ff2d
commit
59595cb027
@ -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 })
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user