forked from shadowfacts/Tusker
parent
08c63a2f84
commit
21874b0966
|
@ -16,6 +16,7 @@ public class Emoji: Codable {
|
|||
public let url: WebURL
|
||||
public let staticURL: WebURL
|
||||
public let visibleInPicker: Bool
|
||||
public let category: String?
|
||||
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
@ -24,6 +25,7 @@ public class Emoji: Codable {
|
|||
self.url = try container.decode(WebURL.self, forKey: .url)
|
||||
self.staticURL = try container.decode(WebURL.self, forKey: .staticURL)
|
||||
self.visibleInPicker = try container.decode(Bool.self, forKey: .visibleInPicker)
|
||||
self.category = try container.decodeIfPresent(String.self, forKey: .category)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
|
@ -31,6 +33,7 @@ public class Emoji: Codable {
|
|||
case url
|
||||
case staticURL = "static_url"
|
||||
case visibleInPicker = "visible_in_picker"
|
||||
case category
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,6 +176,19 @@ struct ComposeAutocompleteEmojisView: View {
|
|||
@State private var emojis: [Emoji] = []
|
||||
@ScaledMetric private var emojiSize = 30
|
||||
|
||||
private var emojisBySection: [String: [Emoji]] {
|
||||
var values: [String: [Emoji]] = [:]
|
||||
for emoji in emojis {
|
||||
let key = emoji.category ?? ""
|
||||
if !values.keys.contains(key) {
|
||||
values[key] = [emoji]
|
||||
} else {
|
||||
values[key]!.append(emoji)
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
// When exapnded, the toggle button should be at the top. When collapsed, it should be centered.
|
||||
HStack(alignment: expanded ? .top : .center, spacing: 0) {
|
||||
|
@ -214,12 +227,28 @@ struct ComposeAutocompleteEmojisView: View {
|
|||
private var verticalGrid: some View {
|
||||
ScrollView {
|
||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: emojiSize), spacing: 4)]) {
|
||||
ForEach(emojis, id: \.shortcode) { (emoji) in
|
||||
Button {
|
||||
uiState.currentInput?.autocomplete(with: ":\(emoji.shortcode):")
|
||||
} label: {
|
||||
CustomEmojiImageView(emoji: emoji)
|
||||
.frame(height: emojiSize)
|
||||
ForEach(emojisBySection.keys.sorted(), id: \.self) { section in
|
||||
Section {
|
||||
ForEach(emojisBySection[section]!, id: \.shortcode) { emoji in
|
||||
Button {
|
||||
uiState.currentInput?.autocomplete(with: ":\(emoji.shortcode):")
|
||||
} label: {
|
||||
CustomEmojiImageView(emoji: emoji)
|
||||
.frame(height: emojiSize)
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
if !section.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(section)
|
||||
.font(.caption)
|
||||
|
||||
Rectangle()
|
||||
.foregroundColor(Color(.separator))
|
||||
.frame(height: 0.5)
|
||||
}
|
||||
.padding(.top, 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue