| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- //
- // LNIMEmojiManager.swift
- // Lanu
- //
- // Created by OneeChan on 2025/12/18.
- //
- import Foundation
- private class LNEmojiConfig: Codable {
- var face_name: String = ""
- var face_file: String = ""
- var face_id: String = ""
- }
- class LNIMEmojiManager {
- static let shared = LNIMEmojiManager()
- private let resourcePath = URL(fileURLWithPath: Bundle.main.path(forResource: "TUIChatFace", ofType: "bundle")!)
- private var recentEmoji: [String] = [] {
- didSet {
- LNUserDefaults[.imRecentEmojis] = recentEmoji
- }
- }
-
- private(set) var emojiGroup: LNEmojiGroup?
- var recentGroup: LNEmojiGroup? {
- guard !recentEmoji.isEmpty else { return nil }
- let emojis = recentEmoji.compactMap {
- emojiGroup?.emojiFor($0)
- }
- guard !emojis.isEmpty else { return nil }
-
- let group = LNEmojiGroup()
- group.emojis = emojis
- group.groupName = TIMLocalizedText.shared.commonText("TUIChatFaceGroupRecentEmojiName")
- return group
- }
-
- private var faceCache: [String: UIImage] = [:]
-
- private init() {
- DispatchQueue.global().async { [weak self] in
- guard let self else { return }
- reloadEmoji()
- loadRecent()
- }
- }
-
- func addRecentEmoji(name: String) {
- if recentEmoji.contains(name) {
- recentEmoji.removeAll { $0 == name }
- } else {
- recentEmoji.removeLast()
- }
- recentEmoji.insert(name, at: 0)
- }
-
- func getFaceFromCache(path: String?) -> UIImage? {
- guard let path, !path.isEmpty else { return nil }
-
- if let image = faceCache[path] { return image }
-
- if let loaded = UIImage(contentsOfFile: path) {
- faceCache[path] = loaded
- return loaded
- }
- return nil
- }
- }
- extension LNIMEmojiManager {
- private func reloadEmoji() {
- let plistPath = resourcePath.appendingPathComponent("emoji/emoji.plist").path
-
- guard let data = try? Data(contentsOf: URL(fileURLWithPath: plistPath)) else { return }
- let decoder = PropertyListDecoder()
- guard let infos: [LNEmojiConfig] = try? decoder.decode([LNEmojiConfig].self, from: data) else { return }
-
- var emojis: [LNEmojiData] = []
- for info in infos {
- let data = LNEmojiData()
- data.name = info.face_name
- data.path = resourcePath.appendingPathComponent(String(format: "emoji/%@", info.face_file)).path
- data.localizableName = TIMLocalizedText.shared.faceText(info.face_name)
-
- addFaceToCache(path: data.path)
- emojis.append(data)
- }
- guard !emojis.isEmpty else { return }
-
- let group = LNEmojiGroup()
- group.emojis = emojis
- group.groupName = TIMLocalizedText.shared.commonText("TUIChatFaceGroupAllEmojiName")
- emojiGroup = group
- }
-
- private func loadRecent() {
- let cached: [String] = LNUserDefaults[.imRecentEmojis, []]
- if !cached.isEmpty {
- recentEmoji = Array(cached.prefix(6))
- return
- }
- let plistPath = resourcePath.appendingPathComponent("emoji/emojiRecentDefaultList.plist").path
-
- guard let data = try? Data(contentsOf: URL(fileURLWithPath: plistPath)) else { return }
- let decoder = PropertyListDecoder()
- guard let infos: [LNEmojiConfig] = try? decoder.decode([LNEmojiConfig].self, from: data) else { return }
-
- let allNames: [String] = infos.map { $0.face_name }
- recentEmoji = Array(allNames.prefix(6))
- }
-
- private func addFaceToCache(path: String) {
- faceCache[path] = UIImage(contentsOfFile: path)
- }
- }
|