Various improvements

This commit is contained in:
Ilya Laktyushin 2023-09-05 16:56:48 +04:00
parent 04ca831081
commit 266f9e5ad8
12 changed files with 187 additions and 60 deletions

View File

@ -46,6 +46,7 @@ swift_library(
"//submodules/TelegramUI/Components/AnimationCache:AnimationCache",
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
"//submodules/TelegramUI/Components/SliderContextItem:SliderContextItem",
"//submodules/TooltipUI",
],
visibility = [
"//visibility:public",

View File

@ -11,6 +11,7 @@ import RadialStatusNode
import ScreenCaptureDetection
import AppBundle
import LocalizedPeerData
import TooltipUI
private func galleryMediaForMedia(media: Media) -> Media? {
if let media = media as? TelegramMediaImage {
@ -57,23 +58,54 @@ private final class SecretMediaPreviewControllerNode: GalleryControllerNode {
private var timeoutNode: RadialStatusNode?
private var validLayout: (ContainerViewLayout, CGFloat)?
var beginTimeAndTimeout: (Double, Double)? {
didSet {
if let (beginTime, timeout) = self.beginTimeAndTimeout, Int32(timeout) != viewOnceTimeout {
if let (beginTime, timeout) = self.beginTimeAndTimeout {
var beginTime = beginTime
if self.timeoutNode == nil {
let timeoutNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.5))
self.timeoutNode = timeoutNode
var iconImage: UIImage?
if let image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/SecretMediaIcon"), color: .white) {
let factor: CGFloat = 0.48
iconImage = generateImage(CGSize(width: floor(image.size.width * factor), height: floor(image.size.height * factor)), contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: size))
})
let icon: RadialStatusNodeState.SecretTimeoutIcon
let timeoutValue = Int32(timeout)
if timeoutValue == viewOnceTimeout || "".isEmpty {
beginTime = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
if let image = generateImage(CGSize(width: 28.0, height: 28.0), rotatedContext: { size, context in
let bounds = CGRect(origin: .zero, size: size)
context.clear(bounds)
let string = "1"
let attributedString = NSAttributedString(string: string, attributes: [NSAttributedString.Key.font: Font.with(size: 14.0, design: .round), NSAttributedString.Key.foregroundColor: UIColor.white])
let line = CTLineCreateWithAttributedString(attributedString)
let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds)
let lineOffset = CGPoint(x: -1.0, y: 0.0)
let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (bounds.size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (bounds.size.height - lineBounds.size.height) / 2.0))
context.translateBy(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0)
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0)
context.translateBy(x: lineOrigin.x, y: lineOrigin.y)
CTLineDraw(line, context)
context.translateBy(x: -lineOrigin.x, y: -lineOrigin.y)
}) {
icon = .image(image)
} else {
icon = .flame
}
} else {
icon = .flame
}
timeoutNode.transitionToState(.secretTimeout(color: .white, icon: iconImage, beginTime: beginTime, timeout: timeout, sparks: true), completion: {})
timeoutNode.transitionToState(.secretTimeout(color: .white, icon: icon, beginTime: beginTime, timeout: timeout, sparks: true), completion: {})
self.addSubnode(timeoutNode)
timeoutNode.addTarget(self, action: #selector(self.statusTapGesture), forControlEvents: .touchUpInside)
// let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.statusTapGesture))
// timeoutNode.view.addGestureRecognizer(tapGesture)
if let (layout, navigationHeight) = self.validLayout {
self.layoutTimeoutNode(layout, navigationBarHeight: navigationHeight, transition: .immediate)
@ -86,6 +118,13 @@ private final class SecretMediaPreviewControllerNode: GalleryControllerNode {
}
}
var statusPressed: (UIView) -> Void = { _ in }
@objc private func statusTapGesture() {
if let sourceView = self.timeoutNode?.view {
self.statusPressed(sourceView)
}
}
override func animateIn(animateContent: Bool, useSimpleAnimation: Bool) {
super.animateIn(animateContent: animateContent, useSimpleAnimation: useSimpleAnimation)
@ -149,6 +188,8 @@ public final class SecretMediaPreviewController: ViewController {
private var screenCaptureEventsDisposable: Disposable?
private weak var tooltipController: TooltipScreen?
public init(context: AccountContext, messageId: MessageId) {
self.context = context
self.messageId = messageId
@ -214,6 +255,12 @@ public final class SecretMediaPreviewController: ViewController {
self.displayNode = SecretMediaPreviewControllerNode(controllerInteraction: controllerInteraction)
self.displayNodeDidLoad()
self.controllerNode.statusPressed = { [weak self] sourceView in
if let self {
self.presentViewOnceTooltip(sourceView: sourceView)
}
}
self.controllerNode.statusBar = self.statusBar
self.controllerNode.navigationBar = self.navigationBar
@ -497,6 +544,42 @@ public final class SecretMediaPreviewController: ViewController {
}
}
private func presentViewOnceTooltip(sourceView: UIView) {
if let tooltipController = self.tooltipController {
self.tooltipController = nil
tooltipController.dismiss()
}
let absoluteFrame = sourceView.convert(sourceView.bounds, to: nil)
let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.maxY + 2.0), size: CGSize())
let iconName = "anim_autoremove_on"
let text: String
if self.currentNodeMessageIsVideo {
text = "This video can only be viewed once"
} else {
text = "This photo can only be viewed once"
}
let tooltipController = TooltipScreen(
account: self.context.account,
sharedContext: self.context.sharedContext,
text: .plain(text: text),
balancedTextLayout: true,
style: .customBlur(UIColor(rgb: 0x18181a), 0.0),
arrowStyle: .small,
icon: .animation(name: iconName, delay: 0.1, tintColor: nil),
location: .point(location, .top),
displayDuration: .default,
inset: 8.0,
shouldDismissOnTouch: { _, _ in
return .ignore
}
)
self.tooltipController = tooltipController
self.present(tooltipController, in: .window(.root))
}
public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)

View File

@ -4,6 +4,35 @@ import AsyncDisplayKit
import Display
public enum RadialStatusNodeState: Equatable {
public enum SecretTimeoutIcon: Equatable {
case none
case image(UIImage)
case flame
public static func ==(lhs: SecretTimeoutIcon, rhs: SecretTimeoutIcon) -> Bool {
switch lhs {
case .none:
if case .none = rhs {
return true
} else {
return false
}
case let .image(lhsImage):
if case let .image(rhsImage) = rhs, lhsImage === rhsImage {
return true
} else {
return false
}
case .flame:
if case .flame = rhs {
return true
} else {
return false
}
}
}
}
case none
case download(UIColor)
case play(UIColor)
@ -13,7 +42,7 @@ public enum RadialStatusNodeState: Equatable {
case check(UIColor)
case customIcon(UIImage)
case staticTimeout
case secretTimeout(color: UIColor, icon: UIImage?, beginTime: Double, timeout: Double, sparks: Bool)
case secretTimeout(color: UIColor, icon: SecretTimeoutIcon, beginTime: Double, timeout: Double, sparks: Bool)
public static func ==(lhs: RadialStatusNodeState, rhs: RadialStatusNodeState) -> Bool {
switch lhs {
@ -72,7 +101,7 @@ public enum RadialStatusNodeState: Equatable {
return false
}
case let .secretTimeout(lhsColor, lhsIcon, lhsBeginTime, lhsTimeout, lhsSparks):
if case let .secretTimeout(rhsColor, rhsIcon, rhsBeginTime, rhsTimeout, rhsSparks) = rhs, lhsColor.isEqual(rhsColor), lhsIcon === rhsIcon, lhsBeginTime.isEqual(to: rhsBeginTime), lhsTimeout.isEqual(to: rhsTimeout), lhsSparks == rhsSparks {
if case let .secretTimeout(rhsColor, rhsIcon, rhsBeginTime, rhsTimeout, rhsSparks) = rhs, lhsColor.isEqual(rhsColor), lhsIcon == rhsIcon, lhsBeginTime.isEqual(to: rhsBeginTime), lhsTimeout.isEqual(to: rhsTimeout), lhsSparks == rhsSparks {
return true
} else {
return false
@ -137,7 +166,7 @@ public enum RadialStatusNodeState: Equatable {
return false
}
case let .secretTimeout(lhsColor, lhsIcon, lhsBeginTime, lhsTimeout, lhsSparks):
if case let .secretTimeout(rhsColor, rhsIcon, rhsBeginTime, rhsTimeout, rhsSparks) = rhs, lhsColor.isEqual(rhsColor), lhsIcon === rhsIcon, lhsBeginTime.isEqual(to: rhsBeginTime), lhsTimeout.isEqual(to: rhsTimeout), lhsSparks == rhsSparks {
if case let .secretTimeout(rhsColor, rhsIcon, rhsBeginTime, rhsTimeout, rhsSparks) = rhs, lhsColor.isEqual(rhsColor), lhsIcon == rhsIcon, lhsBeginTime.isEqual(to: rhsBeginTime), lhsTimeout.isEqual(to: rhsTimeout), lhsSparks == rhsSparks {
return true
} else {
return false

View File

@ -25,12 +25,12 @@ private struct ContentParticle {
private final class RadialStatusSecretTimeoutContentNodeParameters: NSObject {
let color: UIColor
let icon: UIImage?
let icon: RadialStatusNodeState.SecretTimeoutIcon
let progress: CGFloat
let sparks: Bool
let particles: [ContentParticle]
init(color: UIColor, icon: UIImage?, progress: CGFloat, sparks: Bool, particles: [ContentParticle]) {
init(color: UIColor, icon: RadialStatusNodeState.SecretTimeoutIcon, progress: CGFloat, sparks: Bool, particles: [ContentParticle]) {
self.color = color
self.icon = icon
self.progress = progress
@ -48,7 +48,7 @@ final class RadialStatusSecretTimeoutContentNode: RadialStatusContentNode {
private let beginTime: Double
private let timeout: Double
private let icon: UIImage?
private let icon: RadialStatusNodeState.SecretTimeoutIcon
private let sparks: Bool
private var progress: CGFloat = 0.0
@ -58,7 +58,7 @@ final class RadialStatusSecretTimeoutContentNode: RadialStatusContentNode {
private var displayLink: CADisplayLink?
init(color: UIColor, beginTime: Double, timeout: Double, icon: UIImage?, sparks: Bool) {
init(color: UIColor, beginTime: Double, timeout: Double, icon: RadialStatusNodeState.SecretTimeoutIcon, sparks: Bool) {
self.color = color
self.beginTime = beginTime
self.timeout = timeout
@ -84,7 +84,7 @@ final class RadialStatusSecretTimeoutContentNode: RadialStatusContentNode {
self.displayLink?.isPaused = true
self.displayLink?.add(to: RunLoop.main, forMode: .common)
if icon != nil {
if case .flame = icon {
self.addSubnode(self.animationNode)
}
}
@ -202,15 +202,15 @@ final class RadialStatusSecretTimeoutContentNode: RadialStatusContentNode {
}
if let parameters = parameters as? RadialStatusSecretTimeoutContentNodeParameters {
// if let icon = parameters.icon, let _ = icon.cgImage {
// let imageRect = CGRect(origin: CGPoint(x: floor((bounds.size.width - icon.size.width) / 2.0), y: floor((bounds.size.height - icon.size.height) / 2.0)), size: icon.size)
// context.saveGState()
// context.translateBy(x: imageRect.midX, y: imageRect.midY)
// context.scaleBy(x: 1.0, y: -1.0)
// context.translateBy(x: -imageRect.midX, y: -imageRect.midY)
// context.draw(iconImage, in: imageRect)
// context.restoreGState()
// }
if case let .image(icon) = parameters.icon, let iconImage = icon.cgImage {
let imageRect = CGRect(origin: CGPoint(x: floor((bounds.size.width - icon.size.width) / 2.0), y: floor((bounds.size.height - icon.size.height) / 2.0)), size: icon.size)
context.saveGState()
context.translateBy(x: imageRect.midX, y: imageRect.midY)
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: -imageRect.midX, y: -imageRect.midY)
context.draw(iconImage, in: imageRect)
context.restoreGState()
}
let lineWidth: CGFloat
if parameters.sparks {

View File

@ -95,7 +95,7 @@ enum AccountStateMutationOperation {
case UpdatePinnedItemIds(PeerGroupId, AccountStateUpdatePinnedItemIdsOperation)
case UpdatePinnedTopic(peerId: PeerId, threadId: Int64, isPinned: Bool)
case UpdatePinnedTopicOrder(peerId: PeerId, threadIds: [Int64])
case ReadMessageContents((PeerId?, [Int32]))
case ReadMessageContents(peerIdsAndMessageIds: (PeerId?, [Int32]), date: Int32?)
case UpdateMessageImpressionCount(MessageId, Int32)
case UpdateMessageForwardsCount(MessageId, Int32)
case UpdateInstalledStickerPacks(AccountStateUpdateStickerPacksOperation)
@ -574,8 +574,8 @@ struct AccountMutableState {
self.addOperation(.UpdatePinnedTopicOrder(peerId: peerId, threadIds: threadIds))
}
mutating func addReadMessagesContents(_ peerIdsAndMessageIds: (PeerId?, [Int32])) {
self.addOperation(.ReadMessageContents(peerIdsAndMessageIds))
mutating func addReadMessagesContents(_ peerIdsAndMessageIds: (PeerId?, [Int32]), date: Int32?) {
self.addOperation(.ReadMessageContents(peerIdsAndMessageIds: peerIdsAndMessageIds, date: date))
}
mutating func addUpdateMessageImpressionCount(id: MessageId, count: Int32) {

View File

@ -1479,11 +1479,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
case let .updateChannelPinnedTopic(flags, channelId, topicId):
let isPinned = (flags & (1 << 0)) != 0
updatedState.addUpdatePinnedTopic(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadId: Int64(topicId), isPinned: isPinned)
case let .updateReadMessagesContents(_, messages, _, _, _):
updatedState.addReadMessagesContents((nil, messages))
case let .updateReadMessagesContents(_, messages, _, _, date):
updatedState.addReadMessagesContents((nil, messages), date: date)
case let .updateChannelReadMessagesContents(_, channelId, topMsgId, messages):
let _ = topMsgId
updatedState.addReadMessagesContents((PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), messages))
updatedState.addReadMessagesContents((PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), messages), date: nil)
case let .updateChannelMessageViews(channelId, id, views):
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), namespace: Namespaces.Message.Cloud, id: id), count: views)
/*case let .updateChannelMessageForwards(channelId, id, forwards):
@ -2929,7 +2929,7 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
}, pinned: (flags & (1 << 0)) != 0)
case let .updateChannelReadMessagesContents(_, _, topMsgId, messages):
let _ = topMsgId
updatedState.addReadMessagesContents((peer.id, messages))
updatedState.addReadMessagesContents((peer.id, messages), date: nil)
case let .updateChannelMessageViews(_, id, views):
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), count: views)
case let .updateChannelWebPage(_, apiWebpage, _, _):
@ -4181,16 +4181,16 @@ func replayFinalState(
transaction.setPeerPinnedThreads(peerId: peerId, threadIds: currentThreadIds)
case let .UpdatePinnedTopicOrder(peerId, threadIds):
transaction.setPeerPinnedThreads(peerId: peerId, threadIds: threadIds)
case let .ReadMessageContents(peerIdAndMessageIds):
case let .ReadMessageContents(peerIdAndMessageIds, date):
let (peerId, messageIds) = peerIdAndMessageIds
if let peerId = peerId {
for id in messageIds {
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id))
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), consumeDate: date)
}
} else {
for messageId in transaction.messageIdsForGlobalIds(messageIds) {
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: messageId)
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: messageId, consumeDate: date)
}
}
case let .UpdateMessageImpressionCount(id, count):

View File

@ -307,7 +307,7 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption
}
}
for messageId in messageIds {
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: messageId)
markMessageContentAsConsumedRemotely(transaction: transaction, messageId: messageId, consumeDate: nil)
}
default:
break

View File

@ -160,7 +160,7 @@ func _internal_markReactionsAsSeenInteractively(postbox: Postbox, messageId: Mes
}
}
func markMessageContentAsConsumedRemotely(transaction: Transaction, messageId: MessageId) {
func markMessageContentAsConsumedRemotely(transaction: Transaction, messageId: MessageId, consumeDate: Int32?) {
if let message = transaction.getMessage(messageId) {
var updateMessage = false
var updatedAttributes = message.attributes
@ -184,35 +184,41 @@ func markMessageContentAsConsumedRemotely(transaction: Transaction, messageId: M
}
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
let countdownBeginTime = consumeDate ?? timestamp
for i in 0 ..< updatedAttributes.count {
if let attribute = updatedAttributes[i] as? AutoremoveTimeoutMessageAttribute {
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && message.containsSecretMedia {
updatedAttributes[i] = AutoremoveTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: timestamp)
updatedAttributes[i] = AutoremoveTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: countdownBeginTime)
updateMessage = true
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
} else {
for i in 0 ..< updatedMedia.count {
if let _ = updatedMedia[i] as? TelegramMediaImage {
updatedMedia[i] = TelegramMediaExpiredContent(data: .image)
} else if let _ = updatedMedia[i] as? TelegramMediaFile {
updatedMedia[i] = TelegramMediaExpiredContent(data: .file)
if attribute.timeout == viewOnceTimeout || timestamp >= countdownBeginTime + attribute.timeout {
for i in 0 ..< updatedMedia.count {
if let _ = updatedMedia[i] as? TelegramMediaImage {
updatedMedia[i] = TelegramMediaExpiredContent(data: .image)
} else if let _ = updatedMedia[i] as? TelegramMediaFile {
updatedMedia[i] = TelegramMediaExpiredContent(data: .file)
}
}
}
}
}
} else if let attribute = updatedAttributes[i] as? AutoclearTimeoutMessageAttribute {
if (attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0) && message.containsSecretMedia {
updatedAttributes[i] = AutoclearTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: timestamp)
updatedAttributes[i] = AutoclearTimeoutMessageAttribute(timeout: attribute.timeout, countdownBeginTime: countdownBeginTime)
updateMessage = true
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
} else {
for i in 0 ..< updatedMedia.count {
if let _ = updatedMedia[i] as? TelegramMediaImage {
updatedMedia[i] = TelegramMediaExpiredContent(data: .image)
} else if let _ = updatedMedia[i] as? TelegramMediaFile {
updatedMedia[i] = TelegramMediaExpiredContent(data: .file)
if attribute.timeout == viewOnceTimeout || timestamp >= countdownBeginTime + attribute.timeout {
if let _ = updatedMedia[i] as? TelegramMediaImage {
updatedMedia[i] = TelegramMediaExpiredContent(data: .image)
} else if let _ = updatedMedia[i] as? TelegramMediaFile {
updatedMedia[i] = TelegramMediaExpiredContent(data: .file)
}
}
}
}

View File

@ -4111,6 +4111,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
fileprivate func presentReactionPremiumSuggestion() {
self.hapticFeedback.impact(.light)
self.dismissAllTooltips()
let context = self.context
@ -4142,7 +4144,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
)
}
let controller = UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: true, position: .bottom, animateInAsReplacement: false, action: { [weak self] action in
let controller = UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: true, position: .top, animateInAsReplacement: false, action: { [weak self] action in
if case .info = action, let self {
if let stickerScreen = self.node.stickerScreen {
self.node.stickerScreen = nil

View File

@ -1157,9 +1157,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
case .Local:
if isSecretMedia && self.secretProgressIcon != nil {
if let (beginTime, timeout) = secretBeginTimeAndTimeout {
state = .secretTimeout(color: messageTheme.mediaOverlayControlColors.foregroundColor, icon: secretProgressIcon, beginTime: beginTime, timeout: timeout, sparks: true)
state = .secretTimeout(color: messageTheme.mediaOverlayControlColors.foregroundColor, icon: .flame, beginTime: beginTime, timeout: timeout, sparks: true)
} else {
state = .customIcon(secretProgressIcon!)
state = .staticTimeout
}
} else {
state = .none

View File

@ -1796,6 +1796,10 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
var badgeContent: ChatMessageInteractiveMediaBadgeContent?
var mediaDownloadState: ChatMessageInteractiveMediaDownloadState?
if isSecretMedia {
backgroundColor = messageTheme.mediaDateAndStatusFillColor
}
if let invoice = invoice {
if let extendedMedia = invoice.extendedMedia {
if case let .preview(_, _, maybeVideoDuration) = extendedMedia, let videoDuration = maybeVideoDuration {
@ -1989,11 +1993,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
secretProgressIcon = PresentationResourcesChat.chatBubbleSecretMediaCompactIcon(theme)
}
if isSecretMedia, let (maybeBeginTime, timeout) = secretBeginTimeAndTimeout, let beginTime = maybeBeginTime, Int32(timeout) != viewOnceTimeout {
state = .secretTimeout(color: messageTheme.mediaOverlayControlColors.foregroundColor, icon: secretProgressIcon, beginTime: beginTime, timeout: timeout, sparks: true)
backgroundColor = messageTheme.mediaDateAndStatusFillColor
state = .secretTimeout(color: messageTheme.mediaOverlayControlColors.foregroundColor, icon: .flame, beginTime: beginTime, timeout: timeout, sparks: true)
} else if isSecretMedia, let _ = secretProgressIcon {
state = .staticTimeout
backgroundColor = messageTheme.mediaDateAndStatusFillColor
} else if let file = media as? TelegramMediaFile, !file.isVideoSticker {
let isInlinePlayableVideo = file.isVideo && !isSecretMedia && (self.automaticPlayback ?? false)
if (!isInlinePlayableVideo || isStory) && file.isVideo {

View File

@ -1347,8 +1347,12 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
var panelWrapperFrame = CGRect(origin: CGPoint(x: leftMargin + layout.safeInsets.left, y: layout.size.height - contentHeight - insets.bottom - margin), size: CGSize(width: layout.size.width - leftMargin * 2.0 - layout.safeInsets.left - layout.safeInsets.right, height: contentHeight))
if case .top = self.placementPosition {
panelFrame.origin.y = insets.top + margin
panelWrapperFrame.origin.y = insets.top + margin
var topInset = insets.top
if topInset.isZero {
topInset = layout.statusBarHeight ?? 44.0
}
panelFrame.origin.y = topInset + margin
panelWrapperFrame.origin.y = topInset + margin
}
transition.updateFrame(node: self.panelNode, frame: panelFrame)
@ -1441,7 +1445,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
let statusSize: CGFloat = 30.0
transition.updateFrame(node: statusNode, frame: CGRect(origin: CGPoint(x: floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize)))
if firstLayout {
statusNode.transitionToState(.secretTimeout(color: .white, icon: nil, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
statusNode.transitionToState(.secretTimeout(color: .white, icon: .none, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
}
}