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."; "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$@"; "Channel.AdminLog.JoinedViaPublicRequest" = "%1$@ joined via public request, approved by %2$@";
"Share.UploadProgress" = "Uploading • %d%";
"Share.UploadDone" = "Done";

View File

@ -111,7 +111,7 @@ public final class MoreButtonNode: ASDisplayNode {
} }
} }
@objc private func buttonPressed() { @objc public func buttonPressed() {
self.action?(self.contextSourceNode, nil) self.action?(self.contextSourceNode, nil)
if case .more = self.iconNode.iconState { if case .more = self.iconNode.iconState {
self.iconNode.play() self.iconNode.play()

View File

@ -542,6 +542,24 @@ public final class ChatMessageBubbleBackdrop: ASDisplayNode {
self.backgroundContent?.offsetSpring(value: value, duration: duration, damping: damping) 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 = {}) { public func updateFrame(_ value: CGRect, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void = {}) {
if let maskView = self.maskView { 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)) 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 chatLocation: ChatLocation?
private let bannedSendMedia: (Int32, Bool)? private let bannedSendMedia: (Int32, Bool)?
private let collection: PHAssetCollection? private let collection: PHAssetCollection?
private let saveEditedPhotos: Bool
private let titleView: MediaPickerTitleView private let titleView: MediaPickerTitleView
private let moreButtonNode: MoreButtonNode private let moreButtonNode: MoreButtonNode
@ -687,7 +688,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
} }
let proceed: (Bool) -> Void = { convertToJpeg in 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 return
} }
controller.completed = true controller.completed = true
@ -1066,7 +1067,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private var isDismissing = false 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 self.context = context
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
@ -1076,6 +1077,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.chatLocation = chatLocation self.chatLocation = chatLocation
self.bannedSendMedia = bannedSendMedia self.bannedSendMedia = bannedSendMedia
self.collection = collection 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 = 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 self.titleView.title = collection?.localizedTitle ?? presentationData.strings.Attachment_Gallery
@ -1339,7 +1341,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
} }
@objc private func rightButtonPressed() { @objc private func rightButtonPressed() {
self.moreButtonNode.action?(self.moreButtonNode.contextSourceNode, nil) self.moreButtonNode.buttonPressed()
} }
public func resetForReuse() { public func resetForReuse() {

View File

@ -583,7 +583,9 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
let scrubbingTimestampValue = strongSelf.scrubbingTimestampValue let scrubbingTimestampValue = strongSelf.scrubbingTimestampValue
strongSelf.scrubbingTimestampValue = nil strongSelf.scrubbingTimestampValue = nil
strongSelf._scrubbingTimestamp.set(.single(nil)) strongSelf._scrubbingTimestamp.set(.single(nil))
Queue.mainQueue().after(0.01, {
strongSelf._scrubbingPosition.set(.single(nil)) strongSelf._scrubbingPosition.set(.single(nil))
})
if let scrubbingTimestampValue = scrubbingTimestampValue, apply { if let scrubbingTimestampValue = scrubbingTimestampValue, apply {
if let statusValue = strongSelf.statusValue { if let statusValue = strongSelf.statusValue {
switch statusValue.status { 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)) 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) 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) 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) 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/WallpaperBackgroundNode:WallpaperBackgroundNode",
"//submodules/ShimmerEffect:ShimmerEffect", "//submodules/ShimmerEffect:ShimmerEffect",
"//submodules/ContextUI:ContextUI", "//submodules/ContextUI:ContextUI",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

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

View File

@ -1,11 +1,14 @@
import Foundation import Foundation
import UIKit import UIKit
import AsyncDisplayKit import AsyncDisplayKit
import SwiftSignalKit
import Display import Display
import Postbox import Postbox
import TelegramPresentationData import TelegramPresentationData
import ActivityIndicator import ActivityIndicator
import RadialStatusNode import RadialStatusNode
import AnimatedStickerNode
import TelegramAnimatedStickerNode
public enum ShareLoadingState { public enum ShareLoadingState {
case preparing case preparing
@ -13,7 +16,11 @@ public enum ShareLoadingState {
case done 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 var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme private let theme: PresentationTheme
@ -83,3 +90,229 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
public func updateSelectedPeers() { 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

@ -10704,12 +10704,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
buttons = .single((availableButtons, .gallery)) buttons = .single((availableButtons, .gallery))
} }
let _ = (buttons let dataSettings = self.context.sharedContext.accountManager.transaction { transaction -> GeneratedMediaStoreSettings in
|> deliverOnMainQueue).start(next: { [weak self] buttons, initialButton in let entry = transaction.getSharedData(ApplicationSpecificSharedDataKeys.generatedMediaStoreSettings)?.get(GeneratedMediaStoreSettings.self)
return entry ?? GeneratedMediaStoreSettings.defaultSettings
}
let _ = combineLatest(queue: Queue.mainQueue(), buttons, dataSettings).start(next: { [weak self] buttonsAndInitialButton, dataSettings in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let (buttons, initialButton) = buttonsAndInitialButton
guard let initialButton = initialButton else { guard let initialButton = initialButton else {
if let botId = botId { if let botId = botId {
let _ = (context.engine.messages.getAttachMenuBot(botId: botId) let _ = (context.engine.messages.getAttachMenuBot(botId: botId)
@ -10751,7 +10757,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
controller.prepareForReuse() controller.prepareForReuse()
return return
} }
strongSelf.presentMediaPicker(bannedSendMedia: bannedSendMedia, present: { controller, mediaPickerContext in strongSelf.presentMediaPicker(saveEditedPhotos: dataSettings.storeEditedPhotos, bannedSendMedia: bannedSendMedia, present: { controller, mediaPickerContext in
let _ = currentMediaController.swap(controller) let _ = currentMediaController.swap(controller)
if !inputText.string.isEmpty { if !inputText.string.isEmpty {
mediaPickerContext?.setCaption(inputText) mediaPickerContext?.setCaption(inputText)
@ -11435,11 +11441,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.present(actionSheet, in: .window(.root)) 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 { guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return 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 let mediaPickerContext = controller.mediaPickerContext
controller.openCamera = { [weak self] cameraView in controller.openCamera = { [weak self] cameraView in
self?.openCamera(cameraView: cameraView) self?.openCamera(cameraView: cameraView)

View File

@ -2764,8 +2764,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
shareButtonNode.removeFromSupernode() shareButtonNode.removeFromSupernode()
} }
if case .System = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ { if case let .System(duration, _) = animation/*, !strongSelf.mainContextSourceNode.isExtractedToContextPreview*/ {
if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) { if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) {
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.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil) animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true strongSelf.clippingNode.clipsToBounds = true
@ -2778,17 +2792,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil) animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: animation.transition) strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: animation.transition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: animation.transition) strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: animation.transition)
}
if let _ = strongSelf.backgroundNode.type { 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 !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if let (rect, size) = strongSelf.absoluteRect { if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size) strongSelf.updateAbsoluteRect(rect, within: size)

View File

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

View File

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

View File

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