Attachment menu improvements

This commit is contained in:
Ilya Laktyushin 2022-02-21 18:15:24 +03:00
parent 2dd23729b5
commit 8adf325410
9 changed files with 123 additions and 112 deletions

View File

@ -93,7 +93,17 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)?
let defaultTopInset: CGFloat = 210.0
private var defaultTopInset: CGFloat {
guard let (layout, _, _) = self.validLayout else{
return 210.0
}
if case .compact = layout.metrics.widthClass {
return min(layout.size.width, layout.size.height) * 0.2488
} else {
return 210.0
}
}
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
guard let (layout, controllers, coveredByModalTransition) = self.validLayout else {
return
@ -449,61 +459,10 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if !self.wrappingNode.frame.contains(point) {
let convertedPoint = self.view.convert(point, to: self.container.view)
if !self.container.frame.contains(convertedPoint) {
return false
}
return super.point(inside: point, with: event)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard let result = super.hitTest(point, with: event) else {
return nil
}
// var currentParent: UIView? = result
// var enableScrolling = true
// while true {
// if currentParent == nil {
// break
// }
// if currentParent is UIKeyInput {
// if currentParent?.disablesInteractiveModalDismiss == true {
// enableScrolling = false
// break
// }
// } else if let scrollView = currentParent as? UIScrollView {
// if scrollView === self.scrollNode.view {
// break
// }
// if scrollView.disablesInteractiveModalDismiss {
// enableScrolling = false
// break
// } else {
// if scrollView.isDecelerating && scrollView.contentOffset.y < -scrollView.contentInset.top {
// return self.scrollNode.view
// }
// }
// } else if let listView = currentParent as? ListViewBackingView, let listNode = listView.target {
// if listNode.view.disablesInteractiveModalDismiss {
// enableScrolling = false
// break
// } else if listNode.scroller.isDecelerating && listNode.scroller.contentOffset.y < listNode.scroller.contentInset.top {
// return self.scrollNode.view
// }
// }
// currentParent = currentParent?.superview
// }
// if let controller = self.container.controllers.last {
// if controller.view.disablesInteractiveModalDismiss {
// enableScrolling = false
// }
// }
// self.isInteractiveDimissEnabled = enableScrolling
// if let layout = self.validLayout {
// if layout.inputHeight != nil && layout.inputHeight != 0.0 {
// enableScrolling = false
// }
// }
// self.scrollNode.view.isScrollEnabled = enableScrolling
return result
}
}

View File

@ -22,6 +22,14 @@ public enum AttachmentButtonType: Equatable {
public protocol AttachmentContainable: ViewController {
var requestAttachmentMenuExpansion: () -> Void { get set }
func prepareForReuse()
}
public extension AttachmentContainable {
func prepareForReuse() {
}
}
public enum AttachmentMediaPickerSendMode {
@ -226,6 +234,9 @@ public class AttachmentController: ViewController {
func switchToController(_ type: AttachmentButtonType, _ ascending: Bool) {
guard self.currentType != type else {
if let controller = self.currentController {
controller.scrollToTopWithTabBar?()
}
return
}
let previousType = self.currentType
@ -240,6 +251,7 @@ public class AttachmentController: ViewController {
self?.container.update(isExpanded: true, transition: .animated(duration: 0.4, curve: .spring))
}
let previousController = strongSelf.currentController
let animateTransition = previousType != nil
strongSelf.currentController = controller
@ -256,15 +268,10 @@ public class AttachmentController: ViewController {
guard let strongSelf = self else {
return
}
if ascending {
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: 70.0, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
} else {
strongSelf.container.container.view.layer.animatePosition(from: CGPoint(x: -70.0, y: 0.0), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
}
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?.prepareForReuse()
})
})
}

View File

@ -27,8 +27,6 @@ private final class AttachButtonComponent: CombinedComponent {
let context: AccountContext
let type: AttachmentButtonType
let isSelected: Bool
let isCollapsed: Bool
let transitionFraction: CGFloat
let strings: PresentationStrings
let theme: PresentationTheme
let action: () -> Void
@ -37,8 +35,6 @@ private final class AttachButtonComponent: CombinedComponent {
context: AccountContext,
type: AttachmentButtonType,
isSelected: Bool,
isCollapsed: Bool,
transitionFraction: CGFloat,
strings: PresentationStrings,
theme: PresentationTheme,
action: @escaping () -> Void
@ -46,8 +42,6 @@ private final class AttachButtonComponent: CombinedComponent {
self.context = context
self.type = type
self.isSelected = isSelected
self.isCollapsed = isCollapsed
self.transitionFraction = transitionFraction
self.strings = strings
self.theme = theme
self.action = action
@ -63,12 +57,6 @@ private final class AttachButtonComponent: CombinedComponent {
if lhs.isSelected != rhs.isSelected {
return false
}
if lhs.isCollapsed != rhs.isCollapsed {
return false
}
if lhs.transitionFraction != rhs.transitionFraction {
return false
}
if lhs.strings !== rhs.strings {
return false
}
@ -81,6 +69,7 @@ private final class AttachButtonComponent: CombinedComponent {
static var body: Body {
let icon = Child(Image.self)
let title = Child(Text.self)
let button = Child(Rectangle.self)
return { context in
let name: String
@ -114,7 +103,10 @@ private final class AttachButtonComponent: CombinedComponent {
let tintColor = component.isSelected ? component.theme.rootController.tabBar.selectedIconColor : component.theme.rootController.tabBar.iconColor
let icon = icon.update(
component: Image(image: image, tintColor: tintColor),
component: Image(
image: image,
tintColor: tintColor
),
availableSize: CGSize(width: 30.0, height: 30.0),
transition: context.transition
)
@ -128,8 +120,18 @@ private final class AttachButtonComponent: CombinedComponent {
availableSize: context.availableSize,
transition: .immediate
)
let button = button.update(
component: Rectangle(
color: .clear,
width: context.availableSize.width,
height: context.availableSize.height
),
availableSize: context.availableSize,
transition: .immediate
)
let topInset: CGFloat = 5.0 + UIScreenPixel
let topInset: CGFloat = 4.0 + UIScreenPixel
let spacing: CGFloat = 15.0 + UIScreenPixel
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((context.availableSize.width - icon.size.width) / 2.0), y: topInset), size: icon.size)
@ -137,18 +139,19 @@ private final class AttachButtonComponent: CombinedComponent {
context.add(title
.position(CGPoint(x: titleFrame.midX, y: titleFrame.midY))
.gesture(.tap {
component.action()
})
)
context.add(icon
.position(CGPoint(x: iconFrame.midX, y: iconFrame.midY))
)
context.add(button
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
.gesture(.tap {
component.action()
})
)
return context.availableSize
}
}
@ -451,33 +454,26 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
}
let visibleRect = self.scrollNode.bounds.insetBy(dx: -180.0, dy: 0.0)
let actualVisibleRect = self.scrollNode.bounds
var validButtons = Set<Int>()
var sideInset = sideInset
let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count)
if buttonsWidth < layout.size.width {
sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0)
}
let distanceBetweenNodes = layout.size.width / CGFloat(self.buttons.count)
let internalWidth = distanceBetweenNodes * CGFloat(self.buttons.count - 1)
let leftNodeOriginX = (layout.size.width - internalWidth) / 2.0
// var sideInset = sideInset
// let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count)
// if buttonsWidth < layout.size.width {
// sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0)
// }
//
for i in 0 ..< self.buttons.count {
let buttonFrame = CGRect(origin: CGPoint(x: sideInset + buttonSize.width * CGFloat(i), y: 0.0), size: buttonSize)
let originX = floor(leftNodeOriginX + CGFloat(i) * distanceBetweenNodes - buttonSize.width / 2.0)
let buttonFrame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: buttonSize)
if !visibleRect.intersects(buttonFrame) {
continue
}
validButtons.insert(i)
let edge = buttonSize.width * 0.75
let leftEdge = max(-edge, min(0.0, buttonFrame.minX - actualVisibleRect.minX)) / -edge
let rightEdge = min(edge, max(0.0, buttonFrame.maxX - actualVisibleRect.maxX)) / edge
let transitionFraction: CGFloat
if leftEdge > rightEdge {
transitionFraction = leftEdge
} else {
transitionFraction = -rightEdge
}
var buttonTransition = transition
let buttonView: ComponentHostView<Empty>
if let current = self.buttonViews[i] {
@ -496,8 +492,6 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
context: self.context,
type: type,
isSelected: i == self.selectedIndex,
isCollapsed: self.isCollapsed,
transitionFraction: transitionFraction,
strings: self.presentationData.strings,
theme: self.presentationData.theme,
action: { [weak self] in
@ -524,13 +518,14 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
return false
}
var sideInset = sideInset
let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count)
if buttonsWidth < layout.size.width {
sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0)
}
// var sideInset = sideInset
// let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count)
// if buttonsWidth < layout.size.width {
// sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0)
// }
let contentSize = CGSize(width: sideInset * 2.0 + CGFloat(self.buttons.count) * buttonSize.width, height: buttonSize.height)
let contentSize = CGSize(width: layout.size.width, height: buttonSize.height)
// CGSize(width: sideInset * 2.0 + CGFloat(self.buttons.count) * buttonSize.width, height: buttonSize.height)
self.scrollLayout = (layout.size.width, contentSize)
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.isSelecting ? -buttonSize.height : 0.0), size: CGSize(width: layout.size.width, height: buttonSize.height)))

View File

@ -333,4 +333,10 @@ public final class LocationPickerController: ViewController, AttachmentContainab
self.interaction?.openSearch()
}
public func prepareForReuse() {
self.interaction?.updateMapMode(.map)
self.interaction?.dismissSearch()
self.scrollToTop?()
}
}

View File

@ -36,6 +36,7 @@ swift_library(
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
"//submodules/WebSearchUI:WebSearchUI",
],
visibility = [
"//visibility:public",

View File

@ -17,6 +17,7 @@ import SegmentedControlNode
import ManagedAnimationNode
import ContextUI
import LegacyMediaPickerUI
import WebSearchUI
private class MediaAssetsContext: NSObject, PHPhotoLibraryChangeObserver {
private var registeredChangeObserver = false
@ -388,6 +389,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private let titleView: MediaPickerSegmentedTitleView
private let moreButtonNode: MediaPickerMoreButtonNode
public weak var webSearchController: WebSearchController?
public var openCamera: ((TGAttachmentCameraView?) -> Void)?
public var presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)?
public var presentSchedulePicker: (Bool, @escaping (Int32) -> Void) -> Void = { _, _ in }
@ -1016,7 +1019,21 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.scrollToTop = { [weak self] in
if let strongSelf = self {
strongSelf.controllerNode.scrollToTop(animated: true)
if let webSearchController = strongSelf.webSearchController {
webSearchController.scrollToTop?()
} else {
strongSelf.controllerNode.scrollToTop(animated: true)
}
}
}
self.scrollToTopWithTabBar = { [weak self] in
if let strongSelf = self {
if let webSearchController = strongSelf.webSearchController {
webSearchController.cancel()
} else {
strongSelf.scrollToTop?()
}
}
}
}
@ -1067,6 +1084,14 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.dismiss()
}
public func prepareForReuse() {
if let webSearchController = self.webSearchController {
self.webSearchController = nil
webSearchController.dismiss()
}
self.scrollToTop?()
}
@objc private func searchOrMorePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) {
switch self.moreButtonNode.iconNode.iconState {
case .search:

View File

@ -158,6 +158,12 @@ private func attachmentFileControllerEntries(presentationData: PresentationData,
private class AttachmentFileControllerImpl: ItemListController, AttachmentContainable {
public var requestAttachmentMenuExpansion: () -> Void = {}
var prepareForReuseImpl: () -> Void = {}
public func prepareForReuse() {
self.prepareForReuseImpl()
self.scrollToTop?()
}
}
private struct AttachmentFileControllerState: Equatable {
@ -259,6 +265,13 @@ public func attachmentFileController(context: AccountContext, updatedPresentatio
}
let controller = AttachmentFileControllerImpl(context: context, state: signal)
controller.prepareForReuseImpl = {
updateState { state in
var updatedState = state
updatedState.searching = false
return updatedState
}
}
dismissImpl = { [weak controller] in
controller?.dismiss(animated: true)
}

View File

@ -10989,6 +10989,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
webSearchController.dismissed = {
updateMediaPickerContext(mediaPickerContext)
}
controller?.webSearchController = webSearchController
updateMediaPickerContext(webSearchController.mediaPickerContext)
}
})

View File

@ -241,11 +241,7 @@ public final class WebSearchController: ViewController {
}
navigationContentNode.cancel = { [weak self] in
if let strongSelf = self {
strongSelf.controllerNode.dismissInput?()
strongSelf.controllerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] _ in
self?.dismissed()
self?.dismiss()
})
strongSelf.cancel()
}
}
self.navigationBar?.setContentNode(navigationContentNode, animated: false)
@ -320,6 +316,14 @@ public final class WebSearchController: ViewController {
self.selectionDisposable?.dispose()
}
public func cancel() {
self.controllerNode.dismissInput?()
self.controllerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak self] _ in
self?.dismissed()
self?.dismiss()
})
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)