diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index abdd8985d4..b45faed228 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -84,6 +84,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case enableDebugDataDisplay(Bool) case acceleratedStickers(Bool) case experimentalBackground(Bool) + case inlineStickers(Bool) case snow(Bool) case playerEmbedding(Bool) case playlistPlayback(Bool) @@ -106,7 +107,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.logging.rawValue case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: return DebugControllerSection.experiments.rawValue - case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .snow: + case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineStickers, .snow: return DebugControllerSection.experiments.rawValue case .preferredVideoCodec: return DebugControllerSection.videoExperiments.rawValue @@ -181,16 +182,18 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 29 case .experimentalBackground: return 30 - case .snow: + case .inlineStickers: return 31 - case .playerEmbedding: + case .snow: return 32 - case .playlistPlayback: + case .playerEmbedding: return 33 - case .voiceConference: + case .playlistPlayback: return 34 + case .voiceConference: + return 35 case let .preferredVideoCodec(index, _, _, _): - return 35 + index + return 36 + index case .disableVideoAspectScaling: return 100 case .enableVoipTcp: @@ -948,6 +951,16 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) + case let .inlineStickers(value): + return ItemListSwitchItem(presentationData: presentationData, title: "Inline Stickers", value: value, sectionId: self.section, style: .blocks, updated: { value in + let _ = arguments.sharedContext.accountManager.transaction ({ transaction in + transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in + var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings + settings.inlineStickers = value + return PreferencesEntry(settings) + }) + }).start() + }) case let .snow(value): return ItemListSwitchItem(presentationData: presentationData, title: "Snow", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in @@ -1073,6 +1086,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.enableDebugDataDisplay(experimentalSettings.enableDebugDataDisplay)) entries.append(.acceleratedStickers(experimentalSettings.acceleratedStickers)) entries.append(.experimentalBackground(experimentalSettings.experimentalBackground)) + entries.append(.inlineStickers(experimentalSettings.inlineStickers)) entries.append(.playerEmbedding(experimentalSettings.playerEmbedding)) entries.append(.playlistPlayback(experimentalSettings.playlistPlayback)) } diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 0998f6617b..9a5ea7b959 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -75,6 +75,11 @@ private final class InlineStickerItemLayer: SimpleLayer { private var disposable: Disposable? private var isInHierarchy: Bool = false + var isVisibleForAnimations: Bool = false { + didSet { + self.updatePlayback() + } + } private var displayLink: ConstantDisplayLinkAnimator? init(context: AccountContext, file: TelegramMediaFile) { @@ -132,7 +137,7 @@ private final class InlineStickerItemLayer: SimpleLayer { } private func updatePlayback() { - let shouldBePlaying = self.isInHierarchy && self.frameSource != nil + let shouldBePlaying = self.isInHierarchy && self.isVisibleForAnimations && self.frameSource != nil if shouldBePlaying != (self.displayLink != nil) { if shouldBePlaying { self.displayLink = ConstantDisplayLinkAnimator(update: { [weak self] in @@ -205,6 +210,22 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private var cachedChatMessageText: CachedChatMessageText? + private var isVisibleForAnimations: Bool { + return self.visibility != .none + } + + override var visibility: ListViewItemNodeVisibility { + didSet { + let wasVisible = oldValue != .none + let isVisible = self.visibility != .none + if wasVisible != isVisible { + for (_, itemLayer) in self.inlineStickerItemLayers { + itemLayer.isVisibleForAnimations = isVisible + } + } + } + } + required init() { self.textNode = TextNode() @@ -436,33 +457,33 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { attributedText = NSAttributedString(string: " ", font: textFont, textColor: messageTheme.primaryTextColor) } - #if DEBUG - let updatedString = NSMutableAttributedString(attributedString: attributedText) - while true { - var hadUpdates = false - updatedString.string.enumerateSubstrings(in: updatedString.string.startIndex ..< updatedString.string.endIndex, options: [.byComposedCharacterSequences]) { substring, substringRange, _, stop in - if let substring = substring { - let emoji = substring.basicEmoji.0 - - var emojiFile: TelegramMediaFile? - emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file - if emojiFile == nil { - emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file - } - - if let emojiFile = emojiFile { - updatedString.replaceCharacters(in: NSRange(substringRange, in: updatedString.string), with: NSAttributedString(string: "[..]", attributes: [NSAttributedString.Key("Attribute__EmbeddedItem"): InlineStickerItem(file: emojiFile), NSAttributedString.Key.foregroundColor: UIColor.clear.cgColor])) - hadUpdates = true - stop = true + if item.context.sharedContext.immediateExperimentalUISettings.inlineStickers { + let updatedString = NSMutableAttributedString(attributedString: attributedText) + while true { + var hadUpdates = false + updatedString.string.enumerateSubstrings(in: updatedString.string.startIndex ..< updatedString.string.endIndex, options: [.byComposedCharacterSequences]) { substring, substringRange, _, stop in + if let substring = substring { + let emoji = substring.basicEmoji.0 + + var emojiFile: TelegramMediaFile? + emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file + if emojiFile == nil { + emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file + } + + if let emojiFile = emojiFile { + updatedString.replaceCharacters(in: NSRange(substringRange, in: updatedString.string), with: NSAttributedString(string: "[...]", attributes: [NSAttributedString.Key("Attribute__EmbeddedItem"): InlineStickerItem(file: emojiFile), NSAttributedString.Key.foregroundColor: UIColor.clear.cgColor])) + hadUpdates = true + stop = true + } } } + if !hadUpdates { + break + } } - if !hadUpdates { - break - } + attributedText = updatedString } - attributedText = updatedString - #endif let cutout: TextNodeCutout? = nil @@ -671,6 +692,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { itemLayer = InlineStickerItemLayer(context: context, file: stickerItem.file) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) + itemLayer.isVisibleForAnimations = self.isVisibleForAnimations } itemLayer.frame = CGRect(origin: item.rect.offsetBy(dx: textLayout.insets.left, dy: textLayout.insets.top + 1.0).center, size: CGSize()).insetBy(dx: -12.0, dy: -12.0) diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index a97a6c14f6..8e16a1ffdc 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -20,6 +20,7 @@ public struct ExperimentalUISettings: Codable, Equatable { public var acceleratedStickers: Bool public var experimentalBackground: Bool public var snow: Bool + public var inlineStickers: Bool public static var defaultSettings: ExperimentalUISettings { return ExperimentalUISettings( @@ -38,7 +39,8 @@ public struct ExperimentalUISettings: Codable, Equatable { enableDebugDataDisplay: false, acceleratedStickers: false, experimentalBackground: false, - snow: false + snow: false, + inlineStickers: false ) } @@ -58,7 +60,8 @@ public struct ExperimentalUISettings: Codable, Equatable { enableDebugDataDisplay: Bool, acceleratedStickers: Bool, experimentalBackground: Bool, - snow: Bool + snow: Bool, + inlineStickers: Bool ) { self.keepChatNavigationStack = keepChatNavigationStack self.skipReadHistory = skipReadHistory @@ -76,6 +79,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.acceleratedStickers = acceleratedStickers self.experimentalBackground = experimentalBackground self.snow = snow + self.inlineStickers = inlineStickers } public init(from decoder: Decoder) throws { @@ -97,6 +101,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.acceleratedStickers = (try container.decodeIfPresent(Int32.self, forKey: "acceleratedStickers") ?? 0) != 0 self.experimentalBackground = (try container.decodeIfPresent(Int32.self, forKey: "experimentalBackground") ?? 0) != 0 self.snow = (try container.decodeIfPresent(Int32.self, forKey: "snow") ?? 0) != 0 + self.inlineStickers = (try container.decodeIfPresent(Int32.self, forKey: "inlineStickers") ?? 0) != 0 } public func encode(to encoder: Encoder) throws { @@ -118,6 +123,7 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encode((self.acceleratedStickers ? 1 : 0) as Int32, forKey: "acceleratedStickers") try container.encode((self.experimentalBackground ? 1 : 0) as Int32, forKey: "experimentalBackground") try container.encode((self.snow ? 1 : 0) as Int32, forKey: "snow") + try container.encode((self.inlineStickers ? 1 : 0) as Int32, forKey: "inlineStickers") } }