String+TUIEmoji.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //
  2. // String+TUIEmoji.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/12/17.
  6. //
  7. import Foundation
  8. private class LNEmojiDescContent {
  9. var range: NSRange
  10. var string: String
  11. init(range: NSRange, string: String) {
  12. self.range = range
  13. self.string = string
  14. }
  15. }
  16. private class LNEnojiImageContent {
  17. var range: NSRange
  18. var string: NSAttributedString
  19. init(range: NSRange, string: NSAttributedString) {
  20. self.range = range
  21. self.string = string
  22. }
  23. }
  24. extension String {
  25. private static var regex_emoji = "\\[[a-zA-Z0-9_\\u4e00-\\u9fa5]+\\]"
  26. var getEmojiDescContent: String {
  27. var content = self
  28. guard let emojiGroup = LNIMEmojiManager.shared.emojiGroup else { return content }
  29. let re = try? NSRegularExpression(pattern: Self.regex_emoji, options: .caseInsensitive)
  30. guard let re else { return content }
  31. let resultArray = re.matches(in: content, options: [], range: .init(location: 0, length: content.count))
  32. var waitingReplaceM: [LNEmojiDescContent] = []
  33. for match in resultArray {
  34. guard let range = Range(match.range, in: content) else {
  35. continue
  36. }
  37. let subStr = String(content[range])
  38. guard let emoji = emojiGroup.emojiFor(subStr) else { continue }
  39. let text = emoji.localizableName.isEmpty ? emoji.name : emoji.localizableName
  40. let content = LNEmojiDescContent(range: match.range, string: text)
  41. waitingReplaceM.append(content)
  42. }
  43. guard !waitingReplaceM.isEmpty else { return content }
  44. for item in waitingReplaceM.reversed() {
  45. guard let range = Range(item.range, in: content) else { continue }
  46. content = content.replacingCharacters(in: range, with: item.string)
  47. }
  48. return content
  49. }
  50. func getEmojiString(with font: UIFont) -> NSMutableAttributedString {
  51. let content = NSMutableAttributedString(string: self)
  52. guard let emojiGroup = LNIMEmojiManager.shared.emojiGroup else { return content }
  53. let re = try? NSRegularExpression(pattern: Self.regex_emoji, options: .caseInsensitive)
  54. guard let re else { return content }
  55. let resultArray = re.matches(in: self, options: [], range: .init(location: 0, length: count))
  56. var waitingReplaceM: [LNEnojiImageContent] = []
  57. for match in resultArray {
  58. guard let range = Range(match.range, in: self) else {
  59. continue
  60. }
  61. let subStr = String(self[range])
  62. guard let emoji = emojiGroup.emojiFor(subStr) else { continue }
  63. let attachment = LNIMChatEmojiAttachment()
  64. attachment.name = emoji.name
  65. attachment.font = font
  66. attachment.image = LNIMEmojiManager.shared.getFaceFromCache(path: emoji.path)
  67. let attachStr = NSAttributedString(attachment: attachment)
  68. let content = LNEnojiImageContent(range: match.range, string: attachStr)
  69. waitingReplaceM.append(content)
  70. }
  71. guard !waitingReplaceM.isEmpty else { return content }
  72. for item in waitingReplaceM.reversed() {
  73. content.replaceCharacters(in: item.range, with: item.string)
  74. }
  75. return content
  76. }
  77. }
  78. extension NSAttributedString {
  79. var toEmojiContent: String {
  80. let sourceStr = NSMutableAttributedString(attributedString: self)
  81. var waitingReplaceM: [LNEmojiDescContent] = []
  82. sourceStr.enumerateAttribute(.attachment, in: .init(location: 0, length: sourceStr.length))
  83. { value, range, _ in
  84. if let emoji = value as? LNIMChatEmojiAttachment {
  85. waitingReplaceM.append(LNEmojiDescContent(range: range, string: emoji.name))
  86. }
  87. }
  88. for item in waitingReplaceM.reversed() {
  89. sourceStr.replaceCharacters(in: item.range, with: item.string)
  90. }
  91. return sourceStr.string
  92. }
  93. }