mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 14:02:48 +00:00
Fixed emoji determination
This commit is contained in:
parent
1b7f876c3f
commit
69a824f26a
@ -39,7 +39,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
|
|||||||
switch self {
|
switch self {
|
||||||
case let .MessageEntry(message, presentationData, _, _, _, _):
|
case let .MessageEntry(message, presentationData, _, _, _, _):
|
||||||
var type = 2
|
var type = 2
|
||||||
if presentationData.largeEmoji && message.elligibleForLargeEmoji {
|
if presentationData.largeEmoji && message.elligibleForLargeEmoji && messageTextIsElligibleForLargeEmoji(message.text) {
|
||||||
type = 3
|
type = 3
|
||||||
}
|
}
|
||||||
return UInt64(message.stableId) | ((UInt64(type) << 40))
|
return UInt64(message.stableId) | ((UInt64(type) << 40))
|
||||||
|
|||||||
@ -724,11 +724,13 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
switch contentData {
|
switch contentData {
|
||||||
case let .chat(itemPeer, peer, _, messageText):
|
case let .chat(itemPeer, peer, _, messageText):
|
||||||
|
let messageText = messageText.replacingOccurrences(of: "\n\n", with: " ")
|
||||||
|
|
||||||
if inlineAuthorPrefix == nil, let embeddedState = embeddedState as? ChatEmbeddedInterfaceState {
|
if inlineAuthorPrefix == nil, let embeddedState = embeddedState as? ChatEmbeddedInterfaceState {
|
||||||
hasDraft = true
|
hasDraft = true
|
||||||
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
|
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
|
||||||
|
|
||||||
attributedText = NSAttributedString(string: embeddedState.text.string, font: textFont, textColor: theme.messageTextColor)
|
attributedText = NSAttributedString(string: embeddedState.text.string.replacingOccurrences(of: "\n\n", with: " "), font: textFont, textColor: theme.messageTextColor)
|
||||||
} else if let message = message {
|
} else if let message = message {
|
||||||
if let inlineAuthorPrefix = inlineAuthorPrefix {
|
if let inlineAuthorPrefix = inlineAuthorPrefix {
|
||||||
let composedString = NSMutableAttributedString()
|
let composedString = NSMutableAttributedString()
|
||||||
|
|||||||
@ -352,7 +352,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.presentationData.largeEmoji && self.message.elligibleForLargeEmoji && viewClassName == ChatMessageBubbleItemNode.self {
|
if viewClassName == ChatMessageBubbleItemNode.self && self.presentationData.largeEmoji && self.message.elligibleForLargeEmoji && messageTextIsElligibleForLargeEmoji(message.text) {
|
||||||
viewClassName = ChatMessageStickerItemNode.self
|
viewClassName = ChatMessageStickerItemNode.self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -192,17 +192,26 @@ private func matchingEmojiEntry(_ emoji: String) -> (UInt8, UInt8, UInt8)? {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func messageTextIsElligibleForLargeEmoji(_ emoji: String) -> Bool {
|
||||||
|
for emoji in emoji.emojis {
|
||||||
|
if let _ = matchingEmojiEntry(emoji) {
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func largeEmoji(postbox: Postbox, emoji: String, outline: Bool = true) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
func largeEmoji(postbox: Postbox, emoji: String, outline: Bool = true) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||||
var dataSignals: [Signal<MediaResourceData, NoError>] = []
|
var dataSignals: [Signal<MediaResourceData, NoError>] = []
|
||||||
for emoji in emoji.emojis {
|
for emoji in emoji.emojis {
|
||||||
if let entry = matchingEmojiEntry(emoji) {
|
|
||||||
let thumbnailResource = EmojiThumbnailResource(emoji: emoji)
|
let thumbnailResource = EmojiThumbnailResource(emoji: emoji)
|
||||||
let thumbnailRepresentation = CachedEmojiThumbnailRepresentation(outline: outline)
|
let thumbnailRepresentation = CachedEmojiThumbnailRepresentation(outline: outline)
|
||||||
|
let thumbnailSignal = postbox.mediaBox.cachedResourceRepresentation(thumbnailResource, representation: thumbnailRepresentation, complete: true, fetch: true)
|
||||||
|
|
||||||
|
if let entry = matchingEmojiEntry(emoji) {
|
||||||
let spriteResource = EmojiSpriteResource(packId: entry.0, stickerId: entry.1)
|
let spriteResource = EmojiSpriteResource(packId: entry.0, stickerId: entry.1)
|
||||||
let representation = CachedEmojiRepresentation(tile: entry.2, outline: outline)
|
let representation = CachedEmojiRepresentation(tile: entry.2, outline: outline)
|
||||||
|
|
||||||
let thumbnailSignal = postbox.mediaBox.cachedResourceRepresentation(thumbnailResource, representation: thumbnailRepresentation, complete: true, fetch: true)
|
|
||||||
let signal: Signal<MediaResourceData?, NoError> = .single(nil) |> then(postbox.mediaBox.cachedResourceRepresentation(spriteResource, representation: representation, complete: true, fetch: true) |> map(Optional.init))
|
let signal: Signal<MediaResourceData?, NoError> = .single(nil) |> then(postbox.mediaBox.cachedResourceRepresentation(spriteResource, representation: representation, complete: true, fetch: true) |> map(Optional.init))
|
||||||
|
|
||||||
let dataSignal = thumbnailSignal
|
let dataSignal = thumbnailSignal
|
||||||
@ -217,6 +226,8 @@ func largeEmoji(postbox: Postbox, emoji: String, outline: Bool = true) -> Signal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataSignals.append(dataSignal)
|
dataSignals.append(dataSignal)
|
||||||
|
} else {
|
||||||
|
dataSignals.append(thumbnailSignal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,11 @@ import CoreText
|
|||||||
|
|
||||||
extension UnicodeScalar {
|
extension UnicodeScalar {
|
||||||
var isEmoji: Bool {
|
var isEmoji: Bool {
|
||||||
switch value {
|
switch self.value {
|
||||||
case 0x1F600...0x1F64F, // Emoticons
|
case 0x1F600...0x1F64F, // Emoticons
|
||||||
0x1F300...0x1F5FF, // Misc Symbols and Pictographs
|
0x1F300...0x1F5FF, // Misc Symbols and Pictographs
|
||||||
0x1F680...0x1F6FF, // Transport and Map
|
0x1F680...0x1F6FF, // Transport and Map
|
||||||
0x1F1E6...0x1F1FF, // Regional country flags
|
0x1F1E6...0x1F1FF, // Regional country flags
|
||||||
0x2600...0x26FF, // Misc symbols
|
|
||||||
0x2700...0x27BF, // Dingbats
|
|
||||||
0xE0020...0xE007F, // Tags
|
0xE0020...0xE007F, // Tags
|
||||||
0xFE00...0xFE0F, // Variation Selectors
|
0xFE00...0xFE0F, // Variation Selectors
|
||||||
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
|
0x1F900...0x1F9FF, // Supplemental Symbols and Pictographs
|
||||||
@ -23,8 +21,18 @@ extension UnicodeScalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var maybeEmoji: Bool {
|
||||||
|
switch self.value {
|
||||||
|
case 0x2600...0x26FF, // Misc symbols
|
||||||
|
0x2700...0x27BF: // Dingbats
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var isZeroWidthJoiner: Bool {
|
var isZeroWidthJoiner: Bool {
|
||||||
return value == 8205
|
return self.value == 8205
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,34 +45,44 @@ extension String {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
var glyphCount: Int {
|
|
||||||
let richText = NSAttributedString(string: self)
|
|
||||||
let line = CTLineCreateWithAttributedString(richText)
|
|
||||||
return CTLineGetGlyphCount(line)
|
|
||||||
}
|
|
||||||
|
|
||||||
var isSingleEmoji: Bool {
|
var isSingleEmoji: Bool {
|
||||||
return glyphCount == 1 && containsEmoji
|
return self.emojis.count == 1 && self.containsEmoji
|
||||||
}
|
}
|
||||||
|
|
||||||
var containsEmoji: Bool {
|
var containsEmoji: Bool {
|
||||||
return unicodeScalars.contains { $0.isEmoji }
|
return self.unicodeScalars.contains { $0.isEmoji }
|
||||||
}
|
}
|
||||||
|
|
||||||
var containsOnlyEmoji: Bool {
|
var containsOnlyEmoji: Bool {
|
||||||
return !isEmpty && !unicodeScalars.contains(where: {
|
guard !self.isEmpty else {
|
||||||
!$0.isEmoji && !$0.isZeroWidthJoiner
|
return false
|
||||||
})
|
}
|
||||||
|
var nextShouldBeFE0F = false
|
||||||
|
for scalar in self.unicodeScalars {
|
||||||
|
if nextShouldBeFE0F {
|
||||||
|
if scalar.value == 0xfe0f {
|
||||||
|
nextShouldBeFE0F = false
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scalar.maybeEmoji {
|
||||||
|
nextShouldBeFE0F = true
|
||||||
|
}
|
||||||
|
else if !scalar.isEmoji && !scalar.isZeroWidthJoiner {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !nextShouldBeFE0F
|
||||||
}
|
}
|
||||||
|
|
||||||
// The next tricks are mostly to demonstrate how tricky it can be to determine emoji's
|
|
||||||
// If anyone has suggestions how to improve this, please let me know
|
|
||||||
var emojiString: String {
|
var emojiString: String {
|
||||||
return emojiScalars.map { String($0) }.reduce("", +)
|
return self.emojiScalars.map { String($0) }.reduce("", +)
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstEmoji: String {
|
var firstEmoji: String {
|
||||||
if let first = emojiScalars.first {
|
if let first = self.emojiScalars.first {
|
||||||
return String(first)
|
return String(first)
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
@ -84,7 +102,7 @@ extension String {
|
|||||||
fileprivate var emojiScalars: [UnicodeScalar] {
|
fileprivate var emojiScalars: [UnicodeScalar] {
|
||||||
var chars: [UnicodeScalar] = []
|
var chars: [UnicodeScalar] = []
|
||||||
var previous: UnicodeScalar?
|
var previous: UnicodeScalar?
|
||||||
for cur in unicodeScalars {
|
for cur in self.unicodeScalars {
|
||||||
if let previous = previous, previous.isZeroWidthJoiner && cur.isEmoji {
|
if let previous = previous, previous.isZeroWidthJoiner && cur.isEmoji {
|
||||||
chars.append(previous)
|
chars.append(previous)
|
||||||
chars.append(cur)
|
chars.append(cur)
|
||||||
|
|||||||
@ -158,15 +158,24 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var size = validLayout.size
|
||||||
|
if case .compact = validLayout.metrics.widthClass, size.width > size.height {
|
||||||
|
size = CGSize(width: size.height, height: size.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let background = self.background, background.size == size {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch self.wallpaper {
|
switch self.wallpaper {
|
||||||
case .image, .file:
|
case .image, .file:
|
||||||
if let image = chatControllerBackgroundImage(wallpaper: self.wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, composed: false) {
|
if let image = chatControllerBackgroundImage(wallpaper: self.wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, composed: false) {
|
||||||
self.background = ImageBasedPasscodeBackground(image: image, size: validLayout.size)
|
self.background = ImageBasedPasscodeBackground(image: image, size: size)
|
||||||
} else {
|
} else {
|
||||||
self.background = DefaultPasscodeBackground(size: validLayout.size)
|
self.background = DefaultPasscodeBackground(size: size)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
self.background = DefaultPasscodeBackground(size: validLayout.size)
|
self.background = DefaultPasscodeBackground(size: size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let background = self.background {
|
if let background = self.background {
|
||||||
@ -313,12 +322,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let hadValidLayout = self.validLayout != nil
|
|
||||||
self.validLayout = layout
|
self.validLayout = layout
|
||||||
|
|
||||||
if !hadValidLayout {
|
|
||||||
self.updateBackground()
|
self.updateBackground()
|
||||||
}
|
|
||||||
|
|
||||||
if layout.size.width == 320.0 {
|
if layout.size.width == 320.0 {
|
||||||
self.iconNode.alpha = 0.0
|
self.iconNode.alpha = 0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user