diff --git a/Threaded/Components/Post/EmojiSelector.swift b/Threaded/Components/Post/EmojiSelector.swift new file mode 100644 index 0000000..d4f4cc0 --- /dev/null +++ b/Threaded/Components/Post/EmojiSelector.swift @@ -0,0 +1,76 @@ +//Made by Lumaa + +import SwiftUI + +struct EmojiSelector: View { + @Environment(AccountManager.self) private var accountManager + + @State private var emojiContainers: [CategorizedEmojiContainer] = [] + @Binding var viewModel: PostingView.ViewModel + + var body: some View { + if emojiContainers.isEmpty { + ProgressView() + .ignoresSafeArea() + .task { + await fetchCustomEmojis() + } + } else { + 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, priority: .low) + } + .buttonStyle(NoTapAnimationStyle()) + } + } + } + } + } + .padding() + .padding(.vertical) + } + } + + 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 {} + } +} diff --git a/Threaded/Views/PostingView.swift b/Threaded/Views/PostingView.swift index be20844..b43e596 100644 --- a/Threaded/Views/PostingView.swift +++ b/Threaded/Views/PostingView.swift @@ -22,16 +22,19 @@ struct PostingView: View { @State private var postingStatus: Bool = false var body: some View { + if accountManager.getAccount() != nil { posting + .background(Color.appBackground) .sheet(isPresented: $selectingEmoji) { - Text(String("Custom Emoji selection")) - .presentationDetents([.medium]) + EmojiSelector(viewModel: $viewModel) + .presentationDetents([.height(200), .medium]) .presentationDragIndicator(.visible) - .presentationBackgroundInteraction(.enabled) // Allow users to move the cursor while adding emojis + .presentationBackgroundInteraction(.enabled(upThrough: .height(200))) // Allow users to move the cursor while adding emojis } } else { loading + .background(Color.appBackground) } }