mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Attachment menu improvements
This commit is contained in:
parent
2dd23729b5
commit
8adf325410
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -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)))
|
||||
|
@ -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?()
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ swift_library(
|
||||
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
|
||||
"//submodules/PresentationDataUtils:PresentationDataUtils",
|
||||
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
|
||||
"//submodules/WebSearchUI:WebSearchUI",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -10989,6 +10989,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
webSearchController.dismissed = {
|
||||
updateMediaPickerContext(mediaPickerContext)
|
||||
}
|
||||
controller?.webSearchController = webSearchController
|
||||
updateMediaPickerContext(webSearchController.mediaPickerContext)
|
||||
}
|
||||
})
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user