Merge commit 'f9f9f20141efba933f6159243df5f19f8cacb024'

This commit is contained in:
Ali 2022-02-27 15:43:55 +04:00
commit 0befe4d8bc
24 changed files with 404 additions and 95 deletions

View File

@ -7307,25 +7307,13 @@ Sorry for the inconvenience.";
"Attachment.OpenCamera" = "Open Camera";
"Attachment.DeselectedPhotos_1" = "%@ photo deselected";
"Attachment.DeselectedPhotos_2" = "%@ photos deselected";
"Attachment.DeselectedPhotos_3_10" = "%@ photos deselected";
"Attachment.DeselectedPhotos_any" = "%@ photos deselected";
"Attachment.DeselectedPhotos_many" = "%@ photos deselected";
"Attachment.DeselectedPhotos_0" = "%@ photos deselected";
"Attachment.DeselectedVideos_1" = "%@ video deselected";
"Attachment.DeselectedVideos_2" = "%@ videos deselected";
"Attachment.DeselectedVideos_3_10" = "%@ videos deselected";
"Attachment.DeselectedVideos_any" = "%@ videos deselected";
"Attachment.DeselectedVideos_many" = "%@ videos deselected";
"Attachment.DeselectedVideos_0" = "%@ videos deselected";
"Attachment.DeselectedItems_1" = "%@ item deselected";
"Attachment.DeselectedItems_2" = "%@ items deselected";
"Attachment.DeselectedItems_3_10" = "%@ items deselected";
"Attachment.DeselectedItems_any" = "%@ items deselected";
"Attachment.DeselectedItems_many" = "%@ items deselected";
"Attachment.DeselectedItems_0" = "%@ items deselected";
"PrivacyPhoneNumberSettings.CustomPublicLink" = "Users who have your number saved in their contacts will also see it on Telegram.\n\nThis public link opens a chat with you:\n[https://t.me/%@]()";
@ -7357,3 +7345,6 @@ Sorry for the inconvenience.";
"Attachment.MyAlbums" = "My Albums";
"Attachment.MediaTypes" = "Media Types";
"Attachment.LocationAccessTitle" = "Access Your Location";
"Attachment.LocationAccessText" = "Share places or your live location.";

View File

@ -22,7 +22,7 @@ public enum AttachmentButtonType: Equatable {
public protocol AttachmentContainable: ViewController {
var requestAttachmentMenuExpansion: () -> Void { get set }
var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void { get set }
var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void { get set }
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void { get set }
var cancelPanGesture: () -> Void { get set }
@ -289,7 +289,6 @@ public class AttachmentController: ViewController {
self.currentType = type
self.controller?.requestController(type, { [weak self] controller, mediaPickerContext in
if let strongSelf = self {
strongSelf.mediaPickerContext = mediaPickerContext
if let controller = controller {
strongSelf.controller?._ready.set(controller.ready.get())
controller._presentedInModal = true
@ -299,7 +298,9 @@ public class AttachmentController: ViewController {
}
controller.updateNavigationStack = { [weak self] f in
if let strongSelf = self {
strongSelf.currentControllers = f(strongSelf.currentControllers)
let (controllers, mediaPickerContext) = f(strongSelf.currentControllers)
strongSelf.currentControllers = controllers
strongSelf.mediaPickerContext = mediaPickerContext
if let layout = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
}
@ -346,6 +347,7 @@ public class AttachmentController: ViewController {
strongSelf.switchingController = false
}
}
strongSelf.mediaPickerContext = mediaPickerContext
}
})
}
@ -419,7 +421,6 @@ public class AttachmentController: ViewController {
}
}
private var isCollapsed: Bool = false
private var isUpdatingContainer = false
private var switchingController = false
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
@ -427,22 +428,15 @@ public class AttachmentController: ViewController {
transition.updateFrame(node: self.dim, frame: CGRect(origin: CGPoint(), size: layout.size))
if self.modalProgress < 0.5 {
self.isCollapsed = false
} else if self.modalProgress == 1.0 {
self.isCollapsed = true
}
var containerLayout = layout
let containerRect: CGRect
if case .regular = layout.metrics.widthClass {
let size = CGSize(width: 390.0, height: 620.0)
let insets = layout.insets(options: [.input])
let masterWidth = min(max(320.0, floor(layout.size.width / 3.0)), floor(layout.size.width / 2.0))
var position: CGPoint = CGPoint(x: masterWidth - 174.0, y: layout.size.height - size.height - layout.intrinsicInsets.bottom - 40.0)
if let inputHeight = layout.inputHeight {
position.y -= inputHeight
}
let position: CGPoint = CGPoint(x: masterWidth - 174.0, y: layout.size.height - size.height - insets.bottom - 40.0)
containerRect = CGRect(origin: position, size: size)
containerLayout.size = containerRect.size
containerLayout.intrinsicInsets.bottom = 12.0
@ -469,8 +463,8 @@ public class AttachmentController: ViewController {
}
let isEffecitvelyCollapsedUpdated = (self.isCollapsed || self.selectionCount > 0) != (self.panel.isCollapsed || self.panel.isSelecting)
let panelHeight = self.panel.update(layout: containerLayout, buttons: self.controller?.buttons ?? [], isCollapsed: self.isCollapsed, isSelecting: self.selectionCount > 0, transition: transition)
let isEffecitvelyCollapsedUpdated = (self.selectionCount > 0) != (self.panel.isSelecting)
let panelHeight = self.panel.update(layout: containerLayout, buttons: self.controller?.buttons ?? [], isSelecting: self.selectionCount > 0, transition: transition)
var panelTransition = transition
if isEffecitvelyCollapsedUpdated {
panelTransition = .animated(duration: 0.25, curve: .easeInOut)

View File

@ -169,7 +169,6 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
private var buttons: [AttachmentButtonType] = []
private var selectedIndex: Int = 0
private(set) var isCollapsed: Bool = false
private(set) var isSelecting: Bool = false
private var validLayout: ContainerViewLayout?
@ -383,7 +382,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
strongSelf.updateChatPresentationInterfaceState({ $0.updatedTheme(presentationData.theme) })
if let layout = strongSelf.validLayout {
let _ = strongSelf.update(layout: layout, buttons: strongSelf.buttons, isCollapsed: strongSelf.isCollapsed, isSelecting: strongSelf.isSelecting, transition: .immediate)
let _ = strongSelf.update(layout: layout, buttons: strongSelf.buttons, isSelecting: strongSelf.isSelecting, transition: .immediate)
}
}
})
@ -551,13 +550,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
}
}
func update(layout: ContainerViewLayout, buttons: [AttachmentButtonType], isCollapsed: Bool, isSelecting: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
func update(layout: ContainerViewLayout, buttons: [AttachmentButtonType], isSelecting: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
self.validLayout = layout
self.buttons = buttons
let isCollapsedUpdated = self.isCollapsed != isCollapsed
self.isCollapsed = isCollapsed
let isSelectingUpdated = self.isSelecting != isSelecting
self.isSelecting = isSelecting
@ -605,7 +601,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
containerFrame = bounds
}
let containerBounds = CGRect(origin: CGPoint(), size: containerFrame.size)
if isCollapsedUpdated || isSelectingUpdated {
if isSelectingUpdated {
containerTransition = .animated(duration: 0.25, curve: .easeInOut)
} else {
containerTransition = transition
@ -635,13 +631,9 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
self.backgroundNode.update(size: containerBounds.size, transition: transition)
containerTransition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: UIScreenPixel)))
let _ = self.updateScrollLayoutIfNeeded(force: isCollapsedUpdated || isSelectingUpdated, transition: containerTransition)
let _ = self.updateScrollLayoutIfNeeded(force: isSelectingUpdated, transition: containerTransition)
var buttonTransition: Transition = .immediate
if isCollapsedUpdated {
buttonTransition = .easeInOut(duration: 0.25)
}
self.updateViews(transition: buttonTransition)
self.updateViews(transition: .immediate)
return containerFrame.height
}

View File

@ -518,7 +518,7 @@ public final class ComposedPoll {
private class CreatePollControllerImpl: ItemListController, AttachmentContainable {
public var requestAttachmentMenuExpansion: () -> Void = {}
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
public var cancelPanGesture: () -> Void = { }
}

View File

@ -1499,7 +1499,10 @@ public final class ContactListNode: ASDisplayNode {
self.indexNode.update(size: indexNodeFrame.size, color: self.presentationData.theme.list.itemAccentColor, sections: indexSections, transition: transition)
}
self.authorizationNode.updateLayout(size: layout.size, insets: insets, transition: transition)
let permissionSize = CGSize(width: layout.size.width, height: layout.size.height - 160.0)
var permissionInsets = insets
permissionInsets.bottom += 100.0
self.authorizationNode.updateLayout(size: permissionSize, insets: permissionInsets, transition: transition)
transition.updateFrame(node: self.authorizationNode, frame: self.bounds)
if !hadValidLayout {

View File

@ -20,7 +20,6 @@ public enum DeviceAccessCameraSubject {
case qrCode
}
public enum DeviceAccessMicrophoneSubject {
case audio
case video

View File

@ -127,6 +127,7 @@ public class ImageNode: ASDisplayNode {
private var first = true
private let enableEmpty: Bool
public var enableAnimatedTransition: Bool
public var animateFirstTransition = true
private let _contentReady = Promise<Bool>()
private var didSetReady: Bool = false
@ -166,7 +167,7 @@ public class ImageNode: ASDisplayNode {
if strongSelf.first && next != nil {
strongSelf.first = false
animate = false
if strongSelf.isNodeLoaded {
if strongSelf.isNodeLoaded && strongSelf.animateFirstTransition {
strongSelf.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
}
}

View File

@ -1056,7 +1056,7 @@ open class NavigationBar: ASDisplayNode {
var rightTitleInset: CGFloat = rightInset + 1.0
if self.backButtonNode.supernode != nil {
let backButtonSize = self.backButtonNode.updateLayout(constrainedSize: CGSize(width: size.width, height: nominalHeight), isLandscape: isLandscape)
leftTitleInset += backButtonSize.width + backButtonInset + 1.0
leftTitleInset = backButtonSize.width + backButtonInset + 1.0
let topHitTestSlop = (nominalHeight - backButtonSize.height) * 0.5
self.backButtonNode.hitTestSlop = UIEdgeInsets(top: -topHitTestSlop, left: -27.0, bottom: -topHitTestSlop, right: -8.0)

View File

@ -177,7 +177,9 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
self.bottomStripeNode = ASDisplayNode()
self.bottomStripeNode.isLayerBacked = true
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
self.extractedBackgroundImageNode = ASImageNode()
self.extractedBackgroundImageNode.displaysAsynchronously = false
@ -671,7 +673,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.topStripeNode.removeFromSupernode()
}
if strongSelf.bottomStripeNode.supernode == nil {
strongSelf.addSubnode(strongSelf.bottomStripeNode)
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0)
}
if strongSelf.maskNode.supernode != nil {
strongSelf.maskNode.removeFromSupernode()
@ -693,10 +695,10 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
}
if strongSelf.bottomStripeNode.supernode == nil {
strongSelf.addSubnode(strongSelf.bottomStripeNode)
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
}
if strongSelf.maskNode.supernode == nil {
strongSelf.addSubnode(strongSelf.maskNode)
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
}
let hasCorners = itemListHasRoundedBlockLayout(params)
@ -765,6 +767,8 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
shimmerNode = ShimmerEffectNode()
strongSelf.placeholderNode = shimmerNode
if strongSelf.bottomStripeNode.supernode != nil {
strongSelf.bottomStripeNode.removeFromSupernode()
strongSelf.addSubnode(strongSelf.bottomStripeNode)
strongSelf.insertSubnode(shimmerNode, belowSubnode: strongSelf.bottomStripeNode)
} else {
strongSelf.addSubnode(shimmerNode)

View File

@ -81,9 +81,11 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, content: JoinLinkPreviewPeerContentNode.Content) {
self.avatarNode = AvatarNode(font: avatarFont)
self.titleNode = ASTextNode()
self.titleNode.textAlignment = .center
self.countNode = ASTextNode()
self.aboutNode = ASTextNode()
self.aboutNode.maximumNumberOfLines = 8
self.aboutNode.textAlignment = .center
self.descriptionNode = ASTextNode()
self.descriptionNode.maximumNumberOfLines = 3
self.descriptionNode.textAlignment = .center
@ -153,7 +155,7 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
if case let .request(isGroup, _, _, about, _) = content {
if let about = about, !about.isEmpty {
self.aboutNode.attributedText = NSAttributedString(string: about, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor)
self.aboutNode.attributedText = NSAttributedString(string: about, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
self.addSubnode(self.aboutNode)
}

View File

@ -406,7 +406,7 @@ open class LegacyController: ViewController, PresentableController, AttachmentCo
public var disposables = DisposableSet()
open var requestAttachmentMenuExpansion: () -> Void = {}
open var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
open var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
open var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
open var cancelPanGesture: () -> Void = { }

View File

@ -900,7 +900,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
}
transition.updateFrame(node: strongSelf.separatorNode, frame: CGRect(origin: CGPoint(x: leftInset + leftOffset, y: nodeLayout.contentSize.height - UIScreenPixel), size: CGSize(width: params.width - leftInset - leftOffset, height: UIScreenPixel)))
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel))
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -nodeLayout.insets.top - UIScreenPixel), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel - nodeLayout.insets.bottom))
if let backgroundNode = strongSelf.backgroundNode {
backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -nodeLayout.insets.top), size: CGSize(width: params.width, height: nodeLayout.size.height - nodeLayout.insets.bottom))

View File

@ -43,6 +43,8 @@ swift_library(
"//submodules/TooltipUI:TooltipUI",
"//submodules/UndoUI:UndoUI",
"//submodules/AttachmentUI:AttachmentUI",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
],
visibility = [
"//visibility:public",

View File

@ -72,7 +72,7 @@ public final class LocationPickerController: ViewController, AttachmentContainab
private var interaction: LocationPickerInteraction?
public var requestAttachmentMenuExpansion: () -> Void = {}
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
public var cancelPanGesture: () -> Void = { }
@ -294,7 +294,7 @@ public final class LocationPickerController: ViewController, AttachmentContainab
return
}
self.displayNode = LocationPickerControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, interaction: interaction, locationManager: self.locationManager)
self.displayNode = LocationPickerControllerNode(controller: self, context: self.context, presentationData: self.presentationData, mode: self.mode, interaction: interaction, locationManager: self.locationManager)
self.displayNodeDidLoad()
self.controllerNode.beganInteractiveDragging = { [weak self] in
self?.requestAttachmentMenuExpansion()
@ -347,8 +347,4 @@ public final class LocationPickerController: ViewController, AttachmentContainab
self.interaction?.dismissSearch()
self.scrollToTop?()
}
public func prepareForReuse() {
self.updateTabBarAlpha(1.0, .animated(duration: 0.25, curve: .easeInOut))
}
}

View File

@ -240,7 +240,44 @@ struct LocationPickerState {
}
}
private class LocationContext: NSObject, CLLocationManagerDelegate {
private let locationManager: CLLocationManager
private let accessSink = ValuePipe<CLAuthorizationStatus>()
override init() {
self.locationManager = CLLocationManager()
super.init()
self.locationManager.delegate = self
}
func locationAccess() -> Signal<CLAuthorizationStatus, NoError> {
let initialStatus: CLAuthorizationStatus
if #available(iOS 14.0, *) {
initialStatus = self.locationManager.authorizationStatus
} else {
initialStatus = CLLocationManager.authorizationStatus()
}
return .single(initialStatus)
|> then(
self.accessSink.signal()
)
}
@available(iOS 14.0, *)
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
self.accessSink.putNext(manager.authorizationStatus)
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
self.accessSink.putNext(status)
}
}
final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationManagerDelegate {
private weak var controller: LocationPickerController?
private let context: AccountContext
private var presentationData: PresentationData
private let presentationDataPromise: Promise<PresentationData>
@ -248,6 +285,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
private let interaction: LocationPickerInteraction
private let locationManager: LocationManager
private let locationContext: LocationContext
private let listNode: ListView
private let emptyResultsTextNode: ImmediateTextNode
private let headerNode: LocationMapHeaderNode
@ -257,6 +296,10 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
private let optionsNode: LocationOptionsNode
private(set) var searchContainerNode: LocationSearchContainerNode?
private var placeholderBackgroundNode: NavigationBackgroundNode?
private var placeholderNode: LocationPlaceholderNode?
private var locationAccessDenied = false
private var enqueuedTransitions: [LocationPickerTransaction] = []
private var disposable: Disposable?
@ -271,7 +314,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
var beganInteractiveDragging: () -> Void = {}
init(context: AccountContext, presentationData: PresentationData, mode: LocationPickerMode, interaction: LocationPickerInteraction, locationManager: LocationManager) {
init(controller: LocationPickerController, context: AccountContext, presentationData: PresentationData, mode: LocationPickerMode, interaction: LocationPickerInteraction, locationManager: LocationManager) {
self.controller = controller
self.context = context
self.presentationData = presentationData
self.presentationDataPromise = Promise(presentationData)
@ -279,6 +323,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
self.interaction = interaction
self.locationManager = locationManager
self.locationContext = LocationContext()
self.state = LocationPickerState()
self.statePromise = Promise(self.state)
@ -448,8 +494,8 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
let previousAnnotations = Atomic<[LocationPinAnnotation]>(value: [])
let previousEntries = Atomic<[LocationPickerEntry]?>(value: nil)
self.disposable = (combineLatest(self.presentationDataPromise.get(), self.statePromise.get(), userLocation, venues, foundVenues)
|> deliverOnMainQueue).start(next: { [weak self] presentationData, state, userLocation, venues, foundVenuesAndLocation in
self.disposable = (combineLatest(self.presentationDataPromise.get(), self.statePromise.get(), userLocation, venues, foundVenues, self.locationContext.locationAccess())
|> deliverOnMainQueue).start(next: { [weak self] presentationData, state, userLocation, venues, foundVenuesAndLocation, access in
if let strongSelf = self {
let (foundVenues, foundVenuesLocation) = foundVenuesAndLocation ?? (nil, nil)
@ -590,6 +636,18 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
var updateLayout = false
let transition: ContainedViewLayoutTransition = .animated(duration: 0.45, curve: .spring)
if [.denied, .restricted].contains(access) {
if !strongSelf.locationAccessDenied {
strongSelf.locationAccessDenied = true
updateLayout = true
}
} else {
if strongSelf.locationAccessDenied {
strongSelf.locationAccessDenied = false
updateLayout = true
}
}
if previousState.displayingMapModeOptions != state.displayingMapModeOptions {
updateLayout = true
} else if previousState.selectedLocation.isCustom != state.selectedLocation.isCustom {
@ -892,6 +950,57 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
searchContainerNode.frame = CGRect(origin: CGPoint(), size: layout.size)
searchContainerNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationHeight, transition: transition)
}
if self.locationAccessDenied {
self.controller?.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate)
Queue.mainQueue().after(0.25) {
self.controller?.updateTabBarAlpha(0.0, .immediate)
}
var placeholderTransition = transition
let placeholderNode: LocationPlaceholderNode
let backgroundNode: NavigationBackgroundNode
if let current = self.placeholderNode, let background = self.placeholderBackgroundNode {
placeholderNode = current
backgroundNode = background
backgroundNode.updateColor(color: self.presentationData.theme.rootController.tabBar.backgroundColor, transition: .immediate)
} else {
backgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.tabBar.backgroundColor)
if let navigationBar = self.controller?.navigationBar {
self.insertSubnode(backgroundNode, belowSubnode: navigationBar)
} else {
self.addSubnode(backgroundNode)
}
self.placeholderBackgroundNode = backgroundNode
placeholderNode = LocationPlaceholderNode(content: .intro)
placeholderNode.settingsPressed = { [weak self] in
self?.context.sharedContext.applicationBindings.openSettings()
}
self.insertSubnode(placeholderNode, aboveSubnode: backgroundNode)
self.placeholderNode = placeholderNode
placeholderTransition = .immediate
}
placeholderNode.update(layout: layout, theme: self.presentationData.theme, strings: self.presentationData.strings, transition: placeholderTransition)
placeholderTransition.updateFrame(node: placeholderNode, frame: CGRect(origin: CGPoint(), size: layout.size))
let placeholderFrame = CGRect(origin: CGPoint(), size: layout.size)
backgroundNode.update(size: placeholderFrame.size, transition: placeholderTransition)
placeholderTransition.updateFrame(node: placeholderNode, frame: placeholderFrame)
} else {
if let placeholderNode = self.placeholderNode {
self.placeholderNode = nil
placeholderNode.removeFromSupernode()
}
if let placeholderBackgroundNode = self.placeholderBackgroundNode {
self.placeholderBackgroundNode = nil
placeholderBackgroundNode.removeFromSupernode()
}
self.controller?.updateTabBarAlpha(1.0, .immediate)
}
}
func updateSendActionHighlight(_ highlighted: Bool) {

View File

@ -0,0 +1,134 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import TelegramPresentationData
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import SolidRoundedButtonNode
import PresentationDataUtils
final class LocationPlaceholderNode: ASDisplayNode {
enum Content {
case intro
}
private let content: Content
private var animationNode: AnimatedStickerNode
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private let buttonNode: SolidRoundedButtonNode
private var validLayout: ContainerViewLayout?
private var cameraTextNode: ImmediateTextNode
var settingsPressed: () -> Void = {}
var cameraPressed: () -> Void = {}
init(content: Content) {
self.content = content
let name: String
let playbackMode: AnimatedStickerPlaybackMode
switch content {
case .intro:
name = "Location"
playbackMode = .loop
}
self.animationNode = AnimatedStickerNode()
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: name), width: 320, height: 320, playbackMode: playbackMode, mode: .direct(cachePathPrefix: nil))
self.animationNode.visibility = true
self.titleNode = ImmediateTextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleNode.textAlignment = .center
self.titleNode.maximumNumberOfLines = 1
self.textNode = ImmediateTextNode()
self.textNode.isUserInteractionEnabled = false
self.textNode.lineSpacing = 0.1
self.textNode.textAlignment = .center
self.textNode.maximumNumberOfLines = 0
self.buttonNode = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: .black, foregroundColor: .white), height: 50.0, cornerRadius: 12.0, gloss: true)
self.cameraTextNode = ImmediateTextNode()
self.cameraTextNode.isUserInteractionEnabled = false
super.init()
self.addSubnode(self.animationNode)
self.addSubnode(self.textNode)
if case .intro = self.content {
self.addSubnode(self.titleNode)
self.addSubnode(self.buttonNode)
self.buttonNode.pressed = { [weak self] in
self?.settingsPressed()
}
}
}
private var theme: PresentationTheme?
func update(layout: ContainerViewLayout, theme: PresentationTheme, strings: PresentationStrings, transition: ContainedViewLayoutTransition) {
self.validLayout = layout
let themeUpdated = self.theme != theme
self.theme = theme
var imageSize = CGSize(width: 144.0, height: 144.0)
var insets = layout.insets(options: [])
if layout.size.width == 460.0 {
insets.top += -60.0
imageSize = CGSize(width: 112.0, height: 112.0)
} else {
insets.top += -160.0
}
let imageSpacing: CGFloat = 12.0
let textSpacing: CGFloat = 12.0
let buttonSpacing: CGFloat = 15.0
let cameraSpacing: CGFloat = 13.0
let imageHeight = layout.size.width < layout.size.height ? imageSize.height + imageSpacing : 0.0
if themeUpdated {
self.buttonNode.updateTheme(SolidRoundedButtonTheme(theme: theme))
}
self.buttonNode.title = strings.Attachment_OpenSettings
let buttonWidth: CGFloat = 248.0
let buttonHeight = self.buttonNode.updateLayout(width: buttonWidth, transition: transition)
let title: String
let text: String
switch self.content {
case .intro:
title = strings.Attachment_LocationAccessTitle
text = strings.Attachment_LocationAccessText
}
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(17.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: theme.list.freeTextColor, paragraphAlignment: .center)
self.cameraTextNode.attributedText = NSAttributedString(string: strings.Attachment_OpenCamera, font: Font.regular(17.0), textColor: theme.list.itemAccentColor, paragraphAlignment: .center)
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - 40.0, height: max(1.0, layout.size.height - insets.top - insets.bottom)))
let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - 40.0, height: max(1.0, layout.size.height - insets.top - insets.bottom)))
let cameraSize = self.cameraTextNode.updateLayout(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - 70.0, height: max(1.0, layout.size.height - insets.top - insets.bottom)))
let totalHeight = imageHeight + titleSize.height + textSpacing + textSize.height + buttonSpacing + buttonHeight + cameraSpacing + cameraSize.height
let topOffset = insets.top + floor((layout.size.height - insets.top - insets.bottom - totalHeight) / 2.0)
transition.updateAlpha(node: self.animationNode, alpha: imageHeight > 0.0 ? 1.0 : 0.0)
transition.updateFrame(node: self.animationNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - imageSize.width) / 2.0), y: topOffset), size: imageSize))
self.animationNode.updateLayout(size: imageSize)
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - titleSize.width - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: topOffset + imageHeight), size: titleSize))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - textSize.width - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: self.titleNode.frame.maxY + textSpacing), size: textSize))
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((layout.size.width - buttonWidth - layout.safeInsets.left - layout.safeInsets.right) / 2.0), y: self.textNode.frame.maxY + buttonSpacing), size: CGSize(width: buttonWidth, height: buttonHeight)))
}
}

View File

@ -74,7 +74,7 @@ enum LegacyMediaPickerGallerySource {
case selection(item: TGMediaSelectableItem)
}
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, chatLocation: ChatLocation?, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?) -> Void, presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)?, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void) {
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, chatLocation: ChatLocation?, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?) -> Void, presentStickers: ((@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?)?, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void, dismissAll: @escaping () -> Void) {
let reminder = peer?.id == context.account.peerId
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
@ -186,10 +186,12 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
updateHiddenMedia(nil)
legacyController?.dismiss()
}
model.interfaceView.donePressed = { [weak controller] item in
if let item = item as? TGMediaPickerGalleryItem {
controller?.dismissWhenReady(animated: true)
completed(item.asset, false, nil)
dismissAll()
}
}
model.interfaceView.doneLongPressed = { [weak selectionContext, weak editingContext, weak legacyController, weak model] item in

View File

@ -120,6 +120,8 @@ private final class MediaGroupsGridAlbumItemNode : ListViewItemNode {
self.imageNode = ImageNode()
self.imageNode.clipsToBounds = true
self.imageNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 62.0))
self.imageNode.contentMode = .scaleAspectFill
self.imageNode.animateFirstTransition = false
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
@ -332,13 +334,19 @@ private class MediaGroupsAlbumGridItemNode: ListViewItemNode {
let listInsets = UIEdgeInsets(top: 10.0, left: 0.0, bottom: 10.0, right: 0.0)
strongSelf.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: contentSize.height, height: contentSize.width - params.leftInset - params.rightInset)
strongSelf.listNode.position = CGPoint(x: contentSize.width / 2.0, y: contentSize.height / 2.0)
strongSelf.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: contentSize.height, height: contentSize.width), insets: listInsets, duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
strongSelf.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: contentSize.height, height: contentSize.width - params.leftInset - params.rightInset), insets: listInsets, duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
var entries: [MediaGroupsGridAlbumEntry] = []
var index: Int = 0
for collection in item.collections {
let result = PHAsset.fetchAssets(in: collection, options: nil)
if let firstItem = result.firstObject {
let firstItem: PHAsset?
if collection.assetCollectionSubtype == .smartAlbumUserLibrary {
firstItem = result.lastObject
} else {
firstItem = result.firstObject
}
if let firstItem = firstItem {
entries.append(MediaGroupsGridAlbumEntry(theme: item.presentationData.theme, index: index, collection: collection, firstItem: firstItem, count: presentationStringsFormattedNumber(Int32(result.count))))
index += 1
}

View File

@ -84,6 +84,7 @@ final class MediaPickerGridItemNode: GridItemNode {
self.imageNode.clipsToBounds = true
self.imageNode.contentMode = .scaleAspectFill
self.imageNode.isLayerBacked = false
self.imageNode.animateFirstTransition = false
self.gradientNode = ASImageNode()
self.gradientNode.displaysAsynchronously = false

View File

@ -18,6 +18,8 @@ import AttachmentUI
import ContextUI
import WebSearchUI
let overflowInset: CGFloat = 70.0
final class MediaPickerInteraction {
let openMedia: (PHFetchResult<PHAsset>, Int, UIImage?) -> Void
let openSelectedMedia: (TGMediaSelectableItem, UIImage?) -> Void
@ -99,10 +101,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
public var legacyCompletion: (_ signals: [Any], _ silently: Bool, _ scheduleTime: Int32?) -> Void = { _, _, _ in }
public var requestAttachmentMenuExpansion: () -> Void = { }
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
public var cancelPanGesture: () -> Void = { }
var dismissAll: () -> Void = { }
private class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate {
enum DisplayMode {
case all
@ -166,6 +170,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
super.init()
if controller.collection != nil {
self.preloadPromise.set(false)
}
self.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.backgroundNode)
self.containerNode.addSubnode(self.gridNode)
@ -281,6 +289,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.gridNode.scrollView.alwaysBounceVertical = true
self.gridNode.scrollView.showsVerticalScrollIndicator = false
if self.controller?.collection != nil {
self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in
return point.x > 44.0 + overflowInset
}
}
if self.controller?.collection == nil {
let cameraView = TGAttachmentCameraView(forSelfPortrait: false)!
cameraView.clipsToBounds = true
@ -315,6 +329,9 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
strongSelf.controller?.interaction?.selectionState?.setItem(asset, selected: selected, animated: true, sender: nil)
}
}
if self.controller?.collection != nil {
self.selectionGesture?.sideInset = 44.0 + overflowInset
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
@ -481,8 +498,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
}, presentStickers: controller.presentStickers, presentSchedulePicker: controller.presentSchedulePicker, presentTimerPicker: controller.presentTimerPicker, getCaptionPanelView: controller.getCaptionPanelView, present: { [weak self] c, a in
self?.controller?.present(c, in: .window(.root), with: a)
}, finishedTransitionIn: {
self.openingMedia = false
}, finishedTransitionIn: { [weak self] in
self?.openingMedia = false
}, dismissAll: { [weak self] in
self?.controller?.dismissAll()
})
}
@ -512,8 +531,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
}, presentStickers: controller.presentStickers, presentSchedulePicker: controller.presentSchedulePicker, presentTimerPicker: controller.presentTimerPicker, getCaptionPanelView: controller.getCaptionPanelView, present: { [weak self] c, a in
self?.controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
}, finishedTransitionIn: {
self.openingMedia = false
}, finishedTransitionIn: { [weak self] in
self?.openingMedia = false
}, dismissAll: { [weak self] in
self?.controller?.dismissAll()
})
}
@ -611,13 +632,20 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private var previousContentOffset: GridNodeVisibleContentOffset?
func updateNavigation(transition: ContainedViewLayoutTransition) {
func updateNavigation(delayDisappear: Bool = false, transition: ContainedViewLayoutTransition) {
if let selectionNode = self.selectionNode, selectionNode.alpha > 0.0 {
self.controller?.navigationBar?.updateBackgroundAlpha(1.0, transition: .immediate)
self.controller?.updateTabBarAlpha(1.0, transition)
} else if self.placeholderNode != nil {
self.controller?.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate)
self.controller?.updateTabBarAlpha(0.0, transition)
if delayDisappear {
Queue.mainQueue().after(0.25) {
self.controller?.updateTabBarAlpha(0.0, transition)
}
} else {
self.controller?.updateTabBarAlpha(0.0, transition)
}
} else {
var previousContentOffsetValue: CGFloat?
if let previousContentOffset = self.previousContentOffset, case let .known(value) = previousContentOffset {
@ -637,6 +665,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
case .unknown, .none:
self.controller?.navigationBar?.updateBackgroundAlpha(1.0, transition: .immediate)
}
self.controller?.updateTabBarAlpha(1.0, transition)
}
let count = Int32(self.controller?.interaction?.selectionState?.count() ?? 0)
@ -652,7 +681,6 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
var insets = layout.insets(options: [])
insets.top += navigationBarHeight
let overflowInset: CGFloat = 70.0
let bounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: layout.size.height))
let innerBounds = CGRect(origin: CGPoint(x: -overflowInset, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))
@ -968,6 +996,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
}, selectionState: selectionContext ?? TGMediaSelectionContext(), editingState: editingContext ?? TGMediaEditingContext())
self.interaction?.selectionState?.grouping = true
self.updateSelectionState(count: Int32(selectionContext?.count() ?? 0))
}
required init(coder aDecoder: NSCoder) {
@ -1014,7 +1044,11 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
@objc private func backPressed() {
self.updateNavigationStack { current in
return current.filter { $0 !== self }
var mediaPickerContext: AttachmentMediaPickerContext?
if let first = current.first as? MediaPickerScreen {
mediaPickerContext = first.webSearchController?.mediaPickerContext ?? first.mediaPickerContext
}
return (current.filter { $0 !== self }, mediaPickerContext)
}
}
@ -1039,9 +1073,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
public func prepareForReuse() {
self.controllerNode.cameraView?.resumePreview()
Queue.mainQueue().after(0.2, {
self.controllerNode.updateNavigation(transition: .animated(duration: 0.15, curve: .easeInOut))
})
self.controllerNode.updateNavigation(delayDisappear: true, transition: .immediate)
}
@objc private func searchOrMorePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) {
@ -1051,20 +1083,31 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.presentWebSearch(MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, openGroup: { [weak self] collection in
if let strongSelf = self {
if let webSearchController = strongSelf.webSearchController {
strongSelf.webSearchController = nil
if collection.assetCollectionSubtype != .smartAlbumUserLibrary {
Queue.mainQueue().after(0.5) {
webSearchController.cancel()
}
// strongSelf.webSearchController = nil
// Queue.mainQueue().after(0.5) {
// webSearchController.cancel()
// }
} else {
strongSelf.webSearchController = nil
webSearchController.cancel()
}
}
if collection.assetCollectionSubtype != .smartAlbumUserLibrary {
let mediaPicker = MediaPickerScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, chatLocation: strongSelf.chatLocation, bannedSendMedia: strongSelf.bannedSendMedia, collection: collection, editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
mediaPicker.presentStickers = strongSelf.presentStickers
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
mediaPicker.getCaptionPanelView = strongSelf.getCaptionPanelView
mediaPicker.legacyCompletion = strongSelf.legacyCompletion
mediaPicker.dismissAll = { [weak self] in
self?.dismiss(animated: true, completion: nil)
}
mediaPicker._presentedInModal = true
mediaPicker.updateNavigationStack = strongSelf.updateNavigationStack
strongSelf.updateNavigationStack({ _ in return [strongSelf, mediaPicker]})
strongSelf.updateNavigationStack({ _ in return ([strongSelf, mediaPicker], strongSelf.mediaPickerContext)})
}
}
}))
@ -1205,6 +1248,8 @@ private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
private var initialLocation: CGPoint?
var sideInset: CGFloat = 0.0
init(target: Any?, action: Selector?, gridNode: GridNode) {
self.gridNode = gridNode
@ -1216,12 +1261,17 @@ private class MediaPickerGridSelectionGesture: UIPanGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
guard let touch = touches.first, let gridNode = self.gridNode else {
guard let touch = touches.first, self.numberOfTouches == 1, let gridNode = self.gridNode else {
return
}
let location = touch.location(in: gridNode.view)
self.initialLocation = location
if location.x > self.sideInset {
self.initialLocation = location
} else {
self.state = .failed
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {

View File

@ -189,7 +189,7 @@ public final class PermissionContentNode: ASDisplayNode {
public func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, insets)
let sidePadding: CGFloat
var sidePadding: CGFloat
let fontSize: CGFloat
if min(size.width, size.height) > 330.0 {
fontSize = 24.0
@ -198,8 +198,9 @@ public final class PermissionContentNode: ASDisplayNode {
fontSize = 20.0
sidePadding = 20.0
}
sidePadding += insets.left
let smallerSidePadding: CGFloat = 20.0
let smallerSidePadding: CGFloat = 20.0 + insets.left
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.bold(fontSize), textColor: self.theme.list.itemPrimaryTextColor)
@ -207,7 +208,7 @@ public final class PermissionContentNode: ASDisplayNode {
let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: size.width - smallerSidePadding * 2.0, height: .greatestFiniteMagnitude))
let textSize = self.textNode.updateLayout(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))
let buttonInset: CGFloat = 16.0
let buttonWidth = min(size.width, size.height) - buttonInset * 2.0
let buttonWidth = min(size.width, size.height) - buttonInset * 2.0 - insets.left - insets.right
let buttonHeight = self.actionButton.updateLayout(width: buttonWidth, transition: transition)
let footerSize = self.footerNode.updateLayout(CGSize(width: size.width - smallerSidePadding * 2.0, height: .greatestFiniteMagnitude))
let privacyButtonSize = self.privacyPolicyButton.measure(CGSize(width: size.width - sidePadding * 2.0, height: .greatestFiniteMagnitude))

View File

@ -165,10 +165,12 @@ private func attachmentFileControllerEntries(presentationData: PresentationData,
private class AttachmentFileControllerImpl: ItemListController, AttachmentContainable {
public var requestAttachmentMenuExpansion: () -> Void = {}
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
public var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
public var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
public var cancelPanGesture: () -> Void = { }
var delayDisappear = false
var resetForReuseImpl: () -> Void = {}
public func resetForReuse() {
self.resetForReuseImpl()
@ -176,7 +178,9 @@ private class AttachmentFileControllerImpl: ItemListController, AttachmentContai
}
public func prepareForReuse() {
self.delayDisappear = true
self.visibleBottomContentOffsetChanged?(self.visibleBottomContentOffset)
self.delayDisappear = false
}
}
@ -300,13 +304,21 @@ public func attachmentFileController(context: AccountContext, updatedPresentatio
}
let controller = AttachmentFileControllerImpl(context: context, state: signal)
controller.delayDisappear = true
controller.visibleBottomContentOffsetChanged = { [weak controller] offset in
switch offset {
case let .known(value):
let backgroundAlpha: CGFloat = min(30.0, value) / 30.0
controller?.updateTabBarAlpha(backgroundAlpha, .immediate)
let backgroundAlpha: CGFloat = min(30.0, max(0.0, value)) / 30.0
if backgroundAlpha.isZero && controller?.delayDisappear == true {
Queue.mainQueue().after(0.25, {
controller?.updateTabBarAlpha(backgroundAlpha, .animated(duration: 0.1, curve: .easeInOut))
})
} else {
controller?.updateTabBarAlpha(backgroundAlpha, .immediate)
}
case .unknown, .none:
controller?.updateTabBarAlpha(1.0, .immediate)
controller?.delayDisappear = false
}
}
controller.resetForReuseImpl = {

View File

@ -76,7 +76,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
}
var requestAttachmentMenuExpansion: () -> Void = {}
var updateNavigationStack: (@escaping ([AttachmentContainable]) -> [AttachmentContainable]) -> Void = { _ in }
var updateNavigationStack: (@escaping ([AttachmentContainable]) -> ([AttachmentContainable], AttachmentMediaPickerContext?)) -> Void = { _ in }
var updateTabBarAlpha: (CGFloat, ContainedViewLayoutTransition) -> Void = { _, _ in }
var cancelPanGesture: () -> Void = { }
@ -237,6 +237,8 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
}
self.displayNodeDidLoad()
self.updateTabBarAlpha(1.0, .immediate)
}
override func viewWillAppear(_ animated: Bool) {
@ -342,6 +344,10 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
public var mediaPickerContext: AttachmentMediaPickerContext {
return ContactsPickerContext(controller: self)
}
public func prepareForReuse() {
self.updateTabBarAlpha(1.0, .immediate)
}
}
private let searchBarFont = Font.regular(17.0)

View File

@ -496,7 +496,9 @@ class WebSearchControllerNode: ASDisplayNode {
insets.top += segmentedHeight
insets.bottom += toolbarHeight
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: layout.size, insets: insets, preloadSize: 400.0, type: gridNodeLayoutForContainerLayout(layout)), transition: .immediate), itemTransition: .immediate, stationaryItems: .none,updateFirstIndexInSectionOffset: nil), completion: { _ in })
let gridInsets = UIEdgeInsets(top: insets.top, left: layout.safeInsets.left, bottom: insets.bottom, right: layout.safeInsets.right)
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: layout.size, insets: gridInsets, preloadSize: 400.0, type: gridNodeLayoutForContainerLayout(layout)), transition: .immediate), itemTransition: .immediate, stationaryItems: .none,updateFirstIndexInSectionOffset: nil), completion: { _ in })
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)