mirror of
https://github.com/metabolist/metatext.git
synced 2024-06-02 08:42:31 +00:00
127 lines
4.1 KiB
Swift
127 lines
4.1 KiB
Swift
// Copyright © 2020 Metabolist. All rights reserved.
|
|
|
|
import Combine
|
|
import DB
|
|
import Foundation
|
|
import Mastodon
|
|
|
|
public enum EmojiPickerError: Error {
|
|
case emojisFileMissing
|
|
case invalidSystemEmojiGroup
|
|
case annotationsAndTagsFileMissing
|
|
}
|
|
|
|
public struct EmojiPickerService {
|
|
private let contentDatabase: ContentDatabase
|
|
|
|
init(contentDatabase: ContentDatabase) {
|
|
self.contentDatabase = contentDatabase
|
|
}
|
|
}
|
|
|
|
public extension EmojiPickerService {
|
|
func customEmojiPublisher() -> AnyPublisher<[PickerEmoji.Category: [PickerEmoji]], Error> {
|
|
contentDatabase.pickerEmojisPublisher().map {
|
|
var typed = [PickerEmoji.Category: [PickerEmoji]]()
|
|
|
|
for emoji in $0 {
|
|
let category: PickerEmoji.Category
|
|
|
|
if let categoryName = emoji.category {
|
|
category = .customNamed(categoryName)
|
|
} else {
|
|
category = .custom
|
|
}
|
|
|
|
if typed[category] == nil {
|
|
typed[category] = [.custom(emoji, inFrequentlyUsed: false)]
|
|
} else {
|
|
typed[category]?.append(.custom(emoji, inFrequentlyUsed: false))
|
|
}
|
|
}
|
|
|
|
return typed
|
|
}
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
func systemEmojiPublisher() -> AnyPublisher<[PickerEmoji.Category: [PickerEmoji]], Error> {
|
|
Future { promise in
|
|
DispatchQueue.global(qos: .userInteractive).async {
|
|
guard let url = Bundle.module.url(forResource: "emojis", withExtension: "json") else {
|
|
promise(.failure(EmojiPickerError.emojisFileMissing))
|
|
|
|
return
|
|
}
|
|
|
|
do {
|
|
let data = try Data(contentsOf: url)
|
|
let decoded = try JSONDecoder().decode([String: [SystemEmoji]].self, from: data)
|
|
var typed = [PickerEmoji.Category: [PickerEmoji]]()
|
|
|
|
for (groupString, emoji) in decoded {
|
|
guard let rawValue = Int(groupString),
|
|
let group = SystemEmoji.Group(rawValue: rawValue)
|
|
else {
|
|
promise(.failure(EmojiPickerError.invalidSystemEmojiGroup))
|
|
|
|
return
|
|
}
|
|
|
|
typed[.systemGroup(group)] = emoji
|
|
.filter { !($0.version > Self.maxEmojiVersion) }
|
|
.map {
|
|
PickerEmoji.system(
|
|
$0.withMaxVersionForSkinToneVariations(Self.maxEmojiVersion),
|
|
inFrequentlyUsed: false)
|
|
}
|
|
}
|
|
|
|
return promise(.success(typed))
|
|
} catch {
|
|
promise(.failure(error))
|
|
}
|
|
}
|
|
}
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
func systemEmojiAnnotationsAndTagsPublisher(languageCode: String) -> AnyPublisher<[String: String], Error> {
|
|
Future { promise in
|
|
guard let url = Bundle.module.url(forResource: languageCode, withExtension: "json") else {
|
|
promise(.failure(EmojiPickerError.annotationsAndTagsFileMissing))
|
|
|
|
return
|
|
}
|
|
|
|
do {
|
|
let data = try Data(contentsOf: url)
|
|
let decoded = try JSONDecoder().decode([String: String].self, from: data)
|
|
|
|
promise(.success(decoded))
|
|
} catch {
|
|
promise(.failure(error))
|
|
}
|
|
}
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
func emojiUses(limit: Int) -> AnyPublisher<[EmojiUse], Error> {
|
|
contentDatabase.emojiUses(limit: limit)
|
|
}
|
|
|
|
func updateUse(emoji: PickerEmoji) -> AnyPublisher<Never, Error> {
|
|
contentDatabase.updateUse(emoji: emoji.name, system: emoji.system)
|
|
}
|
|
}
|
|
|
|
private extension EmojiPickerService {
|
|
static var maxEmojiVersion: Float = {
|
|
if #available(iOS 14.2, *) {
|
|
return 13.0
|
|
}
|
|
|
|
return 12.1
|
|
}()
|
|
}
|