From 8888c6809726bb32da37645dabbb4c23e9205a7a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 7 Jun 2022 17:01:45 +0400 Subject: [PATCH 1/3] Use lottie animation for text loading indicator --- .../BUILD | 1 + ...anscriptionPendingIndicatorComponent.swift | 78 +++++++++++++++++++ .../Animations/animated_text_dots.json | 1 + .../ChatMessageInteractiveFileNode.swift | 11 ++- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 submodules/TelegramUI/Resources/Animations/animated_text_dots.json diff --git a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/BUILD b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/BUILD index 00a1fa5dc3..a7077463f6 100644 --- a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/BUILD +++ b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/BUILD @@ -13,6 +13,7 @@ swift_library( "//submodules/ComponentFlow:ComponentFlow", "//submodules/AppBundle:AppBundle", "//submodules/Display:Display", + "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift index 032121cc22..ff7e3521df 100644 --- a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift +++ b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift @@ -3,6 +3,7 @@ import UIKit import ComponentFlow import AppBundle import Display +import LottieAnimationComponent public final class AudioTranscriptionPendingIndicatorComponent: Component { public let color: UIColor @@ -98,3 +99,80 @@ public final class AudioTranscriptionPendingIndicatorComponent: Component { return view.update(component: self, availableSize: availableSize, transition: transition) } } + +public final class AudioTranscriptionPendingLottieIndicatorComponent: Component { + public let color: UIColor + public let font: UIFont + + public init(color: UIColor, font: UIFont) { + self.color = color + self.font = font + } + + public static func ==(lhs: AudioTranscriptionPendingLottieIndicatorComponent, rhs: AudioTranscriptionPendingLottieIndicatorComponent) -> Bool { + if lhs.color != rhs.color { + return false + } + if lhs.font != rhs.font { + return false + } + return true + } + + public final class View: UIView { + private let animationView: ComponentHostView + + override init(frame: CGRect) { + self.animationView = ComponentHostView() + + super.init(frame: frame) + + self.addSubview(self.animationView) + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: AudioTranscriptionPendingLottieIndicatorComponent, availableSize: CGSize, transition: Transition) -> CGSize { + let originalSize = CGSize(width: 48.0, height: 66.0) + let animationSize = originalSize.aspectFitted(CGSize(width: 15.0, height: 100.0)) + let _ = self.animationView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: "animated_text_dots", + colors: [ + "Comp 1.Point 3.Group 1.Fill 1": component.color, + "Comp 1.Point 2.Group 1.Fill 1": component.color, + "Comp 1.Point 1.Group 1.Fill 1": component.color + ], + mode: .animating(loop: true) + ), + size: animationSize + )), + environment: {}, + containerSize: animationSize + ) + + var stringSize = NSAttributedString(string: "...", font: component.font, textColor: .black).boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil).size + stringSize.width = ceil(stringSize.width) + stringSize.height = ceil(stringSize.height) + + let size = CGSize(width: min(availableSize.width, stringSize.width), height: min(availableSize.height, 10.0)) + + self.animationView.frame = CGRect(origin: CGPoint(x: -2.0, y: size.height - animationSize.height + 4.0 + UIScreenPixel), size: animationSize) + + return size + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} + diff --git a/submodules/TelegramUI/Resources/Animations/animated_text_dots.json b/submodules/TelegramUI/Resources/Animations/animated_text_dots.json new file mode 100644 index 0000000000..db9afcac38 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/animated_text_dots.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":48,"h":66,"nm":"Comp 2","ddd":0,"assets":[{"id":"comp_0","nm":"Comp 1","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Point 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.7,"y":0},"t":12,"s":[118.6,256,0],"to":[-0.6,-119,0],"ti":[-1.438,-92.469,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.32,"y":0},"t":32,"s":[255.938,275.469,0],"to":[0,0,0],"ti":[0,0,0]},{"t":42,"s":[255.938,255.969,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-102.4,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.673,0],[0,-17.673],[17.673,0],[0,17.673]],"o":[[17.673,0],[0,17.673],[-17.673,0],[0,-17.673]],"v":[[-102.4,-32],[-70.4,0],[-102.4,32],[-134.4,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Point 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.7,"y":0},"t":0,"s":[256,256,0],"to":[1.75,-110,0],"ti":[-5.25,-93.219,0]},{"i":{"x":0.42,"y":1},"o":{"x":0.3,"y":0},"t":20,"s":[393.25,276.969,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30,"s":[393.25,255.969,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.673,0],[0,-17.673],[17.673,0],[0,17.673]],"o":[[17.673,0],[0,17.673],[-17.673,0],[0,-17.673]],"v":[[0,-32],[32,0],[0,32],[-32,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Point 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[393.4,256,0],"to":[0,0,0],"ti":[0,0,0]},{"t":40,"s":[118.562,255.969,0]}],"ix":2,"l":2},"a":{"a":0,"k":[102.4,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.673,0],[0,-17.673],[17.673,0],[0,17.673]],"o":[[17.673,0],[0,17.673],[-17.673,0],[0,-17.673]],"v":[[102.4,-32],[134.4,0],[102.4,32],[70.4,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Comp 1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[24,48,0],"ix":2,"l":2},"a":{"a":0,"k":[256,256,0],"ix":1,"l":2},"s":{"a":0,"k":[10.8,10.8,100],"ix":6,"l":2}},"ao":0,"w":512,"h":512,"ip":0,"op":180,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index a7e78e220d..43953f3788 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -659,12 +659,12 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { case let .success(text, isPending): textString = NSAttributedString(string: text, font: textFont, textColor: messageTheme.primaryTextColor) - /*#if DEBUG + #if DEBUG var isPending = isPending if "".isEmpty { isPending = true } - #endif*/ + #endif if isPending { let modifiedString = NSMutableAttributedString(attributedString: textString!) @@ -1027,9 +1027,14 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { strongSelf.transcriptionPendingIndicator = transcriptionPendingIndicator strongSelf.textClippingNode.view.addSubview(transcriptionPendingIndicator) } + + let indicatorComponent: AnyComponent + indicatorComponent = AnyComponent(AudioTranscriptionPendingLottieIndicatorComponent(color: messageTheme.primaryTextColor, font: textFont)) + //indicatorComponent = AnyComponent(AudioTranscriptionPendingIndicatorComponent(color: messageTheme.primaryTextColor, font: textFont)) + let indicatorSize = transcriptionPendingIndicator.update( transition: .immediate, - component: AnyComponent(AudioTranscriptionPendingIndicatorComponent(color: messageTheme.primaryTextColor, font: textFont)), + component: indicatorComponent, environment: {}, containerSize: CGSize(width: 100.0, height: 100.0) ) From 37fc5397dcba287dc8298f337028ee4fb2c61b72 Mon Sep 17 00:00:00 2001 From: Mike Renoir <> Date: Tue, 7 Jun 2022 19:15:01 +0400 Subject: [PATCH 2/3] macos fxies --- .../MtProtoKit/Sources/MTApiEnvironment.m | 4 ++-- ...anagedPremiumPromoConfigurationUpdates.swift | 5 +++-- .../Sources/SyncCore/SyncCore_Namespaces.swift | 2 +- .../SyncCore_PremiumPromoConfiguration.swift | 17 +++++++++++++++-- .../SyncCore/SyncCore_TelegramMediaFile.swift | 9 +++++++++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/submodules/MtProtoKit/Sources/MTApiEnvironment.m b/submodules/MtProtoKit/Sources/MTApiEnvironment.m index 935a2b99ce..d14eb86297 100644 --- a/submodules/MtProtoKit/Sources/MTApiEnvironment.m +++ b/submodules/MtProtoKit/Sources/MTApiEnvironment.m @@ -463,12 +463,12 @@ NSString *suffix = @""; #if TARGET_OS_OSX NSString *value = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"SOURCE"]; if (value != nil) { - suffix = [NSString stringWithFormat:@"%@ ", value]; + suffix = [NSString stringWithFormat:@"%@", value]; } #endif //SOURCE - NSString *versionString = [[NSString alloc] initWithFormat:@"%@ (%@)%@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], suffix]; + NSString *versionString = [[NSString alloc] initWithFormat:@"%@ (%@) %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], suffix]; _appVersion = versionString; _systemLangCode = [[NSLocale preferredLanguages] objectAtIndex:0]; diff --git a/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift b/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift index dea49afd7d..e36c11ff62 100644 --- a/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift +++ b/submodules/TelegramCore/Sources/State/ManagedPremiumPromoConfigurationUpdates.swift @@ -54,10 +54,11 @@ private func updatePremiumPromoConfiguration(transaction: Transaction, _ f: (Pre private extension PremiumPromoConfiguration { init(apiPremiumPromo: Api.help.PremiumPromo) { switch apiPremiumPromo { - case let .premiumPromo(statusText, statusEntities, videoSections, videoFiles, _, _): + case let .premiumPromo(statusText, statusEntities, videoSections, videoFiles, currency, monthlyAmount): self.status = statusText self.statusEntities = messageTextEntitiesFromApiEntities(statusEntities) - + self.currency = currency + self.monthlyAmount = monthlyAmount var videos: [String: TelegramMediaFile] = [:] for (key, document) in zip(videoSections, videoFiles) { if let file = telegramMediaFileFromApiDocument(document) { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index bf3ea7c899..a1ebf48113 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -232,7 +232,7 @@ private enum PreferencesKeyValues: Int32 { case chatListFiltersFeaturedState = 22 case secretChatSettings = 23 case reactionSettings = 24 - case premiumPromo = 25 + case premiumPromo = 26 } public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift index 35bcf7a304..97f796b54f 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_PremiumPromoConfiguration.swift @@ -4,6 +4,8 @@ import Postbox public struct PremiumPromoConfiguration: Codable, Equatable { enum CodingKeys: String, CodingKey { case status + case currency + case monthlyAmount case statusEntities case videos } @@ -36,12 +38,17 @@ public struct PremiumPromoConfiguration: Codable, Equatable { public var statusEntities: [MessageTextEntity] public var videos: [String: TelegramMediaFile] + public var currency: String + public var monthlyAmount: Int64 + public static var defaultValue: PremiumPromoConfiguration { - return PremiumPromoConfiguration(status: "", statusEntities: [], videos: [:]) + return PremiumPromoConfiguration(status: "", statusEntities: [], videos: [:], currency: "", monthlyAmount: 0) } - init(status: String, statusEntities: [MessageTextEntity], videos: [String: TelegramMediaFile]) { + init(status: String, statusEntities: [MessageTextEntity], videos: [String: TelegramMediaFile], currency: String, monthlyAmount: Int64) { self.status = status + self.currency = currency + self.monthlyAmount = monthlyAmount self.statusEntities = statusEntities self.videos = videos } @@ -58,6 +65,10 @@ public struct PremiumPromoConfiguration: Codable, Equatable { videos[pair.key] = pair.value } self.videos = videos + + self.currency = try container.decode(String.self, forKey: .currency) + self.monthlyAmount = try container.decode(Int64.self, forKey: .monthlyAmount) + } public func encode(to encoder: Encoder) throws { @@ -65,6 +76,8 @@ public struct PremiumPromoConfiguration: Codable, Equatable { try container.encode(self.status, forKey: .status) try container.encode(self.statusEntities, forKey: .statusEntities) + try container.encode(self.currency, forKey: .currency) + try container.encode(self.monthlyAmount, forKey: .monthlyAmount) var pairs: [DictionaryPair] = [] for (key, file) in self.videos { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index f0eff5069c..c01106354f 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -499,6 +499,15 @@ public final class TelegramMediaFile: Media, Equatable, Codable { return false } + public var noPremium: Bool { + for attribute in self.attributes { + if case .NoPremium = attribute { + return true + } + } + return false + } + public var premiumEffect: TelegramMediaFile.VideoThumbnail? { if let effect = self.videoThumbnails.first(where: { thumbnail in if let resource = thumbnail.resource as? CloudDocumentSizeMediaResource, resource.sizeSpec == "f" { From 48e09cecb4760d8db3d3a9ec4e97992dda705d43 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 7 Jun 2022 20:35:09 +0400 Subject: [PATCH 3/3] Improve logging --- .../MessageHistoryTagsSummaryTable.swift | 3 +++ .../Messages/TelegramEngineMessages.swift | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/submodules/Postbox/Sources/MessageHistoryTagsSummaryTable.swift b/submodules/Postbox/Sources/MessageHistoryTagsSummaryTable.swift index 8ae38715f2..6dc49b60e9 100644 --- a/submodules/Postbox/Sources/MessageHistoryTagsSummaryTable.swift +++ b/submodules/Postbox/Sources/MessageHistoryTagsSummaryTable.swift @@ -110,6 +110,9 @@ class MessageHistoryTagsSummaryTable: Table { private func set(_ key: MessageHistoryTagsSummaryKey, summary: MessageHistoryTagNamespaceSummary, updatedSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary]) { if self.get(key) != summary { + if key.tag.rawValue == 2048 { + postboxLog("[MessageHistoryTagsSummaryTable] set \(key.tag.rawValue) for \(key.peerId) to \(summary.count)") + } self.updatedKeys.insert(key) self.cachedSummaries[key] = CachedEntry(summary: summary) updatedSummaries[key] = summary diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index dc8c8ac356..f45b440830 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -155,11 +155,35 @@ public extension TelegramEngine { } public func earliestUnseenPersonalMentionMessage(peerId: PeerId) -> Signal { + let account = self.account return _internal_earliestUnseenPersonalMentionMessage(account: self.account, peerId: peerId) + |> mapToSignal { result -> Signal in + switch result { + case .loading: + return .single(result) + case let .result(messageId): + if messageId == nil { + let _ = clearPeerUnseenPersonalMessagesInteractively(account: account, peerId: peerId).start() + } + return .single(result) + } + } } public func earliestUnseenPersonalReactionMessage(peerId: PeerId) -> Signal { + let account = self.account return _internal_earliestUnseenPersonalReactionMessage(account: self.account, peerId: peerId) + |> mapToSignal { result -> Signal in + switch result { + case .loading: + return .single(result) + case let .result(messageId): + if messageId == nil { + let _ = clearPeerUnseenReactionsInteractively(account: account, peerId: peerId).start() + } + return .single(result) + } + } } public func exportMessageLink(peerId: PeerId, messageId: MessageId, isThread: Bool = false) -> Signal {