Merge commit 'acac317502496d98930a6e2ca375f343182b35e5'

This commit is contained in:
Ali 2022-08-03 21:26:31 +04:00
commit b7bc1854e6
6 changed files with 280 additions and 213 deletions

View File

@ -5,7 +5,7 @@ import AVFoundation
public extension UnicodeScalar {
var isEmoji: Bool {
switch self.value {
case 0x1F600...0x1F64F, 0x1F300...0x1F5FF, 0x1F680...0x1F6FF, 0x1F1E6...0x1F1FF, 0xE0020...0xE007F, 0xFE00...0xFE0F, 0x1F900...0x1F9FF, 0x1F018...0x1F0F5, 0x1F200...0x1F270, 65024...65039, 9100...9300, 8400...8447, 0x1F004, 0x1F18E, 0x1F191...0x1F19A, 0x1F5E8, 0x1FA70...0x1FA73, 0x1FA78...0x1FA7A, 0x1FA80...0x1FA82, 0x1FA90...0x1FA95, 0x1F382:
case 0x1F600...0x1F64F, 0x1F300...0x1F5FF, 0x1F680...0x1F6FF, 0x1F1E6...0x1F1FF, 0xE0020...0xE007F, 0xFE00...0xFE0F, 0x1F900...0x1F9FF, 0x1F018...0x1F0F5, 0x1F200...0x1F270, 65024...65039, 9100...9300, 8400...8447, 0x1F004, 0x1F18E, 0x1F191...0x1F19A, 0x1F5E8, 0x1FA70...0x1FA73, 0x1FA78...0x1FA7A, 0x1FA80...0x1FA82, 0x1FA90...0x1FA95, 0x1F382, 0x1FAF1, 0x1FAF2:
return true
case 0x2603, 0x265F, 0x267E, 0x2692, 0x26C4, 0x26C8, 0x26CE, 0x26CF, 0x26D1...0x26D3, 0x26E9, 0x26F0...0x26F9, 0x2705, 0x270A, 0x270B, 0x2728, 0x274E, 0x2753...0x2755, 0x274C, 0x2795...0x2797, 0x27B0, 0x27BF:
return true

View File

@ -492,7 +492,10 @@ class PremiumStarComponent: Component {
}
}
let from = node.presentation.eulerAngles
var from = node.presentation.eulerAngles
if abs(from.y - .pi * 2.0) < 0.001 {
from.y = 0.0
}
node.removeAnimation(forKey: "tapRotate")
var toValue: Float = smallAngle ? 0.0 : .pi * 2.0
@ -505,9 +508,9 @@ class PremiumStarComponent: Component {
let to = SCNVector3(x: 0.0, y: toValue, z: 0.0)
let distance = rad2deg(to.y - from.y)
guard !distance.isZero else {
return
}
// guard !distance.isZero else {
// return
// }
let springAnimation = CASpringAnimation(keyPath: "eulerAngles")
springAnimation.fromValue = NSValue(scnVector3: from)
@ -517,7 +520,11 @@ class PremiumStarComponent: Component {
springAnimation.damping = 5.8
springAnimation.duration = springAnimation.settlingDuration * 0.75
springAnimation.initialVelocity = velocity.flatMap { abs($0 / CGFloat(distance)) } ?? 1.7
springAnimation.completion = { [weak node] finished in
if finished {
node?.eulerAngles = SCNVector3(x: 0.0, y: 0.0, z: 0.0)
}
}
node.addAnimation(springAnimation, forKey: "rotate")
}

View File

@ -411,7 +411,7 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings:
}
}
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool, isPremium: Bool) -> [PrivacyAndSecurityEntry] {
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool, isPremiumDisabled: Bool, isPremium: Bool) -> [PrivacyAndSecurityEntry] {
var entries: [PrivacyAndSecurityEntry] = []
entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)")))
@ -449,7 +449,9 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.presence)))
entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.profilePhoto)))
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls)))
if !isPremiumDisabled {
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium))
}
entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.forwards)))
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations)))
@ -458,7 +460,9 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, presentationData.strings.Channel_NotificationLoading))
entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, presentationData.strings.Channel_NotificationLoading))
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading))
if !isPremiumDisabled {
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, !isPremium))
}
entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, presentationData.strings.Channel_NotificationLoading))
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, presentationData.strings.Channel_NotificationLoading))
entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp))
@ -772,10 +776,14 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
let hapticFeedback = HapticFeedback()
hapticFeedback.impact()
var alreadyPresented = false
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Privacy_VoiceMessages_Tooltip), elevatedLayout: false, animateInAsReplacement: false, action: { action in
if action == .info {
if !alreadyPresented {
let controller = PremiumIntroScreen(context: context, source: .settings)
pushControllerImpl?(controller, true)
alreadyPresented = true
}
return true
}
return false
@ -961,8 +969,9 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let isPremium = accountPeer?.isPremium ?? false
let isPremiumDisabled = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }).isPremiumDisabled
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremium: isPremium), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremiumDisabled: isPremiumDisabled, isPremium: isPremium), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
return (controllerState, (listState, arguments))
}

View File

@ -139,8 +139,8 @@ func chatHistoryEntriesForView(
contentTypeHint = .animatedEmoji
} else if stickersEnabled && message.text.count == 1, let _ = associatedData.animatedEmojiStickers[message.text.basicEmoji.0], (message.textEntitiesAttribute?.entities.isEmpty ?? true) {
contentTypeHint = .animatedEmoji
} else if message.text.count < 10 && messageIsElligibleForLargeEmoji(message) {
contentTypeHint = .largeEmoji
} else if messageIsElligibleForLargeEmoji(message) {
contentTypeHint = .animatedEmoji
}
}
@ -218,10 +218,12 @@ func chatHistoryEntriesForView(
var contentTypeHint: ChatMessageEntryContentType = .generic
if presentationData.largeEmoji, topMessage.media.isEmpty {
if stickersEnabled && topMessage.text.count == 1, let _ = associatedData.animatedEmojiStickers[topMessage.text.basicEmoji.0] {
if stickersEnabled && messageIsElligibleForLargeCustomEmoji(topMessage) {
contentTypeHint = .animatedEmoji
} else if stickersEnabled && topMessage.text.count == 1, let _ = associatedData.animatedEmojiStickers[topMessage.text.basicEmoji.0] {
contentTypeHint = .animatedEmoji
} else if messageIsElligibleForLargeEmoji(topMessage) {
contentTypeHint = .animatedEmoji
} else if topMessage.text.count < 10 && messageIsElligibleForLargeEmoji(topMessage) {
contentTypeHint = .largeEmoji
}
}

View File

@ -543,16 +543,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
var emojiFile: TelegramMediaFile?
var emojiString: String?
if let entities = item.message.textEntitiesAttribute?.entities {
if entities.count == 1, case let .CustomEmoji(_, fileId) = entities[0].type {
if let file = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile {
emojiFile = file
}
} else if messageIsElligibleForLargeCustomEmoji(item.message) {
if messageIsElligibleForLargeCustomEmoji(item.message) || (item.message.text.count > 1 && messageIsElligibleForLargeEmoji(item.message)) {
emojiString = item.message.text
}
}
if emojiFile == nil && emojiString == nil {
emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file
@ -566,12 +559,18 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
} else if self.emojiFile?.id != emojiFile?.id {
self.emojiFile = emojiFile
if let emojiFile = emojiFile {
let dimensions = emojiFile.dimensions ?? PixelDimensions(width: 512, height: 512)
var dimensions = emojiFile.dimensions ?? PixelDimensions(width: 512, height: 512)
if emojiFile.isCustomEmoji {
dimensions = PixelDimensions(dimensions.cgSize.aspectFitted(CGSize(width: 512.0, height: 512.0)))
}
var fitzModifier: EmojiFitzModifier?
if let fitz = fitz {
fitzModifier = EmojiFitzModifier(emoji: fitz)
}
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)
let fillSize = emojiFile.isCustomEmoji ? CGSize(width: 512.0, height: 512.0) : CGSize(width: 384.0, height: 384.0)
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: emojiFile, small: false, size: dimensions.cgSize.aspectFilled(fillSize), fitzModifier: fitzModifier, thumbnail: false, synchronousLoad: synchronousLoad), attemptSynchronously: synchronousLoad)
self.disposable.set(freeMediaFileInteractiveFetched(account: item.context.account, fileReference: .standalone(media: emojiFile)).start())
}
@ -667,7 +666,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
self.didSetUpAnimationNode = true
if let file = file {
let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512)
var dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512)
if file.isCustomEmoji {
dimensions = PixelDimensions(dimensions.cgSize.aspectFitted(CGSize(width: 512.0, height: 512.0)))
}
let fittedSize = isEmoji ? dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)) : dimensions.cgSize.aspectFitted(CGSize(width: 384.0, height: 384.0))
let pathPrefix = item.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(file.resource.id)
@ -703,7 +705,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if !alreadySeen {
item.controllerInteraction.seenOneTimeAnimatedMedia.insert(item.message.id)
if let file = file, file.isCustomEmoji {
if let emojiString = self.emojiString, emojiString.count == 1 {
self.playAdditionalEmojiAnimation(index: 1)
} else if let file = file, file.isPremiumSticker {
Queue.mainQueue().after(0.1) {
@ -940,7 +942,11 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
isEmoji = true
let displaySize = CGSize(width: floor(displaySize.width * item.presentationData.animatedEmojiScale), height: floor(displaySize.height * item.presentationData.animatedEmojiScale))
if let dimensions = emojiFile.dimensions {
if var dimensions = emojiFile.dimensions {
if emojiFile.isCustomEmoji {
dimensions = PixelDimensions(dimensions.cgSize.aspectFitted(CGSize(width: 512.0, height: 512.0)))
}
imageSize = CGSize(width: displaySize.width * CGFloat(dimensions.width) / 512.0, height: displaySize.height * CGFloat(dimensions.height) / 512.0)
} else if let thumbnailSize = emojiFile.previewRepresentations.first?.dimensions {
imageSize = thumbnailSize.cgSize.aspectFitted(displaySize)
@ -961,9 +967,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
deliveryFailedInset += 24.0
}
if item.message.forwardInfo != nil || item.message.attributes.first(where: { $0 is ReplyMessageAttribute }) != nil {
tmpWidth -= 60.0
}
tmpWidth -= deliveryFailedInset
let maximumContentWidth = floor(tmpWidth - layoutConstants.bubble.edgeInset - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - layoutConstants.bubble.contentInsets.right - avatarInset)
let maximumContentWidth = floor(tmpWidth - layoutConstants.bubble.edgeInset - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - layoutConstants.bubble.contentInsets.right - avatarInset) - 70.0
let font = Font.regular(fontSizeForEmojiString(item.message.text))
let attributedText = stringWithAppliedEntities(item.message.text, entities: item.message.textEntitiesAttribute?.entities ?? [], baseColor: .black, linkColor: .black, baseFont: font, linkFont: font, boldFont: font, italicFont: font, boldItalicFont: font, fixedFont: font, blockQuoteFont: font, message: item.message)
@ -1060,7 +1070,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
var needsReplyBackground = false
var replyMarkup: ReplyMarkupMessageAttribute?
let availableContentWidth = max(60.0, params.width - params.leftInset - params.rightInset - max(imageSize.width, 160.0) - 20.0 - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left)
let availableContentWidth = min(120.0, max(60.0, params.width - params.leftInset - params.rightInset - max(imageSize.width, 160.0) - 20.0 - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left))
var ignoreForward = false
if let forwardInfo = item.message.forwardInfo {
@ -1632,7 +1643,16 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
}
private func commitEnqueuedAnimations() {
guard let item = self.item, let file = self.emojiFile, !self.enqueuedAdditionalAnimations.isEmpty else {
guard let item = self.item, !self.enqueuedAdditionalAnimations.isEmpty else {
return
}
var emojiFile = self.emojiFile
if emojiFile == nil {
emojiFile = item.message.associatedMedia.first?.value as? TelegramMediaFile
}
guard let file = emojiFile else {
return
}
@ -1744,7 +1764,21 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
}
let source = AnimatedStickerResourceSource(account: item.context.account, resource: resource, fitzModifier: nil)
guard let animationSize = self.animationSize, let animationNode = self.animationNode else {
let animationSize: CGSize?
let animationNodeFrame: CGRect?
if let size = self.animationSize, let node = self.animationNode {
animationSize = size
animationNodeFrame = node.frame
} else if let _ = self.emojiString {
animationSize = CGSize(width: 384.0, height: 384.0)
animationNodeFrame = self.textNode.textNode.frame
} else {
animationSize = nil
animationNodeFrame = nil
}
guard let animationSize = animationSize, let animationNodeFrame = animationNodeFrame else {
return
}
if self.additionalAnimationNodes.count >= 4 {
@ -1762,8 +1796,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
overlayMeshAnimationNode = current
} else {
if let animationView = MeshRenderer() {
let animationFrame = animationNode.frame.insetBy(dx: -animationNode.frame.width, dy: -animationNode.frame.height)
.offsetBy(dx: incomingMessage ? animationNode.frame.width - 10.0 : -animationNode.frame.width + 10.0, dy: 0.0)
let animationFrame = animationNodeFrame.insetBy(dx: -animationNodeFrame.width, dy: -animationNodeFrame.height)
.offsetBy(dx: incomingMessage ? animationNodeFrame.width - 10.0 : -animationNodeFrame.width + 10.0, dy: 0.0)
animationView.frame = animationFrame
animationView.allAnimationsCompleted = { [weak transitionNode, weak animationView, weak self] in
@ -1794,10 +1828,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
var animationFrame: CGRect
if isStickerEffect {
let scale: CGFloat = 0.245
animationFrame = animationNode.frame.offsetBy(dx: incomingMessage ? animationNode.frame.width * scale - 21.0 : -animationNode.frame.width * scale + 21.0, dy: -1.0).insetBy(dx: -animationNode.frame.width * scale, dy: -animationNode.frame.height * scale)
animationFrame = animationNodeFrame.offsetBy(dx: incomingMessage ? animationNodeFrame.width * scale - 21.0 : -animationNodeFrame.width * scale + 21.0, dy: -1.0).insetBy(dx: -animationNodeFrame.width * scale, dy: -animationNodeFrame.height * scale)
} else {
animationFrame = animationNode.frame.insetBy(dx: -animationNode.frame.width, dy: -animationNode.frame.height)
.offsetBy(dx: incomingMessage ? animationNode.frame.width - 10.0 : -animationNode.frame.width + 10.0, dy: 0.0)
animationFrame = animationNodeFrame.insetBy(dx: -animationNodeFrame.width, dy: -animationNodeFrame.height)
.offsetBy(dx: incomingMessage ? animationNodeFrame.width - 10.0 : -animationNodeFrame.width + 10.0, dy: 0.0)
animationFrame = animationFrame.offsetBy(dx: CGFloat.random(in: -30.0 ... 30.0), dy: CGFloat.random(in: -30.0 ... 30.0))
}
@ -1883,40 +1917,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
}
if let item = self.item, self.imageNode.frame.contains(location) {
if let file = self.telegramFile {
let noPremium = item.message.attributes.contains(where: { attribute in
if attribute is NonPremiumMessageAttribute {
return true
} else {
return false
}
})
if file.isPremiumSticker && !noPremium {
return .optionalAction({
if self.additionalAnimationNodes.isEmpty {
self.playedPremiumStickerAnimation = false
self.playPremiumStickerAnimation()
} else {
item.controllerInteraction.displayPremiumStickerTooltip(file, item.message)
}
})
} else {
return .optionalAction({
let _ = item.controllerInteraction.openMessage(item.message, .default)
})
}
} else if let dice = self.telegramDice {
return .optionalAction({
item.controllerInteraction.displayDiceTooltip(dice)
})
} else if let emojiFile = self.emojiFile {
if let animationNode = self.animationNode as? AnimatedStickerNode, let _ = recognizer {
var shouldPlay = false
if !animationNode.isPlaying && !emojiFile.isCustomEmoji {
shouldPlay = true
}
let emojiTapAction: (Bool) -> InternalBubbleTapAction? = { shouldPlay in
let beatingHearts: [UInt32] = [0x2764, 0x1F90E, 0x1F9E1, 0x1F499, 0x1F49A, 0x1F49C, 0x1F49B, 0x1F5A4, 0x1F90D]
let heart = 0x2764
let peach = 0x1F351
@ -2035,13 +2036,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
self.playAdditionalEmojiAnimation(index: index)
}
}
} else if emojiFile.isCustomEmoji {
} else if let emojiString = self.emojiString, emojiString.count == 1 {
let _ = item.controllerInteraction.openMessage(item.message, .default)
}
if shouldPlay {
let _ = (appConfiguration
|> deliverOnMainQueue).start(next: { [weak self, weak animationNode] appConfiguration in
|> deliverOnMainQueue).start(next: { [weak self] appConfiguration in
guard let strongSelf = self else {
return
}
@ -2059,7 +2060,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
strongSelf.mediaPlayer = mediaPlayer
strongSelf.mediaStatusDisposable.set((mediaPlayer.status
|> deliverOnMainQueue).start(next: { [weak self, weak animationNode] status in
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self {
if let haptic = haptic, !haptic.active {
haptic.start(time: 0.0)
@ -2067,7 +2068,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
switch status.status {
case .playing:
animationNode?.play(firstFrame: false, fromIndex: nil)
if let animationNode = strongSelf.animationNode as? AnimatedStickerNode {
animationNode.play(firstFrame: false, fromIndex: nil)
}
strongSelf.mediaStatusDisposable.set(nil)
default:
break
@ -2081,12 +2084,56 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if let haptic = haptic, !haptic.active {
haptic.start(time: 0.0)
}
animationNode?.play(firstFrame: false, fromIndex: nil)
if let animationNode = strongSelf.animationNode as? AnimatedStickerNode {
animationNode.play(firstFrame: false, fromIndex: nil)
}
}
})
}
})
}
return nil
}
if let emojiString = self.emojiString, emojiString.count == 1 {
return emojiTapAction(false)
}
if let file = self.telegramFile {
let noPremium = item.message.attributes.contains(where: { attribute in
if attribute is NonPremiumMessageAttribute {
return true
} else {
return false
}
})
if file.isPremiumSticker && !noPremium {
return .optionalAction({
if self.additionalAnimationNodes.isEmpty {
self.playedPremiumStickerAnimation = false
self.playPremiumStickerAnimation()
} else {
item.controllerInteraction.displayPremiumStickerTooltip(file, item.message)
}
})
} else {
return .optionalAction({
let _ = item.controllerInteraction.openMessage(item.message, .default)
})
}
} else if let dice = self.telegramDice {
return .optionalAction({
item.controllerInteraction.displayDiceTooltip(dice)
})
} else if let emojiFile = self.emojiFile {
if let animationNode = self.animationNode as? AnimatedStickerNode, let _ = recognizer {
var shouldPlay = false
if !animationNode.isPlaying && !emojiFile.isCustomEmoji {
shouldPlay = true
}
if let result = emojiTapAction(shouldPlay) {
return result
}
}
}
}
@ -2592,7 +2639,7 @@ private func fontSizeForEmojiString(_ string: String) -> CGFloat {
var maxLineLength = 0
for line in lines {
maxLineLength = max(maxLineLength, line.count)
maxLineLength = max(maxLineLength, line.replacingOccurrences(of: " ", with: "").count)
}
let linesCount = lines.count
@ -2602,6 +2649,8 @@ private func fontSizeForEmojiString(_ string: String) -> CGFloat {
let basicSize: CGFloat = 94.0
let multiplier: CGFloat
switch length {
case 1:
multiplier = 1.0
case 2:
multiplier = 0.7
case 3:

View File

@ -192,7 +192,7 @@ private func matchingEmojiEntry(_ emoji: String) -> (UInt8, UInt8, UInt8)? {
}
func messageIsElligibleForLargeEmoji(_ message: Message) -> Bool {
if !message.text.isEmpty && message.text.containsOnlyEmoji && message.text.emojis.count < 6 {
if !message.text.isEmpty && message.text.containsOnlyEmoji {
if !(message.textEntitiesAttribute?.entities.isEmpty ?? true) {
return false
}