Make categorized emoji picker (#1680)

Signed-off-by: Euigyom Kim <egkim@dehol.kr>
This commit is contained in:
Euigyom Kim 2023-11-19 16:09:41 +09:00 committed by GitHub
parent 1e35ffb82b
commit d3b52b3206
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 23 deletions

View file

@ -13,4 +13,5 @@ public struct Emoji: Codable, Hashable, Identifiable, Equatable, Sendable {
public let url: URL public let url: URL
public let staticUrl: URL public let staticUrl: URL
public let visibleInPicker: Bool public let visibleInPicker: Bool
public let category: String?
} }

View file

@ -120,7 +120,7 @@ struct StatusEditorAccessoryView: View {
} }
} }
if !viewModel.customEmojis.isEmpty { if !viewModel.customEmojiContainer.isEmpty {
Button { Button {
isCustomEmojisSheetDisplay = true isCustomEmojisSheetDisplay = true
} label: { } label: {
@ -283,8 +283,12 @@ struct StatusEditorAccessoryView: View {
private var customEmojisSheet: some View { private var customEmojisSheet: some View {
NavigationStack { NavigationStack {
ScrollView { ScrollView {
ForEach(viewModel.customEmojiContainer) { container in
VStack(alignment: .leading) {
Text(container.categoryName)
.font(.scaledFootnote)
LazyVGrid(columns: [GridItem(.adaptive(minimum: 40))], spacing: 9) { LazyVGrid(columns: [GridItem(.adaptive(minimum: 40))], spacing: 9) {
ForEach(viewModel.customEmojis) { emoji in ForEach(container.emojis) { emoji in
LazyImage(url: emoji.url) { state in LazyImage(url: emoji.url) { state in
if let image = state.image { if let image = state.image {
image image
@ -305,7 +309,11 @@ struct StatusEditorAccessoryView: View {
viewModel.insertStatusText(text: " :\(emoji.shortcode): ") viewModel.insertStatusText(text: " :\(emoji.shortcode): ")
} }
} }
}.padding(.horizontal) }
}
.padding(.horizontal)
.padding(.bottom)
}
} }
.toolbar { .toolbar {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {

View file

@ -0,0 +1,8 @@
import Foundation
import Models
struct StatusEditorCategorizedEmojiContainer: Identifiable, Equatable {
let id = UUID().uuidString
let categoryName: String
var emojis: [Emoji]
}

View file

@ -100,7 +100,7 @@ import SwiftUI
var replyToStatus: Status? var replyToStatus: Status?
var embeddedStatus: Status? var embeddedStatus: Status?
var customEmojis: [Emoji] = [] var customEmojiContainer: [StatusEditorCategorizedEmojiContainer] = []
var postingError: String? var postingError: String?
var showPostingErrorAlert: Bool = false var showPostingErrorAlert: Bool = false
@ -726,9 +726,33 @@ import SwiftUI
// MARK: - Custom emojis // MARK: - Custom emojis
func fetchCustomEmojis() async { func fetchCustomEmojis() async {
typealias EmojiContainer = StatusEditorCategorizedEmojiContainer
guard let client else { return } guard let client else { return }
do { do {
customEmojis = try await client.get(endpoint: CustomEmojis.customEmojis) ?? [] 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 ?? "Uncategorized"
if let emojis = dict[category] {
dict[category] = emojis + [emoji]
} else {
dict[category] = [emoji]
}
return dict
}.sorted(by: { lhs, rhs in
if rhs.key == "Uncategorized" { return false }
else if lhs.key == "Uncategorized" { return true }
else { return lhs.key < rhs.key }
}).forEach { key, value in
emojiContainers.append(.init(categoryName: key, emojis: value))
}
customEmojiContainer = emojiContainers
} catch {} } catch {}
} }
} }