added an easter egg for the idiot who dowloads all the emojis

fix downloadall/deleteall stickers
This commit is contained in:
neon443
2025-11-22 18:15:27 +00:00
parent 98d8f083a1
commit 12484f6226
4 changed files with 68 additions and 46 deletions

View File

@@ -65,7 +65,6 @@
A9BBC51A2EB8FA4500FFE82F /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BBC5172EB8FA4500FFE82F /* ViewModifiers.swift */; }; A9BBC51A2EB8FA4500FFE82F /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BBC5172EB8FA4500FFE82F /* ViewModifiers.swift */; };
A9C172DC2EB8C9AC008A7885 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C172DB2EB8C9AC008A7885 /* Trie.swift */; }; A9C172DC2EB8C9AC008A7885 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C172DB2EB8C9AC008A7885 /* Trie.swift */; };
A9C172DD2EB8C9AC008A7885 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C172DB2EB8C9AC008A7885 /* Trie.swift */; }; A9C172DD2EB8C9AC008A7885 /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C172DB2EB8C9AC008A7885 /* Trie.swift */; };
A9C7892D2ED2005000D954F5 /* StickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C7892C2ED2005000D954F5 /* StickerView.swift */; };
A9D15B8B2EB1142C00404792 /* EmojiPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D15B892EB1142C00404792 /* EmojiPack.swift */; }; A9D15B8B2EB1142C00404792 /* EmojiPack.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9D15B892EB1142C00404792 /* EmojiPack.swift */; };
A9EB72392EB93FDB00658CEB /* EmojiCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EB72382EB93FDB00658CEB /* EmojiCollectionView.swift */; }; A9EB72392EB93FDB00658CEB /* EmojiCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EB72382EB93FDB00658CEB /* EmojiCollectionView.swift */; };
A9EB72472EB948C400658CEB /* EmojiRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EB72462EB948C400658CEB /* EmojiRow.swift */; }; A9EB72472EB948C400658CEB /* EmojiRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9EB72462EB948C400658CEB /* EmojiRow.swift */; };
@@ -524,7 +523,6 @@
A9EB724B2EB94A5700658CEB /* Trie.swift in Sources */, A9EB724B2EB94A5700658CEB /* Trie.swift in Sources */,
A986A6CD2EB659E000B6E0FA /* MessagesViewController.swift in Sources */, A986A6CD2EB659E000B6E0FA /* MessagesViewController.swift in Sources */,
A986A6CE2EB659E000B6E0FA /* StickerBrowserDataSource.swift in Sources */, A986A6CE2EB659E000B6E0FA /* StickerBrowserDataSource.swift in Sources */,
A9C7892D2ED2005000D954F5 /* StickerView.swift in Sources */,
A957C17E2ECFAA1100EA3EE9 /* GifView.swift in Sources */, A957C17E2ECFAA1100EA3EE9 /* GifView.swift in Sources */,
A9BBC5192EB8FA4500FFE82F /* ViewModifiers.swift in Sources */, A9BBC5192EB8FA4500FFE82F /* ViewModifiers.swift in Sources */,
A986A6C42EB6598500B6E0FA /* SlackResponse.swift in Sources */, A986A6C42EB6598500B6E0FA /* SlackResponse.swift in Sources */,

View File

@@ -51,9 +51,15 @@ class EmojiHoarder: ObservableObject {
} }
} }
func storeStickers(_ toStore: [UUID]) { @MainActor
for stickerId in toStore { func downloadAllStickers() {
print(stickerId) for emoji in emojis {
guard !downloadedEmojis.contains(emoji.name) else { continue }
download(emoji: emoji, skipStoreIndex: true)
downloadedEmojis.insert(emoji.name)
}
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
self.storeDownloadedIndexes()
} }
} }
@@ -61,26 +67,34 @@ class EmojiHoarder: ObservableObject {
func deleteAllStickers() { func deleteAllStickers() {
for i in emojis.indices { for i in emojis.indices {
guard downloadedEmojis.contains(emojis[i].name) else { continue } guard downloadedEmojis.contains(emojis[i].name) else { continue }
delete(emoji: emojis[i]) delete(emoji: emojis[i], skipStoreIndex: true)
} }
storeDownloadedIndexes()
} }
func storeDB() { private func storeDB() {
try! encoder.encode(emojis).write(to: EmojiHoarder.localEmojiDB) try! encoder.encode(emojis).write(to: EmojiHoarder.localEmojiDB)
} }
func storeDB(data: Data) { private func storeDB(data: Data) {
try! data.write(to: EmojiHoarder.localEmojiDB) try! data.write(to: EmojiHoarder.localEmojiDB)
} }
func resetTrie() { func resetAllIndexes() {
trie.root = TrieNode() trie.root = TrieNode()
trie.dict = [:] trie.dict = [:]
try? FileManager.default.removeItem(at: EmojiHoarder.localTrieDict)
downloadedEmojis = [] downloadedEmojis = []
downloadedEmojisArr = []
UserDefaults.standard.removeObject(forKey: "downloadedEmojis")
UserDefaults.standard.removeObject(forKey: "downloadedEmojisArr")
searchTerm = ""
letterStats = []
} }
//cl i disabled ts cos its quicker to rebuild it then to load ts //cl i disabled ts cos its quicker to rebuild it then to load ts
func saveTrie() { private func saveTrie() {
// return // return
// guard let data = try? encoder.encode(trie.root) else { // guard let data = try? encoder.encode(trie.root) else {
// fatalError("failed to encode trie") // fatalError("failed to encode trie")
@@ -93,7 +107,7 @@ class EmojiHoarder: ObservableObject {
try! dataDict.write(to: EmojiHoarder.localTrieDict) try! dataDict.write(to: EmojiHoarder.localTrieDict)
} }
func loadTrie() { private func loadTrie() {
// return // return
// guard FileManager.default.fileExists(atPath: EmojiHoarder.localTrie.path) else { return } // guard FileManager.default.fileExists(atPath: EmojiHoarder.localTrie.path) else { return }
// guard let data = try? Data(contentsOf: EmojiHoarder.localTrie) else { return } // guard let data = try? Data(contentsOf: EmojiHoarder.localTrie) else { return }
@@ -121,18 +135,18 @@ class EmojiHoarder: ObservableObject {
print("done building trie in", Date().timeIntervalSince1970-start) print("done building trie in", Date().timeIntervalSince1970-start)
} }
func buildTrieDict() { private func buildTrieDict() {
for emoji in emojis { for emoji in emojis {
trie.dict[emoji.name] = emoji trie.dict[emoji.name] = emoji
} }
buildDownloadedEmojis() buildDownloadedEmojis()
} }
func buildDownloadedEmojis() { private func buildDownloadedEmojis() {
downloadedEmojis = [] downloadedEmojis = []
downloadedEmojisArr = [] downloadedEmojisArr = []
downloadedEmojisArr = (try? JSONDecoder().decode([String].self, from: UserDefaults.standard.data(forKey: "downloadedEmojisArr") ?? Data())) ?? [] downloadedEmojisArr = (try? decoder.decode([String].self, from: UserDefaults.standard.data(forKey: "downloadedEmojisArr") ?? Data())) ?? []
downloadedEmojis = (try? JSONDecoder().decode(Set<String>.self, from: UserDefaults.standard.data(forKey: "downloadedEmojis") ?? Data())) ?? [] downloadedEmojis = (try? decoder.decode(Set<String>.self, from: UserDefaults.standard.data(forKey: "downloadedEmojis") ?? Data())) ?? []
if downloadedEmojis.isEmpty || downloadedEmojisArr.isEmpty { if downloadedEmojis.isEmpty || downloadedEmojisArr.isEmpty {
for emoji in emojis { for emoji in emojis {
@@ -141,13 +155,15 @@ class EmojiHoarder: ObservableObject {
downloadedEmojisArr.append(emoji.name) downloadedEmojisArr.append(emoji.name)
} }
} }
}
UserDefaults.standard.set(try! JSONEncoder().encode(downloadedEmojis), forKey: "downloadedEmojis")
UserDefaults.standard.set(try! JSONEncoder().encode(downloadedEmojisArr), forKey: "downloadedEmojisArr") func storeDownloadedIndexes() {
UserDefaults.standard.set(try! encoder.encode(downloadedEmojis), forKey: "downloadedEmojis")
UserDefaults.standard.set(try! encoder.encode(downloadedEmojisArr), forKey: "downloadedEmojisArr")
} }
nonisolated nonisolated
func loadLocalDB() -> [Emoji] { private func loadLocalDB() -> [Emoji] {
if let localEmojiDB = try? Data(contentsOf: EmojiHoarder.localEmojiDB) { if let localEmojiDB = try? Data(contentsOf: EmojiHoarder.localEmojiDB) {
let decoded = try! decoder.decode([Emoji].self, from: localEmojiDB) let decoded = try! decoder.decode([Emoji].self, from: localEmojiDB)
return decoded return decoded
@@ -155,7 +171,7 @@ class EmojiHoarder: ObservableObject {
return [] return []
} }
func loadRemoteDB() async { private func loadRemoteDB() async {
async let fetched = self.fetchRemoteDB() async let fetched = self.fetchRemoteDB()
if let fetched = await fetched { if let fetched = await fetched {
withAnimation { self.emojis = fetched } withAnimation { self.emojis = fetched }
@@ -163,7 +179,7 @@ class EmojiHoarder: ObservableObject {
} }
nonisolated nonisolated
func fetchRemoteDB() async -> [Emoji]? { private func fetchRemoteDB() async -> [Emoji]? {
do { do {
async let (data, _) = try URLSession.shared.data(from: endpoint) async let (data, _) = try URLSession.shared.data(from: endpoint)
decoder.dateDecodingStrategy = .iso8601 decoder.dateDecodingStrategy = .iso8601
@@ -176,7 +192,7 @@ class EmojiHoarder: ObservableObject {
} }
} }
func refreshDB() async { private func refreshDB() async {
guard let fetched = await self.fetchRemoteDB() else { guard let fetched = await self.fetchRemoteDB() else {
let local = loadLocalDB() let local = loadLocalDB()
await MainActor.run { await MainActor.run {
@@ -191,24 +207,26 @@ class EmojiHoarder: ObservableObject {
} }
} }
func download(emoji: Emoji) { nonisolated func download(emoji: Emoji, skipStoreIndex: Bool = false) {
Task.detached { Task.detached {
try? await emoji.downloadImage() try? await emoji.downloadImage()
await MainActor.run { await MainActor.run {
self.downloadedEmojis.insert(emoji.name) self.downloadedEmojis.insert(emoji.name)
self.downloadedEmojisArr.append(emoji.name) self.downloadedEmojisArr.append(emoji.name)
self.trie.dict[emoji.name]?.refresh() self.trie.dict[emoji.name]?.refresh()
if !skipStoreIndex { self.storeDownloadedIndexes() }
Haptic.success.trigger() Haptic.success.trigger()
} }
} }
} }
@MainActor @MainActor
func delete(emoji: Emoji) { func delete(emoji: Emoji, skipStoreIndex: Bool = false) {
emoji.deleteImage() emoji.deleteImage()
downloadedEmojis.remove(emoji.name) downloadedEmojis.remove(emoji.name)
downloadedEmojisArr.removeAll(where: { $0 == emoji.name }) downloadedEmojisArr.removeAll(where: { $0 == emoji.name })
self.trie.dict[emoji.name]?.refresh() self.trie.dict[emoji.name]?.refresh()
if !skipStoreIndex { storeDownloadedIndexes() }
Haptic.heavy.trigger() Haptic.heavy.trigger()
} }
@@ -263,22 +281,4 @@ class EmojiHoarder: ObservableObject {
var by: EmojiHoarder.SortLetterStatsBy = .count var by: EmojiHoarder.SortLetterStatsBy = .count
var ascending: Bool = true var ascending: Bool = true
} }
// func filterEmojis(byCategory category: FilterCategory, searchTerm: String) {
// guard category != .none else {
// filterEmojis(by: searchTerm)
// return
// }
// self.filterEmojis(by: searchTerm)
// DispatchQueue.main.async {
// switch category {
// case .none:
// fallthrough
// case .downloaded:
// withAnimation(.interactiveSpring) { self.filteredEmojis = self.filteredEmojis.filter { $0.isLocal } }
// case .notDownloaded:
// withAnimation(.interactiveSpring) { self.filteredEmojis = self.filteredEmojis.filter { !$0.isLocal } }
// }
// }
// }
} }

View File

@@ -24,7 +24,7 @@ struct SettingsView: View {
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
.clipShape(RoundedRectangle(cornerRadius: 24)) .clipShape(RoundedRectangle(cornerRadius: 24))
.foregroundStyle(.purple) .foregroundStyle(.purple)
.shadow(color: isDark ? .white : .purple, radius: 5) .shadow(color: isDark ? .white : .purple, radius: 2)
.padding(.trailing, 10) .padding(.trailing, 10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
Text("StickerSlack") Text("StickerSlack")
@@ -46,6 +46,10 @@ struct SettingsView: View {
Section { Section {
Text("\(hoarder.emojis.count) total Emoji") Text("\(hoarder.emojis.count) total Emoji")
Text("\(hoarder.downloadedEmojis.count) downloaded Emoji") Text("\(hoarder.downloadedEmojis.count) downloaded Emoji")
if hoarder.downloadedEmojis.count == hoarder.emojis.count {
Text("🎉")
.font(.largeTitle)
}
NavigationLink { NavigationLink {
List { List {
Picker(selection: $hoarder.letterStatsSorting.by) { Picker(selection: $hoarder.letterStatsSorting.by) {
@@ -55,16 +59,20 @@ struct SettingsView: View {
} label: { } label: {
Label("Sort by", systemImage: "arrow.up.arrow.down") Label("Sort by", systemImage: "arrow.up.arrow.down")
} }
.onChange(of: hoarder.letterStatsSorting.by) { _ in
hoarder.sortLetterStats(by: hoarder.letterStatsSorting)
}
Picker(selection: $hoarder.letterStatsSorting.ascending) { Picker(selection: $hoarder.letterStatsSorting.ascending) {
Text("Ascending").tag(true) Text("Ascending").tag(true)
Text("Descending").tag(false) Text("Descending").tag(false)
} label: { } label: {
Label("Order", systemImage: "greaterthan") Label("Order", systemImage: "greaterthan")
} }
.onChange(of: hoarder.letterStatsSorting) { _ in .onChange(of: hoarder.letterStatsSorting.ascending) { _ in
hoarder.sortLetterStats(by: hoarder.letterStatsSorting) hoarder.sortLetterStats(by: hoarder.letterStatsSorting)
} }
ForEach(hoarder.letterStats, id: \.self) { stat in ForEach(hoarder.letterStats, id: \.self) { stat in
HStack { HStack {
Text("\(stat.char)") Text("\(stat.char)")
@@ -82,12 +90,28 @@ struct SettingsView: View {
hoarder.setShowWelcome(to: true) hoarder.setShowWelcome(to: true)
} }
Section("Use with Caution") {
Button("download all", role: .destructive) {
hoarder.downloadAllStickers()
}
Button("delete all", role: .destructive) {
hoarder.deleteAllStickers()
}
}
Section("Debug") { Section("Debug") {
NavigationLink { NavigationLink {
TrieTestingView(hoarder: hoarder) TrieTestingView(hoarder: hoarder)
} label: { } label: {
Label("Tree", systemImage: "tree") Label("Tree", systemImage: "tree")
} }
Button(role: .destructive) {
hoarder.resetAllIndexes()
hoarder.buildTrie()
} label: {
Label("Reindex", systemImage: "list.bullet.clipboard.fill")
}
} }
// Section(content: <#T##() -> View#>, header: <#T##() -> View#>, footer: <#T##() -> View#>) // Section(content: <#T##() -> View#>, header: <#T##() -> View#>, footer: <#T##() -> View#>)
} }

View File

@@ -26,7 +26,7 @@ struct TrieTestingView: View {
.foregroundStyle(.blue) .foregroundStyle(.blue)
Button("reset", role: .destructive) { Button("reset", role: .destructive) {
hoarder.resetTrie() hoarder.resetAllIndexes()
} }
Button("add emojis!") { Button("add emojis!") {
hoarder.buildTrie() hoarder.buildTrie()