mirror of
https://github.com/neon443/StickerSlack.git
synced 2026-03-11 05:19:13 +00:00
ui updates
downloaded emojis is a grid rewrote deleteAllStickers added downloadEmoji
This commit is contained in:
@@ -9,6 +9,7 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Combine
|
import Combine
|
||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
import Haptics
|
||||||
|
|
||||||
class EmojiHoarder: ObservableObject {
|
class EmojiHoarder: ObservableObject {
|
||||||
static let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.neon443.StickerSlack")!.appendingPathComponent("Library", conformingTo: .directory)
|
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 {
|
func deleteAllStickers() {
|
||||||
await withTaskGroup { group in
|
for i in emojis.indices {
|
||||||
for i in emojis.indices {
|
guard downloadedEmojis.contains(emojis[i].name) else { continue }
|
||||||
group.addTask {
|
delete(emoji: emojis[i])
|
||||||
guard await self.emojis[i].isLocal else { return }
|
|
||||||
await self.emojis[i].deleteImage()
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
self.emojis[i].refresh()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +144,25 @@ class EmojiHoarder: ObservableObject {
|
|||||||
withAnimation { filteredEmojis = trie.search(prefix: searchTerm) }
|
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) {
|
// func filterEmojis(byCategory category: FilterCategory, searchTerm: String) {
|
||||||
// guard category != .none else {
|
// guard category != .none else {
|
||||||
// filterEmojis(by: searchTerm)
|
// filterEmojis(by: searchTerm)
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ struct ContentView: View {
|
|||||||
|
|
||||||
@State var searchTerm: String = ""
|
@State var searchTerm: String = ""
|
||||||
|
|
||||||
|
var col: GridItem = GridItem(.fixed(100), spacing: 0, alignment: .center)
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabView {
|
TabView {
|
||||||
List {
|
LazyHGrid(rows: Array(repeating: col, count: 4), spacing: 10) {
|
||||||
ForEach(hoarder.downloadedEmojis, id: \.self) { name in
|
ForEach(hoarder.downloadedEmojis.sorted(by: <), id: \.self) { name in
|
||||||
if let emoji = hoarder.trie.dict[name] {
|
if let emoji = hoarder.trie.dict[name] {
|
||||||
EmojiRow(hoarder: hoarder, emoji: emoji)
|
EmojiPreview(hoarder: hoarder, emoji: emoji)
|
||||||
|
.aspectRatio(1, contentMode: .fit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,46 +15,43 @@ struct EmojiPreview: View {
|
|||||||
@State private var id: UUID = UUID()
|
@State private var id: UUID = UUID()
|
||||||
@State private var delay: TimeInterval = 0
|
@State private var delay: TimeInterval = 0
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
Group {
|
||||||
Text(emoji.name)
|
if let image = emoji.image {
|
||||||
Group {
|
Image(uiImage: image)
|
||||||
if let image = emoji.image {
|
.resizable().scaledToFit()
|
||||||
Image(uiImage: image)
|
.border(.orange)
|
||||||
.resizable().scaledToFit()
|
.overlay(alignment: .bottomLeading) {
|
||||||
.border(.orange)
|
Image(systemName: "arrow.down.circle.fill")
|
||||||
.overlay(alignment: .bottomLeading) {
|
.foregroundStyle(.gray)
|
||||||
Image(systemName: "arrow.down.circle.fill")
|
.shadow(radius: 1)
|
||||||
.foregroundStyle(.gray)
|
.symbolRenderingMode(.hierarchical)
|
||||||
.shadow(radius: 1)
|
}
|
||||||
.symbolRenderingMode(.hierarchical)
|
} else {
|
||||||
}
|
AsyncImage(url: emoji.remoteImageURL) { phase in
|
||||||
} else {
|
if let image = phase.image {
|
||||||
AsyncImage(url: emoji.remoteImageURL) { phase in
|
image
|
||||||
if let image = phase.image {
|
.resizable().scaledToFit()
|
||||||
image
|
} else if phase.error != nil {
|
||||||
.resizable().scaledToFit()
|
ImageErrorView()
|
||||||
} else if phase.error != nil {
|
.onTapGesture {
|
||||||
ImageErrorView()
|
id = UUID()
|
||||||
.onTapGesture {
|
}
|
||||||
|
.onAppear {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now()+delay) {
|
||||||
id = UUID()
|
id = UUID()
|
||||||
|
delay+=0.1
|
||||||
}
|
}
|
||||||
.onAppear {
|
}
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+delay) {
|
} else {
|
||||||
id = UUID()
|
ProgressView()
|
||||||
delay+=0.1
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ProgressView()
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.id(id)
|
|
||||||
}
|
}
|
||||||
}
|
.id(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
|
|||||||
@@ -14,28 +14,26 @@ struct EmojiRow: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
EmojiPreview(
|
VStack {
|
||||||
hoarder: hoarder,
|
HStack(spacing: .zero) {
|
||||||
emoji: emoji
|
// Text
|
||||||
)
|
Text(emoji.name)
|
||||||
|
}
|
||||||
|
EmojiPreview(
|
||||||
|
hoarder: hoarder,
|
||||||
|
emoji: emoji
|
||||||
|
)
|
||||||
|
}
|
||||||
.frame(maxWidth: 100, maxHeight: 100)
|
.frame(maxWidth: 100, maxHeight: 100)
|
||||||
Spacer()
|
Spacer()
|
||||||
if hoarder.downloadedEmojis.contains(emoji.name) {
|
if hoarder.downloadedEmojis.contains(emoji.name) {
|
||||||
Button("", systemImage: "trash") {
|
Button("", systemImage: "trash") {
|
||||||
emoji.deleteImage()
|
hoarder.delete(emoji: emoji)
|
||||||
emoji.refresh()
|
|
||||||
Haptic.heavy.trigger()
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
} else {
|
} else {
|
||||||
Button("", systemImage: "arrow.down.circle") {
|
Button("", systemImage: "arrow.down.circle") {
|
||||||
Task.detached {
|
hoarder.download(emoji: emoji)
|
||||||
try? await emoji.downloadImage()
|
|
||||||
await MainActor.run {
|
|
||||||
emoji.refresh()
|
|
||||||
Haptic.success.trigger()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,32 +46,25 @@ struct EmojiCollectionView: UIViewRepresentable {
|
|||||||
|
|
||||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
let emojiName = items[indexPath.row]
|
let emojiName = items[indexPath.row]
|
||||||
|
let emoji = hoarder.trie.dict[emojiName]!
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||||
|
|
||||||
cell.contentConfiguration = UIHostingConfiguration {
|
cell.contentConfiguration = UIHostingConfiguration {
|
||||||
HStack {
|
HStack {
|
||||||
EmojiPreview(
|
EmojiPreview(
|
||||||
hoarder: hoarder,
|
hoarder: hoarder,
|
||||||
emoji: hoarder.trie.dict[emojiName]!
|
emoji: emoji
|
||||||
)
|
)
|
||||||
.frame(maxWidth: 100, maxHeight: 100)
|
.frame(maxWidth: 100, maxHeight: 100)
|
||||||
Spacer()
|
Spacer()
|
||||||
if hoarder.downloadedEmojis.contains(emojiName) {
|
if hoarder.downloadedEmojis.contains(emojiName) {
|
||||||
Button("", systemImage: "trash") {
|
Button("", systemImage: "trash") {
|
||||||
self.hoarder.trie.dict[emojiName]!.deleteImage()
|
fatalError()
|
||||||
self.hoarder.trie.dict[emojiName]!.refresh()
|
|
||||||
Haptic.heavy.trigger()
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
} else {
|
} else {
|
||||||
Button("", systemImage: "arrow.down.circle") {
|
Button("", systemImage: "arrow.down.circle") {
|
||||||
Task.detached {
|
self.hoarder.download(emoji: emoji)
|
||||||
try? await self.hoarder.trie.dict[emojiName]!.downloadImage()
|
|
||||||
await MainActor.run {
|
|
||||||
self.hoarder.trie.dict[emojiName]!.refresh()
|
|
||||||
Haptic.success.trigger()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user