mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
04ca831081
commit
266f9e5ad8
@ -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",
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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: {})
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user