Merge commit '78cc7c543a17a7806f0202516a65951f15f86dd0'

This commit is contained in:
Ali 2022-04-19 23:26:40 +04:00
commit 1e1cc3d487
16 changed files with 346 additions and 44 deletions

Binary file not shown.

Binary file not shown.

View File

@ -7520,3 +7520,6 @@ Sorry for the inconvenience.";
"Group.RequestToJoinSentDescriptionGroup" = "You will be able to send messages once the admins approve your request.";
"Channel.AdminLog.JoinedViaPublicRequest" = "%1$@ joined via public request, approved by %2$@";
"Share.UploadProgress" = "Uploading • %d%";
"Share.UploadDone" = "Done";

View File

@ -111,13 +111,13 @@ public final class MoreButtonNode: ASDisplayNode {
}
}
@objc private func buttonPressed() {
@objc public func buttonPressed() {
self.action?(self.contextSourceNode, nil)
if case .more = self.iconNode.iconState {
self.iconNode.play()
}
}
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
let animationSize = CGSize(width: 30.0, height: 30.0)
let inset: CGFloat = 0.0

View File

@ -542,6 +542,24 @@ public final class ChatMessageBubbleBackdrop: ASDisplayNode {
self.backgroundContent?.offsetSpring(value: value, duration: duration, damping: damping)
}
public func updateFrame(_ value: CGRect, animator: ControlledTransitionAnimator, completion: @escaping () -> Void = {}) {
if let maskView = self.maskView {
animator.updateFrame(layer: maskView.layer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: value.size.width, height: value.size.height)).insetBy(dx: -maskInset, dy: -maskInset), completion: nil)
}
if let backgroundContent = self.backgroundContent {
animator.updateFrame(layer: backgroundContent.layer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: value.size.width, height: value.size.height)), completion: nil)
if let (rect, containerSize) = self.absolutePosition {
var backgroundFrame = backgroundContent.frame
backgroundFrame.origin.x += rect.minX
backgroundFrame.origin.y += rect.minY
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .animated(duration: animator.duration, curve: .spring))
}
}
animator.updateFrame(layer: self.layer, frame: value, completion: { _ in
completion()
})
}
public func updateFrame(_ value: CGRect, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void = {}) {
if let maskView = self.maskView {
transition.updateFrame(view: maskView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: value.size.width, height: value.size.height)).insetBy(dx: -maskInset, dy: -maskInset))

View File

@ -113,6 +113,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private let chatLocation: ChatLocation?
private let bannedSendMedia: (Int32, Bool)?
private let collection: PHAssetCollection?
private let saveEditedPhotos: Bool
private let titleView: MediaPickerTitleView
private let moreButtonNode: MoreButtonNode
@ -687,7 +688,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
let proceed: (Bool) -> Void = { convertToJpeg in
guard let signals = TGMediaAssetsController.resultSignals(for: controller.interaction?.selectionState, editingContext: controller.interaction?.editingState, intent: asFile ? TGMediaAssetsControllerSendFileIntent : TGMediaAssetsControllerSendMediaIntent, currentItem: nil, storeAssets: true, convertToJpeg: convertToJpeg, descriptionGenerator: legacyAssetPickerItemGenerator(), saveEditedPhotos: true) else {
guard let signals = TGMediaAssetsController.resultSignals(for: controller.interaction?.selectionState, editingContext: controller.interaction?.editingState, intent: asFile ? TGMediaAssetsControllerSendFileIntent : TGMediaAssetsControllerSendMediaIntent, currentItem: nil, storeAssets: true, convertToJpeg: convertToJpeg, descriptionGenerator: legacyAssetPickerItemGenerator(), saveEditedPhotos: controller.saveEditedPhotos) else {
return
}
controller.completed = true
@ -1066,7 +1067,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private var isDismissing = false
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peer: EnginePeer?, chatLocation: ChatLocation?, bannedSendMedia: (Int32, Bool)?, collection: PHAssetCollection? = nil, editingContext: TGMediaEditingContext? = nil, selectionContext: TGMediaSelectionContext? = nil) {
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peer: EnginePeer?, chatLocation: ChatLocation?, bannedSendMedia: (Int32, Bool)?, collection: PHAssetCollection? = nil, editingContext: TGMediaEditingContext? = nil, selectionContext: TGMediaSelectionContext? = nil, saveEditedPhotos: Bool = false) {
self.context = context
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
@ -1076,6 +1077,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.chatLocation = chatLocation
self.bannedSendMedia = bannedSendMedia
self.collection = collection
self.saveEditedPhotos = saveEditedPhotos
self.titleView = MediaPickerTitleView(theme: self.presentationData.theme, segments: [self.presentationData.strings.Attachment_AllMedia, self.presentationData.strings.Attachment_SelectedMedia(1)], selectedIndex: 0)
self.titleView.title = collection?.localizedTitle ?? presentationData.strings.Attachment_Gallery
@ -1339,7 +1341,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
@objc private func rightButtonPressed() {
self.moreButtonNode.action?(self.moreButtonNode.contextSourceNode, nil)
self.moreButtonNode.buttonPressed()
}
public func resetForReuse() {

View File

@ -583,7 +583,9 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
let scrubbingTimestampValue = strongSelf.scrubbingTimestampValue
strongSelf.scrubbingTimestampValue = nil
strongSelf._scrubbingTimestamp.set(.single(nil))
strongSelf._scrubbingPosition.set(.single(nil))
Queue.mainQueue().after(0.01, {
strongSelf._scrubbingPosition.set(.single(nil))
})
if let scrubbingTimestampValue = scrubbingTimestampValue, apply {
if let statusValue = strongSelf.statusValue {
switch statusValue.status {

View File

@ -1085,7 +1085,7 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode, ActionSheetGr
let descriptionTextSize = self.descriptionTextNode.updateLayout(CGSize(width: size.width - inset * 3.0, height: size.height))
var descriptionTextFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - descriptionTextSize.width) / 2.0), y: progressFrame.minY - spacing - 9.0 - descriptionTextSize.height), size: descriptionTextSize)
self.progressTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ClearCache_Progress(Int(progress * 100.0)).string, font: Font.with(size: 17.0, design: .regular, weight: .bold, traits: [.monospacedNumbers]), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
self.progressTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ClearCache_Progress(Int(progress * 100.0)).string, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
let progressTextSize = self.progressTextNode.updateLayout(size)
var progressTextFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - progressTextSize.width) / 2.0), y: descriptionTextFrame.minY - spacing - progressTextSize.height), size: progressTextSize)

View File

@ -32,6 +32,8 @@ swift_library(
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
"//submodules/ShimmerEffect:ShimmerEffect",
"//submodules/ContextUI:ContextUI",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
],
visibility = [
"//visibility:public",

View File

@ -457,7 +457,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
if contentNode is ShareSearchContainerNode {
self.setActionNodesHidden(true, inputField: true, actions: true)
} else if !(contentNode is ShareLoadingContainerNode) {
} else if !(contentNode is ShareLoadingContainer) {
self.setActionNodesHidden(false, inputField: !self.controllerInteraction!.selectedPeers.isEmpty || self.presetText != nil, actions: true)
}
} else {
@ -649,7 +649,12 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
let timestamp = CACurrentMediaTime()
let doneImpl: (Bool) -> Void = { [weak self] shouldDelay in
let minDelay: Double = shouldDelay ? 0.9 : 0.6
let delay = max(minDelay, (timestamp + minDelay) - CACurrentMediaTime())
let delay: Double
if let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareProlongedLoadingContainerNode {
delay = contentNode.completionDuration
} else {
delay = max(minDelay, (timestamp + minDelay) - CACurrentMediaTime())
}
Queue.mainQueue().after(delay, {
self?.animateOut(shared: true, completion: {
self?.dismiss?(true)
@ -658,7 +663,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
})
}
if self.fromForeignApp {
self.transitionToContentNode(ShareLoadingContainerNode(theme: self.presentationData.theme, forceNativeAppearance: true), fastOut: true)
self.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: self.presentationData.theme, strings: self.presentationData.strings, forceNativeAppearance: true), fastOut: true)
} else {
self.animateOut(shared: true, completion: {
})
@ -683,7 +688,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
return
}
guard let contentNode = strongSelf.contentNode as? ShareLoadingContainerNode else {
guard let contentNode = strongSelf.contentNode as? ShareLoadingContainer else {
return
}
@ -988,7 +993,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
transition.updateAlpha(node: self.actionSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.actionsBackgroundNode, alpha: 0.0)
self.transitionToContentNode(ShareLoadingContainerNode(theme: self.presentationData.theme, forceNativeAppearance: true), fastOut: true)
self.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: self.presentationData.theme, strings: self.presentationData.strings, forceNativeAppearance: true), fastOut: true)
let timestamp = CACurrentMediaTime()
self.shareDisposable.set(signal.start(completed: { [weak self] in
let minDelay = 0.6
@ -1041,14 +1046,14 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
}
self.shareDisposable.set((signal
|> deliverOnMainQueue).start(next: { [weak self] status in
guard let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareLoadingContainerNode else {
guard let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareLoadingContainer else {
return
}
if let status = status {
contentNode.state = .progress(status)
}
}, completed: { [weak self] in
guard let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareLoadingContainerNode else {
guard let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareLoadingContainer else {
return
}
contentNode.state = .done

View File

@ -1,11 +1,14 @@
import Foundation
import UIKit
import AsyncDisplayKit
import SwiftSignalKit
import Display
import Postbox
import TelegramPresentationData
import ActivityIndicator
import RadialStatusNode
import AnimatedStickerNode
import TelegramAnimatedStickerNode
public enum ShareLoadingState {
case preparing
@ -13,7 +16,11 @@ public enum ShareLoadingState {
case done
}
public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContainerNode {
protocol ShareLoadingContainer: ASDisplayNode {
var state: ShareLoadingState { get set }
}
public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer {
private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme
@ -83,3 +90,229 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
public func updateSelectedPeers() {
}
}
public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer {
private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme
private let strings: PresentationStrings
private let animationNode: AnimatedStickerNode
private let doneAnimationNode: AnimatedStickerNode
private let progressTextNode: ImmediateTextNode
private let progressBackgroundNode: ASDisplayNode
private let progressForegroundNode: ASDisplayNode
private let animationStatusDisposable = MetaDisposable()
private var progressValue: CGFloat = 0.0
private var randomCompletionStart: CGFloat = .random(in: 0.94...0.97)
private var completionProgress: Double = 0.0
private var isDone: Bool = false
private var startTimestamp: Double?
public var state: ShareLoadingState = .preparing {
didSet {
switch self.state {
case .preparing:
break
case let .progress(value):
let currentTimestamp = CACurrentMediaTime()
if self.startTimestamp == nil {
self.startTimestamp = currentTimestamp
} else if let startTimestamp = self.startTimestamp, currentTimestamp - startTimestamp < 1.0, value > 0.5 && value < 0.9 {
self.randomCompletionStart = 0.8
}
if let (size, isLandscape, bottomInset) = self.validLayout {
self.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.3, curve: .easeInOut))
}
case .done:
if let (size, isLandscape, bottomInset) = self.validLayout {
self.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut))
}
self.animationNode.stopAtNearestLoop = true
self.animationNode.completed = { [weak self] _ in
if let strongSelf = self {
strongSelf.animationNode.visibility = false
strongSelf.doneAnimationNode.visibility = true
strongSelf.doneAnimationNode.isHidden = false
}
}
self.animationNode.frameUpdated = { [weak self] index, total in
if let strongSelf = self {
let progress = min(1.0, CGFloat(index) / CGFloat(total))
if abs(progress - strongSelf.completionProgress) >= 0.05 || progress == 1.0 {
strongSelf.completionProgress = 0.5 * progress
if let (size, isLandscape, bottomInset) = strongSelf.validLayout {
strongSelf.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut))
}
}
}
}
self.doneAnimationNode.frameUpdated = { [weak self] index, total in
if let strongSelf = self {
let progress = 0.5 + min(1.0, CGFloat(index) / CGFloat(total) * 2.1) * 0.5
if abs(progress - strongSelf.completionProgress) >= 0.05 || progress == 1.0 {
strongSelf.completionProgress = progress
if progress == 1.0, !strongSelf.isDone {
strongSelf.isDone = true
if let snapshotView = strongSelf.progressTextNode.view.snapshotContentTree() {
snapshotView.frame = strongSelf.progressTextNode.frame
strongSelf.view.addSubview(snapshotView)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -20.0), duration: 0.25, removeOnCompletion: false, additive: true)
strongSelf.progressTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
strongSelf.progressTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: 20.0), to: CGPoint(), duration: 0.25, additive: true)
}
}
if let (size, isLandscape, bottomInset) = strongSelf.validLayout {
strongSelf.updateLayout(size: size, isLandscape: isLandscape, bottomInset: bottomInset, transition: .animated(duration: 0.2, curve: .easeInOut))
}
}
}
}
self.doneAnimationNode.started = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.animationNode.isHidden = true
}
}
}
}
private var elapsedTime: Double = 0.0
public var completionDuration: Double {
return self.elapsedTime + 3.0 + 0.15
}
public init(theme: PresentationTheme, strings: PresentationStrings, forceNativeAppearance: Bool) {
self.theme = theme
self.strings = strings
self.animationNode = AnimatedStickerNode()
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareProgress"), width: 256, height: 256, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
self.animationNode.visibility = true
self.doneAnimationNode = AnimatedStickerNode()
self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "ShareDone"), width: 256, height: 256, playbackMode: .once, mode: .direct(cachePathPrefix: nil))
self.doneAnimationNode.visibility = false
self.doneAnimationNode.isHidden = true
self.progressTextNode = ImmediateTextNode()
self.progressTextNode.textAlignment = .center
self.progressBackgroundNode = ASDisplayNode()
self.progressBackgroundNode.backgroundColor = theme.actionSheet.controlAccentColor.withMultipliedAlpha(0.2)
self.progressBackgroundNode.cornerRadius = 3.0
self.progressForegroundNode = ASDisplayNode()
self.progressForegroundNode.backgroundColor = theme.actionSheet.controlAccentColor
self.progressForegroundNode.cornerRadius = 3.0
super.init()
self.addSubnode(self.animationNode)
self.addSubnode(self.doneAnimationNode)
self.addSubnode(self.progressTextNode)
self.addSubnode(self.progressBackgroundNode)
self.addSubnode(self.progressForegroundNode)
self.animationStatusDisposable.set((self.animationNode.status
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {
strongSelf.elapsedTime = status.duration - status.timestamp
}
}))
}
deinit {
self.animationStatusDisposable.dispose()
}
public func activate() {
}
public func deactivate() {
}
public func setEnsurePeerVisibleOnLayout(_ peerId: PeerId?) {
}
public func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) {
self.contentOffsetUpdated = f
}
private var validLayout: (CGSize, Bool, CGFloat)?
public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, isLandscape, bottomInset)
let nodeHeight: CGFloat = 400.0
let inset: CGFloat = 24.0
let progressHeight: CGFloat = 6.0
let spacing: CGFloat = 16.0
var progress: CGFloat
switch self.state {
case .preparing:
progress = 0.0
case let .progress(value):
progress = CGFloat(value) * self.randomCompletionStart
case .done:
progress = self.randomCompletionStart + (1.0 - self.randomCompletionStart) * self.completionProgress
}
self.progressValue = max(self.progressValue, progress)
progress = self.progressValue
let progressFrame = CGRect(x: inset, y: size.height - inset - progressHeight, width: size.width - inset * 2.0, height: progressHeight)
self.progressBackgroundNode.frame = progressFrame
let progressForegroundFrame = CGRect(x: progressFrame.minX, y: progressFrame.minY, width: floorToScreenPixels(progressFrame.width * progress), height: progressHeight)
if !self.progressForegroundNode.frame.width.isZero {
transition.updateFrame(node: self.progressForegroundNode, frame: progressForegroundFrame)
} else {
self.progressForegroundNode.frame = progressForegroundFrame
}
let progressText: String
if self.isDone {
progressText = self.strings.Share_UploadDone
} else {
progressText = self.strings.Share_UploadProgress(Int(progress * 100.0)).string
}
self.progressTextNode.attributedText = NSAttributedString(string: progressText, font: Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.theme.actionSheet.primaryTextColor)
let progressTextSize = self.progressTextNode.updateLayout(size)
let progressTextFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - progressTextSize.width) / 2.0), y: progressFrame.minY - spacing - 9.0 - progressTextSize.height), size: progressTextSize)
self.progressTextNode.frame = progressTextFrame
let imageSide: CGFloat = 160.0
let imageSize = CGSize(width: imageSide, height: imageSide)
let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: (progressTextFrame.minY - imageSize.height - 20.0)), size: imageSize)
self.animationNode.frame = animationFrame
self.animationNode.updateLayout(size: imageSize)
self.doneAnimationNode.frame = animationFrame
self.doneAnimationNode.updateLayout(size: imageSize)
self.contentOffsetUpdated?(-size.height + nodeHeight * 0.5, transition)
}
public func updateSelectedPeers() {
}
}

View File

@ -10703,13 +10703,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else {
buttons = .single((availableButtons, .gallery))
}
let dataSettings = self.context.sharedContext.accountManager.transaction { transaction -> GeneratedMediaStoreSettings in
let entry = transaction.getSharedData(ApplicationSpecificSharedDataKeys.generatedMediaStoreSettings)?.get(GeneratedMediaStoreSettings.self)
return entry ?? GeneratedMediaStoreSettings.defaultSettings
}
let _ = (buttons
|> deliverOnMainQueue).start(next: { [weak self] buttons, initialButton in
let _ = combineLatest(queue: Queue.mainQueue(), buttons, dataSettings).start(next: { [weak self] buttonsAndInitialButton, dataSettings in
guard let strongSelf = self else {
return
}
let (buttons, initialButton) = buttonsAndInitialButton
guard let initialButton = initialButton else {
if let botId = botId {
let _ = (context.engine.messages.getAttachMenuBot(botId: botId)
@ -10751,7 +10757,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
controller.prepareForReuse()
return
}
strongSelf.presentMediaPicker(bannedSendMedia: bannedSendMedia, present: { controller, mediaPickerContext in
strongSelf.presentMediaPicker(saveEditedPhotos: dataSettings.storeEditedPhotos, bannedSendMedia: bannedSendMedia, present: { controller, mediaPickerContext in
let _ = currentMediaController.swap(controller)
if !inputText.string.isEmpty {
mediaPickerContext?.setCaption(inputText)
@ -11435,11 +11441,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.present(actionSheet, in: .window(.root))
}
private func presentMediaPicker(bannedSendMedia: (Int32, Bool)?, present: @escaping (MediaPickerScreen, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void) {
private func presentMediaPicker(saveEditedPhotos: Bool, bannedSendMedia: (Int32, Bool)?, present: @escaping (MediaPickerScreen, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void) {
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return
}
let controller = MediaPickerScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), chatLocation: self.chatLocation, bannedSendMedia: bannedSendMedia)
let controller = MediaPickerScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), chatLocation: self.chatLocation, bannedSendMedia: bannedSendMedia, saveEditedPhotos: saveEditedPhotos)
let mediaPickerContext = controller.mediaPickerContext
controller.openCamera = { [weak self] cameraView in
self?.openCamera(cameraView: cameraView)

View File

@ -2764,31 +2764,37 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
shareButtonNode.removeFromSupernode()
}
if case .System = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ {
if case let .System(duration, _) = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ {
if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) {
animation.animator.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true
animation.animator.updateBounds(layer: strongSelf.clippingNode.layer, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size), completion: { [weak strongSelf] _ in
let _ = strongSelf
//strongSelf?.clippingNode.clipsToBounds = false
})
if useDisplayLinkAnimations {
let backgroundAnimation = ListViewAnimation(from: strongSelf.backgroundNode.frame, to: backgroundFrame, duration: duration * UIView.animationDurationFactor(), curve: strongSelf.preferredAnimationCurve, beginAt: beginAt, update: { [weak strongSelf] _, frame in
if let strongSelf = strongSelf {
strongSelf.backgroundNode.frame = frame
strongSelf.clippingNode.position = CGPoint(x: frame.midX, y: frame.midY)
strongSelf.clippingNode.bounds = CGRect(origin: CGPoint(x: frame.minX, y: frame.minY), size: frame.size)
strongSelf.backgroundNode.updateLayout(size: frame.size, transition: .immediate)
strongSelf.backgroundWallpaperNode.updateFrame(frame, transition: .immediate)
strongSelf.shadowNode.updateLayout(backgroundFrame: frame, transition: .immediate)
}
})
strongSelf.setAnimationForKey("backgroundNodeFrame", animation: backgroundAnimation)
} else {
animation.animator.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true
animation.animator.updateBounds(layer: strongSelf.clippingNode.layer, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size), completion: { [weak strongSelf] _ in
let _ = strongSelf
//strongSelf?.clippingNode.clipsToBounds = false
})
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: animation)
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: animation.transition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: animation.transition)
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: animation)
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: animation.transition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: animation.transition)
}
if let _ = strongSelf.backgroundNode.type {
/*var incomingOffset: CGFloat = 0.0
switch type {
case .incoming:
incomingOffset = 5.0
default:
break
}*/
//strongSelf.mainContextSourceNode.contentRect = backgroundFrame.offsetBy(dx: incomingOffset, dy: 0.0)
//strongSelf.mainContainerNode.targetNodeForActivationProgressContentRect = strongSelf.mainContextSourceNode.contentRect
if !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)

View File

@ -1984,6 +1984,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let subtitleNodeRawContainer: ASDisplayNode
let subtitleNode: MultiScaleTextNode
let panelSubtitleNode: MultiScaleTextNode
let nextPanelSubtitleNode: MultiScaleTextNode
let usernameNodeContainer: ASDisplayNode
let usernameNodeRawContainer: ASDisplayNode
let usernameNode: MultiScaleTextNode
@ -2045,6 +2046,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.panelSubtitleNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
self.panelSubtitleNode.displaysAsynchronously = false
self.nextPanelSubtitleNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
self.nextPanelSubtitleNode.displaysAsynchronously = false
self.usernameNodeContainer = ASDisplayNode()
self.usernameNodeRawContainer = ASDisplayNode()
self.usernameNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
@ -2101,6 +2105,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.titleNodeContainer.addSubnode(self.titleNode)
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
self.subtitleNodeContainer.addSubnode(self.panelSubtitleNode)
// self.subtitleNodeContainer.addSubnode(self.nextPanelSubtitleNode)
self.usernameNodeContainer.addSubnode(self.usernameNode)
self.regularContentNode.addSubnode(self.avatarListNode)
@ -2367,6 +2372,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let smallSubtitleString: NSAttributedString
let subtitleString: NSAttributedString
var panelSubtitleString: NSAttributedString?
var nextPanelSubtitleString: NSAttributedString?
let usernameString: NSAttributedString
if let peer = peer {
isVerified = peer.isVerified
@ -2415,7 +2421,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(17.0), textColor: subtitleColor)
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
let (maybePanelStatusData, _, _) = panelStatusData
let (maybePanelStatusData, maybeNextPanelStatusData, _) = panelStatusData
if let panelStatusData = maybePanelStatusData {
let subtitleColor: UIColor
if panelStatusData.isActivity {
@ -2425,6 +2431,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
panelSubtitleString = NSAttributedString(string: panelStatusData.text, font: Font.regular(17.0), textColor: subtitleColor)
}
if let nextPanelStatusData = maybeNextPanelStatusData {
nextPanelSubtitleString = NSAttributedString(string: nextPanelStatusData.text, font: Font.regular(17.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
}
} else {
subtitleString = NSAttributedString(string: " ", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
smallSubtitleString = subtitleString
@ -2477,6 +2486,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
], mainState: TitleNodeStateRegular)
self.panelSubtitleNode.accessibilityLabel = (panelSubtitleString ?? subtitleString).string
let nextPanelSubtitleNodeLayout = self.nextPanelSubtitleNode.updateLayout(states: [
TitleNodeStateRegular: MultiScaleTextState(attributedText: nextPanelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize),
TitleNodeStateExpanded: MultiScaleTextState(attributedText: nextPanelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize)
], mainState: TitleNodeStateRegular)
if let _ = nextPanelSubtitleString {
self.nextPanelSubtitleNode.isHidden = false
}
let usernameNodeLayout = self.usernameNode.updateLayout(states: [
TitleNodeStateRegular: MultiScaleTextState(attributedText: usernameString, constrainedSize: CGSize(width: titleConstrainedSize.width, height: titleConstrainedSize.height)),
TitleNodeStateExpanded: MultiScaleTextState(attributedText: usernameString, constrainedSize: CGSize(width: width - titleNodeLayout[TitleNodeStateExpanded]!.size.width - 8.0, height: titleConstrainedSize.height))
@ -2490,6 +2507,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let titleExpandedSize = titleNodeLayout[TitleNodeStateExpanded]!.size
let subtitleSize = subtitleNodeLayout[TitleNodeStateRegular]!.size
let _ = panelSubtitleNodeLayout[TitleNodeStateRegular]!.size
let _ = nextPanelSubtitleNodeLayout[TitleNodeStateRegular]!.size
let usernameSize = usernameNodeLayout[TitleNodeStateRegular]!.size
if let image = self.titleCredibilityIconNode.image {
@ -2596,6 +2614,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
], alpha: panelSubtitleAlpha, transition: transition)
self.nextPanelSubtitleNode.update(stateFractions: [
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
], alpha: panelSubtitleAlpha, transition: transition)
self.usernameNode.update(stateFractions: [
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
@ -2747,6 +2770,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: CGRect(origin: rawSubtitleFrame.center, size: CGSize()))
transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: subtitleOffset), size: CGSize()))
transition.updateFrame(node: self.panelSubtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelSubtitleOffset), size: CGSize()))
transition.updateFrame(node: self.nextPanelSubtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelSubtitleOffset), size: CGSize()))
transition.updateFrame(node: self.usernameNode, frame: CGRect(origin: CGPoint(), size: CGSize()))
transition.updateSublayerTransformScale(node: self.titleNodeContainer, scale: titleScale)
transition.updateSublayerTransformScale(node: self.subtitleNodeContainer, scale: subtitleScale)
@ -2789,6 +2813,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: subtitleOffset), size: CGSize()))
transition.updateFrame(node: self.panelSubtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelSubtitleOffset), size: CGSize()))
transition.updateFrame(node: self.nextPanelSubtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelSubtitleOffset), size: CGSize()))
transition.updateFrame(node: self.usernameNode, frame: CGRect(origin: CGPoint(), size: CGSize()))
transition.updateSublayerTransformScaleAdditive(node: self.titleNodeContainer, scale: titleScale)
transition.updateSublayerTransformScaleAdditive(node: self.subtitleNodeContainer, scale: subtitleScale)

View File

@ -146,7 +146,7 @@ public func canTranslateText(context: AccountContext, text: String, showTranslat
return (false, nil)
}
if #available(iOS 15.0, *) {
if #available(iOS 12.0, *) {
var dontTranslateLanguages: [String] = []
if let ignoredLanguages = ignoredLanguages {
dontTranslateLanguages = ignoredLanguages

View File

@ -624,7 +624,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
}
@objc private func moreButtonPressed() {
self.moreButtonNode.action?(self.moreButtonNode.contextSourceNode, nil)
self.moreButtonNode.buttonPressed()
}
@objc private func morePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) {