mirror of
https://github.com/neon443/StickerSlack.git
synced 2026-03-11 05:19:13 +00:00
added an easter egg for the idiot who dowloads all the emojis
fix downloadall/deleteall stickers
This commit is contained in:
@@ -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 */,
|
||||||
|
|||||||
@@ -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 } }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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#>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user