mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Unread-based animation playback
This commit is contained in:
parent
9a2394ce1a
commit
6b1a7d1aae
@ -375,6 +375,11 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var isSetUpForPlayback = false
|
private var isSetUpForPlayback = false
|
||||||
|
|
||||||
|
public func playOnce() {
|
||||||
|
self.playbackMode = .once
|
||||||
|
self.play()
|
||||||
|
}
|
||||||
|
|
||||||
public func play(firstFrame: Bool = false, fromIndex: Int? = nil) {
|
public func play(firstFrame: Bool = false, fromIndex: Int? = nil) {
|
||||||
if !firstFrame {
|
if !firstFrame {
|
||||||
|
@ -936,6 +936,7 @@ public final class MessageHistoryView {
|
|||||||
public let entries: [MessageHistoryEntry]
|
public let entries: [MessageHistoryEntry]
|
||||||
public let maxReadIndex: MessageIndex?
|
public let maxReadIndex: MessageIndex?
|
||||||
public let fixedReadStates: MessageHistoryViewReadState?
|
public let fixedReadStates: MessageHistoryViewReadState?
|
||||||
|
public let transientReadStates: MessageHistoryViewReadState?
|
||||||
public let topTaggedMessages: [Message]
|
public let topTaggedMessages: [Message]
|
||||||
public let additionalData: [AdditionalMessageHistoryViewDataEntry]
|
public let additionalData: [AdditionalMessageHistoryViewDataEntry]
|
||||||
public let isLoading: Bool
|
public let isLoading: Bool
|
||||||
@ -952,6 +953,7 @@ public final class MessageHistoryView {
|
|||||||
self.entries = entries
|
self.entries = entries
|
||||||
self.maxReadIndex = nil
|
self.maxReadIndex = nil
|
||||||
self.fixedReadStates = nil
|
self.fixedReadStates = nil
|
||||||
|
self.transientReadStates = nil
|
||||||
self.topTaggedMessages = []
|
self.topTaggedMessages = []
|
||||||
self.additionalData = []
|
self.additionalData = []
|
||||||
self.isLoading = isLoading
|
self.isLoading = isLoading
|
||||||
@ -1053,6 +1055,7 @@ public final class MessageHistoryView {
|
|||||||
self.additionalData = mutableView.additionalDatas
|
self.additionalData = mutableView.additionalDatas
|
||||||
|
|
||||||
self.fixedReadStates = mutableView.combinedReadStates
|
self.fixedReadStates = mutableView.combinedReadStates
|
||||||
|
self.transientReadStates = mutableView.transientReadStates
|
||||||
|
|
||||||
switch mutableView.peerIds {
|
switch mutableView.peerIds {
|
||||||
case .single, .associated:
|
case .single, .associated:
|
||||||
|
@ -52,6 +52,11 @@ public enum ChatControllerInteractionReaction {
|
|||||||
case reaction(String)
|
case reaction(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct UnreadMessageRangeKey: Hashable {
|
||||||
|
var peerId: PeerId
|
||||||
|
var namespace: MessageId.Namespace
|
||||||
|
}
|
||||||
|
|
||||||
public final class ChatControllerInteraction {
|
public final class ChatControllerInteraction {
|
||||||
let openMessage: (Message, ChatControllerInteractionOpenMessageMode) -> Bool
|
let openMessage: (Message, ChatControllerInteractionOpenMessageMode) -> Bool
|
||||||
let openPeer: (PeerId?, ChatControllerInteractionNavigateToPeer, MessageReference?, Peer?) -> Void
|
let openPeer: (PeerId?, ChatControllerInteractionNavigateToPeer, MessageReference?, Peer?) -> Void
|
||||||
@ -149,6 +154,7 @@ public final class ChatControllerInteraction {
|
|||||||
var currentPsaMessageWithTooltip: MessageId?
|
var currentPsaMessageWithTooltip: MessageId?
|
||||||
var stickerSettings: ChatInterfaceStickerSettings
|
var stickerSettings: ChatInterfaceStickerSettings
|
||||||
var searchTextHighightState: (String, [MessageIndex])?
|
var searchTextHighightState: (String, [MessageIndex])?
|
||||||
|
var unreadMessageRange: [UnreadMessageRangeKey: Range<MessageId.Id>] = [:]
|
||||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||||
var currentMessageWithLoadingReplyThread: MessageId?
|
var currentMessageWithLoadingReplyThread: MessageId?
|
||||||
var updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
var updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||||
|
@ -2435,7 +2435,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||||
if text.length != 0 {
|
if text.length != 0 {
|
||||||
var attributes: [MessageAttribute] = []
|
var attributes: [MessageAttribute] = []
|
||||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: Int(self.context.userLimits.maxAnimatedEmojisInText)))
|
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: 0/*Int(self.context.userLimits.maxAnimatedEmojisInText)*/))
|
||||||
if !entities.isEmpty {
|
if !entities.isEmpty {
|
||||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||||
}
|
}
|
||||||
|
@ -1309,31 +1309,35 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
let previousMaxIncomingMessageIndexByNamespace = Atomic<[MessageId.Namespace: MessageIndex]>(value: [:])
|
let previousMaxIncomingMessageIndexByNamespace = Atomic<[MessageId.Namespace: MessageIndex]>(value: [:])
|
||||||
let readHistory = combineLatest(self.maxVisibleIncomingMessageIndex.get(), self.canReadHistory.get())
|
let readHistory = combineLatest(self.maxVisibleIncomingMessageIndex.get(), self.canReadHistory.get())
|
||||||
|> map { messageIndex, canRead in
|
|
||||||
if canRead {
|
self.readHistoryDisposable.set((readHistory |> deliverOnMainQueue).start(next: { [weak self] messageIndex, canRead in
|
||||||
var apply = false
|
guard let strongSelf = self else {
|
||||||
let _ = previousMaxIncomingMessageIndexByNamespace.modify { dict in
|
return
|
||||||
let previousIndex = dict[messageIndex.id.namespace]
|
}
|
||||||
if previousIndex == nil || previousIndex! < messageIndex {
|
if !canRead {
|
||||||
apply = true
|
return
|
||||||
var dict = dict
|
}
|
||||||
dict[messageIndex.id.namespace] = messageIndex
|
|
||||||
return dict
|
var apply = false
|
||||||
}
|
let _ = previousMaxIncomingMessageIndexByNamespace.modify { dict in
|
||||||
|
let previousIndex = dict[messageIndex.id.namespace]
|
||||||
|
if previousIndex == nil || previousIndex! < messageIndex {
|
||||||
|
apply = true
|
||||||
|
var dict = dict
|
||||||
|
dict[messageIndex.id.namespace] = messageIndex
|
||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
if apply {
|
return dict
|
||||||
switch chatLocation {
|
}
|
||||||
case .peer, .replyThread, .feed:
|
if apply {
|
||||||
if !context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
switch chatLocation {
|
||||||
context.applyMaxReadIndex(for: chatLocation, contextHolder: chatLocationContextHolder, messageIndex: messageIndex)
|
case .peer, .replyThread, .feed:
|
||||||
}
|
if !strongSelf.context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
||||||
|
strongSelf.context.applyMaxReadIndex(for: chatLocation, contextHolder: chatLocationContextHolder, messageIndex: messageIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}))
|
||||||
|
|
||||||
self.readHistoryDisposable.set(readHistory.start())
|
|
||||||
|
|
||||||
self.canReadHistoryDisposable = (self.canReadHistory.get() |> deliverOnMainQueue).start(next: { [weak self, weak context] value in
|
self.canReadHistoryDisposable = (self.canReadHistory.get() |> deliverOnMainQueue).start(next: { [weak self, weak context] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -2157,6 +2161,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func forEachVisibleMessageItemNode(_ f: (ChatMessageItemView) -> Void) {
|
||||||
|
self.forEachVisibleItemNode { itemNode in
|
||||||
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
|
f(itemNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func latestMessageInCurrentHistoryView() -> Message? {
|
public func latestMessageInCurrentHistoryView() -> Message? {
|
||||||
if let historyView = self.historyView {
|
if let historyView = self.historyView {
|
||||||
if historyView.originalView.laterId == nil, let firstEntry = historyView.filteredEntries.last {
|
if historyView.originalView.laterId == nil, let firstEntry = historyView.filteredEntries.last {
|
||||||
@ -2369,6 +2381,42 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unreadMessageRangeUpdated = false
|
||||||
|
|
||||||
|
if case let .peer(peerId) = strongSelf.chatLocation, let previousReadStatesValue = strongSelf.historyView?.originalView.transientReadStates, case let .peer(previousReadStates) = previousReadStatesValue, case let .peer(updatedReadStates) = transition.historyView.originalView.transientReadStates {
|
||||||
|
if let previousPeerReadState = previousReadStates[peerId], let updatedPeerReadState = updatedReadStates[peerId] {
|
||||||
|
if previousPeerReadState != updatedPeerReadState {
|
||||||
|
for (namespace, state) in previousPeerReadState.states {
|
||||||
|
inner: for (updatedNamespace, updatedState) in updatedPeerReadState.states {
|
||||||
|
if namespace == updatedNamespace {
|
||||||
|
switch state {
|
||||||
|
case let .idBased(previousIncomingId, _, _, _, _):
|
||||||
|
if case let .idBased(updatedIncomingId, _, _, _, _) = updatedState, previousIncomingId <= updatedIncomingId {
|
||||||
|
let rangeKey = UnreadMessageRangeKey(peerId: peerId, namespace: namespace)
|
||||||
|
|
||||||
|
if let currentRange = strongSelf.controllerInteraction.unreadMessageRange[rangeKey] {
|
||||||
|
if currentRange.upperBound < (updatedIncomingId + 1) {
|
||||||
|
strongSelf.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: peerId, namespace: namespace)] = currentRange.lowerBound ..< (updatedIncomingId + 1)
|
||||||
|
unreadMessageRangeUpdated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.controllerInteraction.unreadMessageRange[rangeKey] = (previousIncomingId + 1) ..< (updatedIncomingId + 1)
|
||||||
|
unreadMessageRangeUpdated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .indexBased:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
break inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//print("Read from \(previousPeerReadState) up to \(updatedPeerReadState)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strongSelf.historyView = transition.historyView
|
strongSelf.historyView = transition.historyView
|
||||||
|
|
||||||
let loadState: ChatHistoryNodeLoadState
|
let loadState: ChatHistoryNodeLoadState
|
||||||
@ -2541,6 +2589,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if unreadMessageRangeUpdated {
|
||||||
|
strongSelf.forEachVisibleMessageItemNode { itemNode in
|
||||||
|
itemNode.unreadMessageRangeUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strongSelf.hasActiveTransition = false
|
strongSelf.hasActiveTransition = false
|
||||||
strongSelf.dequeueHistoryViewTransitions()
|
strongSelf.dequeueHistoryViewTransitions()
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
|
|
||||||
private var currentSwipeAction: ChatControllerInteractionSwipeAction?
|
private var currentSwipeAction: ChatControllerInteractionSwipeAction?
|
||||||
|
|
||||||
|
private var wasPending: Bool = false
|
||||||
|
private var didChangeFromPendingToSent: Bool = false
|
||||||
|
|
||||||
required init() {
|
required init() {
|
||||||
self.contextSourceNode = ContextExtractedContentContainingNode()
|
self.contextSourceNode = ContextExtractedContentContainingNode()
|
||||||
self.containerNode = ContextControllerSourceNode()
|
self.containerNode = ContextControllerSourceNode()
|
||||||
@ -470,6 +473,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
|
|
||||||
override func setupItem(_ item: ChatMessageItem, synchronousLoad: Bool) {
|
override func setupItem(_ item: ChatMessageItem, synchronousLoad: Bool) {
|
||||||
super.setupItem(item, synchronousLoad: synchronousLoad)
|
super.setupItem(item, synchronousLoad: synchronousLoad)
|
||||||
|
|
||||||
|
if item.message.id.namespace == Namespaces.Message.Local {
|
||||||
|
self.wasPending = true
|
||||||
|
}
|
||||||
|
if self.wasPending && item.message.id.namespace != Namespaces.Message.Local {
|
||||||
|
self.didChangeFromPendingToSent = true
|
||||||
|
}
|
||||||
|
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let telegramFile = media as? TelegramMediaFile {
|
if let telegramFile = media as? TelegramMediaFile {
|
||||||
@ -526,7 +536,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: emojiFile, small: false, size: dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)), fitzModifier: fitzModifier, thumbnail: false, synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad)
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: emojiFile, small: false, size: dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)), fitzModifier: fitzModifier, thumbnail: false, synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad)
|
||||||
self.disposable.set(freeMediaFileInteractiveFetched(account: item.context.account, fileReference: .standalone(media: emojiFile)).start())
|
self.disposable.set(freeMediaFileInteractiveFetched(account: item.context.account, fileReference: .standalone(media: emojiFile)).start())
|
||||||
}
|
}
|
||||||
self.updateVisibility()
|
|
||||||
|
|
||||||
let textEmoji = item.message.text.strippedEmoji
|
let textEmoji = item.message.text.strippedEmoji
|
||||||
var additionalTextEmoji = textEmoji
|
var additionalTextEmoji = textEmoji
|
||||||
@ -551,6 +560,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.updateVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateVisibility() {
|
private func updateVisibility() {
|
||||||
@ -558,6 +569,30 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var file: TelegramMediaFile?
|
||||||
|
var playbackMode: AnimatedStickerPlaybackMode = .loop
|
||||||
|
var isEmoji = false
|
||||||
|
var fitzModifier: EmojiFitzModifier?
|
||||||
|
|
||||||
|
if let telegramFile = self.telegramFile {
|
||||||
|
file = telegramFile
|
||||||
|
if !item.controllerInteraction.stickerSettings.loopAnimatedStickers {
|
||||||
|
playbackMode = .once
|
||||||
|
}
|
||||||
|
} else if let emojiFile = self.emojiFile {
|
||||||
|
isEmoji = true
|
||||||
|
file = emojiFile
|
||||||
|
//if alreadySeen && emojiFile.resource is LocalFileReferenceMediaResource {
|
||||||
|
playbackMode = .still(.end)
|
||||||
|
//} else {
|
||||||
|
// playbackMode = .once
|
||||||
|
//}
|
||||||
|
let (_, fitz) = item.message.text.basicEmoji
|
||||||
|
if let fitz = fitz {
|
||||||
|
fitzModifier = EmojiFitzModifier(emoji: fitz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let isPlaying = self.visibilityStatus && !self.forceStopAnimations
|
let isPlaying = self.visibilityStatus && !self.forceStopAnimations
|
||||||
if let animationNode = self.animationNode as? AnimatedStickerNode {
|
if let animationNode = self.animationNode as? AnimatedStickerNode {
|
||||||
if !isPlaying {
|
if !isPlaying {
|
||||||
@ -583,51 +618,20 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
if self.isPlaying != isPlaying {
|
if self.isPlaying != isPlaying {
|
||||||
self.isPlaying = isPlaying
|
self.isPlaying = isPlaying
|
||||||
|
|
||||||
var alreadySeen = false
|
|
||||||
if isPlaying, let _ = self.emojiFile {
|
|
||||||
if item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
|
||||||
alreadySeen = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isPlaying && self.setupTimestamp == nil {
|
if isPlaying && self.setupTimestamp == nil {
|
||||||
self.setupTimestamp = CACurrentMediaTime()
|
self.setupTimestamp = CACurrentMediaTime()
|
||||||
}
|
}
|
||||||
animationNode.visibility = isPlaying
|
animationNode.visibility = isPlaying
|
||||||
|
|
||||||
if self.didSetUpAnimationNode && alreadySeen {
|
/*if self.didSetUpAnimationNode && alreadySeen {
|
||||||
if let emojiFile = self.emojiFile, emojiFile.resource is LocalFileReferenceMediaResource {
|
if let emojiFile = self.emojiFile, emojiFile.resource is LocalFileReferenceMediaResource {
|
||||||
} else {
|
} else {
|
||||||
animationNode.seekTo(.start)
|
animationNode.seekTo(.start)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if self.isPlaying && !self.didSetUpAnimationNode {
|
if self.isPlaying && !self.didSetUpAnimationNode {
|
||||||
self.didSetUpAnimationNode = true
|
self.didSetUpAnimationNode = true
|
||||||
|
|
||||||
var file: TelegramMediaFile?
|
|
||||||
var playbackMode: AnimatedStickerPlaybackMode = .loop
|
|
||||||
var isEmoji = false
|
|
||||||
var fitzModifier: EmojiFitzModifier?
|
|
||||||
|
|
||||||
if let telegramFile = self.telegramFile {
|
|
||||||
file = telegramFile
|
|
||||||
if !item.controllerInteraction.stickerSettings.loopAnimatedStickers {
|
|
||||||
playbackMode = .once
|
|
||||||
}
|
|
||||||
} else if let emojiFile = self.emojiFile {
|
|
||||||
isEmoji = true
|
|
||||||
file = emojiFile
|
|
||||||
if alreadySeen && emojiFile.resource is LocalFileReferenceMediaResource {
|
|
||||||
playbackMode = .still(.end)
|
|
||||||
} else {
|
|
||||||
playbackMode = .once
|
|
||||||
}
|
|
||||||
let (_, fitz) = item.message.text.basicEmoji
|
|
||||||
if let fitz = fitz {
|
|
||||||
fitzModifier = EmojiFitzModifier(emoji: fitz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let file = file {
|
if let file = file {
|
||||||
let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||||
@ -637,15 +641,39 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
let mode: AnimatedStickerMode = .direct(cachePathPrefix: pathPrefix)
|
let mode: AnimatedStickerMode = .direct(cachePathPrefix: pathPrefix)
|
||||||
self.animationSize = fittedSize
|
self.animationSize = fittedSize
|
||||||
animationNode.setup(source: AnimatedStickerResourceSource(account: item.context.account, resource: file.resource, fitzModifier: fitzModifier, isVideo: file.isVideoSticker), width: Int(fittedSize.width), height: Int(fittedSize.height), playbackMode: playbackMode, mode: mode)
|
animationNode.setup(source: AnimatedStickerResourceSource(account: item.context.account, resource: file.resource, fitzModifier: fitzModifier, isVideo: file.isVideoSticker), width: Int(fittedSize.width), height: Int(fittedSize.height), playbackMode: playbackMode, mode: mode)
|
||||||
|
}
|
||||||
if file.isPremiumSticker && !alreadySeen {
|
}
|
||||||
item.controllerInteraction.seenOneTimeAnimatedMedia.insert(item.message.id)
|
}
|
||||||
Queue.mainQueue().after(0.1) {
|
}
|
||||||
self.playPremiumStickerAnimation()
|
|
||||||
}
|
if isPlaying, let animationNode = self.animationNode as? AnimatedStickerNode {
|
||||||
|
var alreadySeen = true
|
||||||
|
if item.message.flags.contains(.Incoming) {
|
||||||
|
if let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] {
|
||||||
|
if unreadRange.contains(item.message.id.id) {
|
||||||
|
if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
||||||
|
alreadySeen = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if self.didChangeFromPendingToSent {
|
||||||
|
if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
||||||
|
alreadySeen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !alreadySeen {
|
||||||
|
item.controllerInteraction.seenOneTimeAnimatedMedia.insert(item.message.id)
|
||||||
|
if let file = file, file.isPremiumSticker {
|
||||||
|
Queue.mainQueue().after(0.1) {
|
||||||
|
self.playPremiumStickerAnimation()
|
||||||
|
}
|
||||||
|
} else if isEmoji {
|
||||||
|
animationNode.seekTo(.start)
|
||||||
|
animationNode.playOnce()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -655,7 +683,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.updateVisibility()
|
self.updateVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private var absoluteRect: (CGRect, CGSize)?
|
private var absoluteRect: (CGRect, CGSize)?
|
||||||
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
self.absoluteRect = (rect, containerSize)
|
self.absoluteRect = (rect, containerSize)
|
||||||
@ -2378,6 +2405,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func unreadMessageRangeUpdated() {
|
||||||
|
self.updateVisibility()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnimatedEmojiSoundsConfiguration {
|
struct AnimatedEmojiSoundsConfiguration {
|
||||||
|
@ -898,4 +898,7 @@ public class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unreadMessageRangeUpdated() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
attributedText = NSAttributedString(string: " ", font: textFont, textColor: messageTheme.primaryTextColor)
|
attributedText = NSAttributedString(string: " ", font: textFont, textColor: messageTheme.primaryTextColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let entities = entities {
|
/*if let entities = entities {
|
||||||
let updatedString = NSMutableAttributedString(attributedString: attributedText)
|
let updatedString = NSMutableAttributedString(attributedString: attributedText)
|
||||||
|
|
||||||
for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) {
|
for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) {
|
||||||
@ -368,48 +368,11 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
updatedAttributes[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(file: emojiFile)
|
updatedAttributes[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(file: emojiFile)
|
||||||
|
|
||||||
let insertString = NSAttributedString(string: "[\u{00a0}\u{00a0}]", attributes: updatedAttributes)
|
let insertString = NSAttributedString(string: "[\u{00a0}\u{00a0}]", attributes: updatedAttributes)
|
||||||
//updatedString.insert(insertString, at: NSRange(substringRange, in: updatedString.string).upperBound)
|
|
||||||
updatedString.replaceCharacters(in: range, with: insertString)
|
updatedString.replaceCharacters(in: range, with: insertString)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*var currentCount = 0
|
|
||||||
let updatedString = NSMutableAttributedString(attributedString: attributedText)
|
|
||||||
var startIndex = updatedString.string.startIndex
|
|
||||||
while true {
|
|
||||||
var hadUpdates = false
|
|
||||||
updatedString.string.enumerateSubstrings(in: 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 {
|
|
||||||
let currentDict = updatedString.attributes(at: NSRange(substringRange, in: updatedString.string).lowerBound, effectiveRange: nil)
|
|
||||||
var updatedAttributes: [NSAttributedString.Key: Any] = currentDict
|
|
||||||
updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor
|
|
||||||
updatedAttributes[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(file: emojiFile)
|
|
||||||
|
|
||||||
let insertString = NSAttributedString(string: "[\u{00a0}\u{00a0}\u{00a0}]", attributes: updatedAttributes)
|
|
||||||
//updatedString.insert(insertString, at: NSRange(substringRange, in: updatedString.string).upperBound)
|
|
||||||
updatedString.replaceCharacters(in: NSRange(substringRange, in: updatedString.string), with: insertString)
|
|
||||||
startIndex = substringRange.lowerBound
|
|
||||||
currentCount += 1
|
|
||||||
hadUpdates = true
|
|
||||||
stop = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hadUpdates || currentCount >= 10 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
attributedText = updatedString
|
attributedText = updatedString
|
||||||
}
|
}*/
|
||||||
|
|
||||||
let cutout: TextNodeCutout? = nil
|
let cutout: TextNodeCutout? = nil
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ private func commitEntity(_ utf16: String.UTF16View, _ type: CurrentEntityType,
|
|||||||
public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimatedEmojisInText: Int? = nil) -> [MessageTextEntity] {
|
public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimatedEmojisInText: Int? = nil) -> [MessageTextEntity] {
|
||||||
var entities: [MessageTextEntity] = []
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
if let maxAnimatedEmojisInText = maxAnimatedEmojisInText {
|
if let maxAnimatedEmojisInText = maxAnimatedEmojisInText, maxAnimatedEmojisInText != 0 {
|
||||||
var count = 0
|
var count = 0
|
||||||
text.string.enumerateSubstrings(in: text.string.startIndex ..< text.string.endIndex, options: [.byComposedCharacterSequences], { substring, substringRange, _, stop in
|
text.string.enumerateSubstrings(in: text.string.startIndex ..< text.string.endIndex, options: [.byComposedCharacterSequences], { substring, substringRange, _, stop in
|
||||||
if let substring = substring {
|
if let substring = substring {
|
||||||
@ -159,10 +159,7 @@ public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimate
|
|||||||
|
|
||||||
count += 1
|
count += 1
|
||||||
if count >= maxAnimatedEmojisInText {
|
if count >= maxAnimatedEmojisInText {
|
||||||
#if DEBUG
|
|
||||||
#else
|
|
||||||
stop = true
|
stop = true
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user