diff --git a/StickerSlack.xcodeproj/project.pbxproj b/StickerSlack.xcodeproj/project.pbxproj index 1e9e074..d9a053f 100644 --- a/StickerSlack.xcodeproj/project.pbxproj +++ b/StickerSlack.xcodeproj/project.pbxproj @@ -663,7 +663,7 @@ INFOPLIST_FILE = StickerSlackiMessageExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = StickerSlackiMessageExtension; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 26.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -695,7 +695,7 @@ INFOPLIST_FILE = StickerSlackiMessageExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = StickerSlackiMessageExtension; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 26.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/StickerSlack/Emoji/Emoji.swift b/StickerSlack/Emoji/Emoji.swift index 6417068..4ed7c3c 100644 --- a/StickerSlack/Emoji/Emoji.swift +++ b/StickerSlack/Emoji/Emoji.swift @@ -13,13 +13,12 @@ import UniformTypeIdentifiers struct Emoji: Codable, Identifiable, Hashable { var id: UUID - var uiID: UUID = UUID() + var uiID: UUID var name: String var localImageURL: URL { let urlString = remoteImageURL.absoluteString let split = urlString.split(separator: ".") let fileExtension = ".\(split.last ?? "png")" -// return EmojiHoarder.container.appendingPathComponent(id.uuidString+fileExtension, conformingTo: .image) return URL(string: EmojiHoarder.container.absoluteString+id.uuidString+fileExtension)! } var remoteImageURL: URL @@ -53,6 +52,7 @@ struct Emoji: Codable, Identifiable, Hashable { init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(UUID.self, forKey: .id) + self.uiID = id self.name = try container.decode(String.self, forKey: .name) self.remoteImageURL = try container.decode(URL.self, forKey: .remoteImageURL) } @@ -62,6 +62,7 @@ struct Emoji: Codable, Identifiable, Hashable { id: UUID = UUID() ) { self.id = id + self.uiID = id self.name = apiEmoji.name self.remoteImageURL = apiEmoji.url } diff --git a/StickerSlack/Emoji/SlackResponse.swift b/StickerSlack/Emoji/SlackResponse.swift index b178432..9fbe1e5 100644 --- a/StickerSlack/Emoji/SlackResponse.swift +++ b/StickerSlack/Emoji/SlackResponse.swift @@ -13,7 +13,6 @@ struct SlackResponse: Identifiable, Codable { var name: String var imageUrl: String var alias: String? - var expiration: Date static func toEmojis(from response: [SlackResponse]?) -> [Emoji]? { guard let response else { return nil } diff --git a/StickerSlack/EmojiHoarder.swift b/StickerSlack/EmojiHoarder.swift index 4ab2520..5f5a1c7 100644 --- a/StickerSlack/EmojiHoarder.swift +++ b/StickerSlack/EmojiHoarder.swift @@ -25,11 +25,9 @@ class EmojiHoarder: ObservableObject { withAnimation { self.emojis = loadLocalDB() } withAnimation { self.filteredEmojis = self.emojis } - Task(priority: .high) { - if let fetched = await self.fetchRemoteDB() { - withAnimation { self.emojis = fetched } - withAnimation { self.filteredEmojis = fetched } - } + Task.detached { + print(Thread.current) + await self.loadRemoteDB() } } @@ -55,12 +53,20 @@ class EmojiHoarder: ObservableObject { return [] } + func loadRemoteDB() async { + async let fetched = self.fetchRemoteDB() + if let fetched = await fetched { + withAnimation { self.emojis = fetched } + withAnimation { self.filteredEmojis = fetched } + } + } + func fetchRemoteDB() async -> [Emoji]? { do { - let (data, _) = try await URLSession.shared.data(from: endpoint) + async let (data, _) = try URLSession.shared.data(from: endpoint) decoder.dateDecodingStrategy = .iso8601 - let decoded: [SlackResponse] = try! decoder.decode([SlackResponse].self, from: data) - storeDB(data: data) + let decoded: [SlackResponse] = try decoder.decode([SlackResponse].self, from: await data) + try storeDB(data: await data) return SlackResponse.toEmojis(from: decoded) } catch { print(error.localizedDescription) @@ -69,12 +75,14 @@ class EmojiHoarder: ObservableObject { } func refreshDB(withCallback callback: (() -> Void)? = nil) { - Task { - guard let fetched = try? await fetchRemoteDB() else { return } - withAnimation { self.emojis = fetched } - withAnimation { self.filteredEmojis = fetched } - if let callback { - callback() + Task.detached { + guard let fetched = await self.fetchRemoteDB() else { return } + DispatchQueue.main.async { + withAnimation { self.emojis = fetched } + withAnimation { self.filteredEmojis = fetched } + if let callback { + callback() + } } } } @@ -84,8 +92,8 @@ class EmojiHoarder: ObservableObject { withAnimation(.interactiveSpring) { self.filteredEmojis = emojis } return } - Task { - let filtered = emojis.filter { $0.name.localizedCaseInsensitiveContains(searchTerm) } + Task.detached { + let filtered = await self.emojis.filter { $0.name.localizedCaseInsensitiveContains(searchTerm) } DispatchQueue.main.async { withAnimation(.interactiveSpring) { self.filteredEmojis = filtered } } @@ -97,15 +105,15 @@ class EmojiHoarder: ObservableObject { filterEmojis(by: searchTerm) return } - Task { - filterEmojis(by: searchTerm) + self.filterEmojis(by: searchTerm) + DispatchQueue.main.async { switch category { case .none: fallthrough case .downloaded: - withAnimation(.interactiveSpring) { filteredEmojis = filteredEmojis.filter { $0.isLocal } } + withAnimation(.interactiveSpring) { self.filteredEmojis = self.filteredEmojis.filter { $0.isLocal } } case .notDownloaded: - withAnimation(.interactiveSpring) { filteredEmojis = filteredEmojis.filter { !$0.isLocal } } + withAnimation(.interactiveSpring) { self.filteredEmojis = self.filteredEmojis.filter { !$0.isLocal } } } } } diff --git a/StickerSlack/Views/EmojiPreview.swift b/StickerSlack/Views/EmojiPreview.swift index 20827e0..e877737 100644 --- a/StickerSlack/Views/EmojiPreview.swift +++ b/StickerSlack/Views/EmojiPreview.swift @@ -17,9 +17,8 @@ struct EmojiPreview: View { VStack(alignment: .leading) { Text(emoji.name) Group { - if let localImage = try? Data(contentsOf: emoji.localImageURL), - let image = UIImage(data: localImage) { - Image(uiImage: image) + if emoji.isLocal { + Image(uiImage: emoji.image!) .resizable().scaledToFit() .border(.orange) .overlay(alignment: .bottomLeading) { diff --git a/StickerSlackTests/StickerSlackTests.swift b/StickerSlackTests/StickerSlackTests.swift index 525b438..98f18d4 100644 --- a/StickerSlackTests/StickerSlackTests.swift +++ b/StickerSlackTests/StickerSlackTests.swift @@ -23,4 +23,13 @@ struct StickerSlackTests { } } + @Test func filteringEmojis() async throws { + let searchQueries = ["heavysob", "yay", "afsdjk", "afhjskf", "g4", "aqua-osx", "neotunes", "", "", ""] + for query in searchQueries { + print(query) + hoarder.filteredEmojis = [] + hoarder.filterEmojis(by: query) + print(hoarder.filteredEmojis.count) + } + } } diff --git a/StickerSlackiMessageExtension/Base.lproj/MainInterface.storyboard b/StickerSlackiMessageExtension/Base.lproj/MainInterface.storyboard index f2cbcc0..22a1a2b 100644 --- a/StickerSlackiMessageExtension/Base.lproj/MainInterface.storyboard +++ b/StickerSlackiMessageExtension/Base.lproj/MainInterface.storyboard @@ -15,19 +15,8 @@ - - - - - - - diff --git a/StickerSlackiMessageExtension/MessagesViewController.swift b/StickerSlackiMessageExtension/MessagesViewController.swift index 998fa46..2cac48c 100644 --- a/StickerSlackiMessageExtension/MessagesViewController.swift +++ b/StickerSlackiMessageExtension/MessagesViewController.swift @@ -20,13 +20,6 @@ class MessagesViewController: MSMessagesAppViewController { // MARK: - Conversation Handling override func willBecomeActive(with conversation: MSConversation) { - let l = UILabel() - l.frame = CGRect(x: 20, y: 20, width: 200, height: 40) - l.textColor = .systemOrange - l.text = "hii!" - view.addSubview(l) - view.bringSubviewToFront(l) - let stickerBrowser = MSStickerBrowserView(frame: .zero, stickerSize: .regular) stickerBrowser.frame = CGRect(x: 60, y: 20, width: 200, height: 600) stickerBrowser.dataSource = dataSource