ui updates

downloaded emojis is a grid
rewrote deleteAllStickers
added downloadEmoji
This commit is contained in:
neon443
2025-11-05 22:04:04 +00:00
parent 08ad69b19a
commit 42739c93da
5 changed files with 76 additions and 73 deletions

View File

@@ -9,6 +9,7 @@ import Foundation
import SwiftUI
import Combine
import UniformTypeIdentifiers
import Haptics
class EmojiHoarder: ObservableObject {
static let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.neon443.StickerSlack")!.appendingPathComponent("Library", conformingTo: .directory)
@@ -45,17 +46,10 @@ class EmojiHoarder: ObservableObject {
}
}
func deleteAllStickers() async {
await withTaskGroup { group in
for i in emojis.indices {
group.addTask {
guard await self.emojis[i].isLocal else { return }
await self.emojis[i].deleteImage()
DispatchQueue.main.sync {
self.emojis[i].refresh()
}
}
}
func deleteAllStickers() {
for i in emojis.indices {
guard downloadedEmojis.contains(emojis[i].name) else { continue }
delete(emoji: emojis[i])
}
}
@@ -150,6 +144,25 @@ class EmojiHoarder: ObservableObject {
withAnimation { filteredEmojis = trie.search(prefix: searchTerm) }
}
func download(emoji: Emoji) {
Task.detached {
try? await emoji.downloadImage()
await MainActor.run {
self.downloadedEmojis.insert(emoji.name)
self.trie.dict[emoji.name]?.refresh()
Haptic.success.trigger()
}
}
}
@MainActor
func delete(emoji: Emoji) {
emoji.deleteImage()
downloadedEmojis.remove(emoji.name)
self.trie.dict[emoji.name]?.refresh()
Haptic.heavy.trigger()
}
// func filterEmojis(byCategory category: FilterCategory, searchTerm: String) {
// guard category != .none else {
// filterEmojis(by: searchTerm)

View File

@@ -13,12 +13,14 @@ struct ContentView: View {
@State var searchTerm: String = ""
var col: GridItem = GridItem(.fixed(100), spacing: 0, alignment: .center)
var body: some View {
TabView {
List {
ForEach(hoarder.downloadedEmojis, id: \.self) { name in
LazyHGrid(rows: Array(repeating: col, count: 4), spacing: 10) {
ForEach(hoarder.downloadedEmojis.sorted(by: <), id: \.self) { name in
if let emoji = hoarder.trie.dict[name] {
EmojiRow(hoarder: hoarder, emoji: emoji)
EmojiPreview(hoarder: hoarder, emoji: emoji)
.aspectRatio(1, contentMode: .fit)
}
}
}

View File

@@ -15,46 +15,43 @@ struct EmojiPreview: View {
@State private var id: UUID = UUID()
@State private var delay: TimeInterval = 0
var body: some View {
VStack(alignment: .leading) {
Text(emoji.name)
Group {
if let image = emoji.image {
Image(uiImage: image)
.resizable().scaledToFit()
.border(.orange)
.overlay(alignment: .bottomLeading) {
Image(systemName: "arrow.down.circle.fill")
.foregroundStyle(.gray)
.shadow(radius: 1)
.symbolRenderingMode(.hierarchical)
}
} else {
AsyncImage(url: emoji.remoteImageURL) { phase in
if let image = phase.image {
image
.resizable().scaledToFit()
} else if phase.error != nil {
ImageErrorView()
.onTapGesture {
var body: some View {
Group {
if let image = emoji.image {
Image(uiImage: image)
.resizable().scaledToFit()
.border(.orange)
.overlay(alignment: .bottomLeading) {
Image(systemName: "arrow.down.circle.fill")
.foregroundStyle(.gray)
.shadow(radius: 1)
.symbolRenderingMode(.hierarchical)
}
} else {
AsyncImage(url: emoji.remoteImageURL) { phase in
if let image = phase.image {
image
.resizable().scaledToFit()
} else if phase.error != nil {
ImageErrorView()
.onTapGesture {
id = UUID()
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now()+delay) {
id = UUID()
delay+=0.1
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now()+delay) {
id = UUID()
delay+=0.1
}
}
} else {
ProgressView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
} else {
ProgressView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
.id(id)
}
}
.id(id)
}
}
#Preview {

View File

@@ -14,28 +14,26 @@ struct EmojiRow: View {
var body: some View {
HStack {
EmojiPreview(
hoarder: hoarder,
emoji: emoji
)
VStack {
HStack(spacing: .zero) {
// Text
Text(emoji.name)
}
EmojiPreview(
hoarder: hoarder,
emoji: emoji
)
}
.frame(maxWidth: 100, maxHeight: 100)
Spacer()
if hoarder.downloadedEmojis.contains(emoji.name) {
Button("", systemImage: "trash") {
emoji.deleteImage()
emoji.refresh()
Haptic.heavy.trigger()
hoarder.delete(emoji: emoji)
}
.buttonStyle(.plain)
} else {
Button("", systemImage: "arrow.down.circle") {
Task.detached {
try? await emoji.downloadImage()
await MainActor.run {
emoji.refresh()
Haptic.success.trigger()
}
}
hoarder.download(emoji: emoji)
}
.buttonStyle(.plain)
}

View File

@@ -46,32 +46,25 @@ struct EmojiCollectionView: UIViewRepresentable {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let emojiName = items[indexPath.row]
let emoji = hoarder.trie.dict[emojiName]!
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.contentConfiguration = UIHostingConfiguration {
HStack {
EmojiPreview(
hoarder: hoarder,
emoji: hoarder.trie.dict[emojiName]!
emoji: emoji
)
.frame(maxWidth: 100, maxHeight: 100)
Spacer()
if hoarder.downloadedEmojis.contains(emojiName) {
Button("", systemImage: "trash") {
self.hoarder.trie.dict[emojiName]!.deleteImage()
self.hoarder.trie.dict[emojiName]!.refresh()
Haptic.heavy.trigger()
fatalError()
}
.buttonStyle(.plain)
} else {
Button("", systemImage: "arrow.down.circle") {
Task.detached {
try? await self.hoarder.trie.dict[emojiName]!.downloadImage()
await MainActor.run {
self.hoarder.trie.dict[emojiName]!.refresh()
Haptic.success.trigger()
}
}
self.hoarder.download(emoji: emoji)
}
.buttonStyle(.plain)
}