Bubble/Threaded/Components/Post/EmojiSelector.swift

85 lines
3.0 KiB
Swift

//Made by Lumaa
import SwiftUI
struct EmojiSelector: View {
@Environment(AccountManager.self) private var accountManager
@State private var loading: Bool = true
@State private var emojiContainers: [CategorizedEmojiContainer] = []
@State var viewModel: PostingView.ViewModel
var body: some View {
ZStack {
if loading {
ProgressView()
.ignoresSafeArea()
} else if !loading && !emojiContainers.isEmpty {
ScrollView(.vertical, showsIndicators: false) {
ForEach(emojiContainers) { container in
LazyVGrid(columns: [.init(.adaptive(minimum: 40, maximum: 40))]) {
Section {
ForEach(container.emojis) { emoji in
Button {
viewModel.append(text: ":\(emoji.shortcode):")
} label: {
OnlineImage(url: emoji.url, size: 40, useNuke: true)
}
.buttonStyle(NoTapAnimationStyle())
}
}
}
}
}
.padding()
.padding(.vertical)
} else {
ContentUnavailableView("status.posting.no-emojis", systemImage: "network.slash")
}
}
.task {
loading = true
await fetchCustomEmojis()
loading = false
}
}
struct CategorizedEmojiContainer: Identifiable, Equatable {
let id = UUID().uuidString
let categoryName: String
var emojis: [Emoji]
}
private func fetchCustomEmojis() async {
typealias EmojiContainer = CategorizedEmojiContainer
guard let client = accountManager.getClient() else { return }
do {
let customEmojis: [Emoji] = try await client.get(endpoint: CustomEmojis.customEmojis) ?? []
var emojiContainers: [EmojiContainer] = []
customEmojis.reduce([String: [Emoji]]()) { currentDict, emoji in
var dict = currentDict
let category = emoji.category ?? "Custom"
if let emojis = dict[category] {
dict[category] = emojis + [emoji]
} else {
dict[category] = [emoji]
}
return dict
}.sorted(by: { lhs, rhs in
if rhs.key == "Custom" { false }
else if lhs.key == "Custom" { true }
else { lhs.key < rhs.key }
}).forEach { key, value in
emojiContainers.append(.init(categoryName: key, emojis: value))
}
self.emojiContainers = emojiContainers
} catch {}
}
}