parent
08c63a2f84
commit
21874b0966
|
@ -16,6 +16,7 @@ public class Emoji: Codable {
|
||||||
public let url: WebURL
|
public let url: WebURL
|
||||||
public let staticURL: WebURL
|
public let staticURL: WebURL
|
||||||
public let visibleInPicker: Bool
|
public let visibleInPicker: Bool
|
||||||
|
public let category: String?
|
||||||
|
|
||||||
public required init(from decoder: Decoder) throws {
|
public required init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
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.url = try container.decode(WebURL.self, forKey: .url)
|
||||||
self.staticURL = try container.decode(WebURL.self, forKey: .staticURL)
|
self.staticURL = try container.decode(WebURL.self, forKey: .staticURL)
|
||||||
self.visibleInPicker = try container.decode(Bool.self, forKey: .visibleInPicker)
|
self.visibleInPicker = try container.decode(Bool.self, forKey: .visibleInPicker)
|
||||||
|
self.category = try container.decodeIfPresent(String.self, forKey: .category)
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
@ -31,6 +33,7 @@ public class Emoji: Codable {
|
||||||
case url
|
case url
|
||||||
case staticURL = "static_url"
|
case staticURL = "static_url"
|
||||||
case visibleInPicker = "visible_in_picker"
|
case visibleInPicker = "visible_in_picker"
|
||||||
|
case category
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,19 @@ struct ComposeAutocompleteEmojisView: View {
|
||||||
@State private var emojis: [Emoji] = []
|
@State private var emojis: [Emoji] = []
|
||||||
@ScaledMetric private var emojiSize = 30
|
@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 {
|
var body: some View {
|
||||||
// When exapnded, the toggle button should be at the top. When collapsed, it should be centered.
|
// When exapnded, the toggle button should be at the top. When collapsed, it should be centered.
|
||||||
HStack(alignment: expanded ? .top : .center, spacing: 0) {
|
HStack(alignment: expanded ? .top : .center, spacing: 0) {
|
||||||
|
@ -214,12 +227,28 @@ struct ComposeAutocompleteEmojisView: View {
|
||||||
private var verticalGrid: some View {
|
private var verticalGrid: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVGrid(columns: [GridItem(.adaptive(minimum: emojiSize), spacing: 4)]) {
|
LazyVGrid(columns: [GridItem(.adaptive(minimum: emojiSize), spacing: 4)]) {
|
||||||
ForEach(emojis, id: \.shortcode) { (emoji) in
|
ForEach(emojisBySection.keys.sorted(), id: \.self) { section in
|
||||||
Button {
|
Section {
|
||||||
uiState.currentInput?.autocomplete(with: ":\(emoji.shortcode):")
|
ForEach(emojisBySection[section]!, id: \.shortcode) { emoji in
|
||||||
} label: {
|
Button {
|
||||||
CustomEmojiImageView(emoji: emoji)
|
uiState.currentInput?.autocomplete(with: ":\(emoji.shortcode):")
|
||||||
.frame(height: emojiSize)
|
} 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