From 1c4ef6896d343c9f1574ab521306f663a3052e33 Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:14:51 +0000 Subject: [PATCH] quicker opening of the imessage app, support ios 17 and below again --- StickerSlack.xcodeproj/project.pbxproj | 20 +++ StickerSlack/Emoji/EmojiHoarder.swift | 6 +- StickerSlack/SwiftUI/BrowseView.swift | 24 +++ StickerSlack/SwiftUI/ContentView.swift | 146 ++++++++---------- StickerSlack/SwiftUI/DownloadedView.swift | 64 ++++++++ StickerSlack/SwiftUI/SearchView.swift | 33 ++++ StickerSlack/UIKit/EmojiCollectionView.swift | 12 ++ .../StickerBrowserDataSource.swift | 2 +- 8 files changed, 219 insertions(+), 88 deletions(-) create mode 100644 StickerSlack/SwiftUI/BrowseView.swift create mode 100644 StickerSlack/SwiftUI/DownloadedView.swift create mode 100644 StickerSlack/SwiftUI/SearchView.swift diff --git a/StickerSlack.xcodeproj/project.pbxproj b/StickerSlack.xcodeproj/project.pbxproj index 11f9bc1..b526c1d 100644 --- a/StickerSlack.xcodeproj/project.pbxproj +++ b/StickerSlack.xcodeproj/project.pbxproj @@ -23,6 +23,13 @@ A949B1F52EA04E8200215164 /* StickerSlackApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949B1F12EA04E8200215164 /* StickerSlackApp.swift */; }; A949B1F82EA04F2300215164 /* EmojiHoarder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949B1F72EA04F2300215164 /* EmojiHoarder.swift */; }; A949B1FB2EA0518800215164 /* SlackResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949B1FA2EA0518800215164 /* SlackResponse.swift */; }; + A955B3EB2EC22C0200E1732D /* Haptics in Frameworks */ = {isa = PBXBuildFile; productRef = A9112EAB2EAFFDB0006739E2 /* Haptics */; }; + A955B3ED2EC22C4A00E1732D /* DownloadedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3EC2EC22C4A00E1732D /* DownloadedView.swift */; }; + A955B3EE2EC22C4A00E1732D /* DownloadedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3EC2EC22C4A00E1732D /* DownloadedView.swift */; }; + A955B3F12EC22E9700E1732D /* BrowseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3F02EC22E9700E1732D /* BrowseView.swift */; }; + A955B3F22EC22E9700E1732D /* BrowseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3F02EC22E9700E1732D /* BrowseView.swift */; }; + A955B3F52EC22EE900E1732D /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3F42EC22EE900E1732D /* SearchView.swift */; }; + A955B3F62EC22EE900E1732D /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A955B3F42EC22EE900E1732D /* SearchView.swift */; }; A9773C2F2EA54AF000F3B753 /* EmojiPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9773C2E2EA54AF000F3B753 /* EmojiPreview.swift */; }; A986A6AE2EB658DF00B6E0FA /* Messages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A969D6932EA3E86500399C05 /* Messages.framework */; }; A986A6BA2EB658E100B6E0FA /* StickerSlackiMessageApp.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A986A6AD2EB658DF00B6E0FA /* StickerSlackiMessageApp.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -101,6 +108,9 @@ A949B1FA2EA0518800215164 /* SlackResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SlackResponse.swift; sourceTree = ""; }; A950E87D2EB57F1100A9F873 /* StickerSlack.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = StickerSlack.xctestplan; sourceTree = ""; }; A950E8802EB6C13700A9F873 /* StickerSlackiMessageApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = StickerSlackiMessageApp.entitlements; sourceTree = ""; }; + A955B3EC2EC22C4A00E1732D /* DownloadedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadedView.swift; sourceTree = ""; }; + A955B3F02EC22E9700E1732D /* BrowseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseView.swift; sourceTree = ""; }; + A955B3F42EC22EE900E1732D /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; A969D6932EA3E86500399C05 /* Messages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Messages.framework; path = Library/Frameworks/Messages.framework; sourceTree = DEVELOPER_DIR; }; A9773C2E2EA54AF000F3B753 /* EmojiPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiPreview.swift; sourceTree = ""; }; A986A6AD2EB658DF00B6E0FA /* StickerSlackiMessageApp.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = StickerSlackiMessageApp.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -125,6 +135,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A955B3EB2EC22C0200E1732D /* Haptics in Frameworks */, A924C3782EA9225800F20781 /* Haptics in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -207,6 +218,9 @@ A949B1F02EA04E8200215164 /* ContentView.swift */, A9BBC5172EB8FA4500FFE82F /* ViewModifiers.swift */, A91C098C2EBBD7AB00210C34 /* Emoji */, + A955B3EC2EC22C4A00E1732D /* DownloadedView.swift */, + A955B3F02EC22E9700E1732D /* BrowseView.swift */, + A955B3F42EC22EE900E1732D /* SearchView.swift */, ); path = SwiftUI; sourceTree = ""; @@ -450,9 +464,12 @@ A949B1F52EA04E8200215164 /* StickerSlackApp.swift in Sources */, A9104C802EB4022500D160EA /* MSSticker.swift in Sources */, A9EB72392EB93FDB00658CEB /* EmojiCollectionView.swift in Sources */, + A955B3EE2EC22C4A00E1732D /* DownloadedView.swift in Sources */, A949B1FB2EA0518800215164 /* SlackResponse.swift in Sources */, + A955B3F52EC22EE900E1732D /* SearchView.swift in Sources */, A935437B2EB2A3C800BB80A4 /* FilterCategory.swift in Sources */, A9C172DD2EB8C9AC008A7885 /* Trie.swift in Sources */, + A955B3F22EC22E9700E1732D /* BrowseView.swift in Sources */, A9EB724F2EB94A6B00658CEB /* TrieTestingView.swift in Sources */, A924C3732EA9127200F20781 /* Emoji.swift in Sources */, A9D15B8B2EB1142C00404792 /* EmojiPack.swift in Sources */, @@ -484,12 +501,15 @@ files = ( A9104C7F2EB4022500D160EA /* MSSticker.swift in Sources */, A9B9A8302EB2CD0B004C9245 /* Emoji.swift in Sources */, + A955B3F12EC22E9700E1732D /* BrowseView.swift in Sources */, A9B9A82F2EB2CCED004C9245 /* EmojiHoarder.swift in Sources */, A9EB724A2EB948E000658CEB /* EmojiCollectionView.swift in Sources */, A9EB724D2EB94A6B00658CEB /* TrieTestingView.swift in Sources */, A9BBC51A2EB8FA4500FFE82F /* ViewModifiers.swift in Sources */, + A955B3ED2EC22C4A00E1732D /* DownloadedView.swift in Sources */, A9C172DC2EB8C9AC008A7885 /* Trie.swift in Sources */, A9EB72472EB948C400658CEB /* EmojiRow.swift in Sources */, + A955B3F62EC22EE900E1732D /* SearchView.swift in Sources */, A9B9A8322EB2CD29004C9245 /* SlackResponse.swift in Sources */, A9B9A82E2EB2CCBE004C9245 /* StickerSlackTests.swift in Sources */, A9B9A8312EB2CD14004C9245 /* FilterCategory.swift in Sources */, diff --git a/StickerSlack/Emoji/EmojiHoarder.swift b/StickerSlack/Emoji/EmojiHoarder.swift index 8a2a406..61e0a43 100644 --- a/StickerSlack/Emoji/EmojiHoarder.swift +++ b/StickerSlack/Emoji/EmojiHoarder.swift @@ -26,10 +26,10 @@ class EmojiHoarder: ObservableObject { @Published var downloadedEmojis: Set = [] @Published var searchTerm: String = "" - init(localOnly: Bool = false) { + init(localOnly: Bool = false, skipIndex: Bool = false) { let localDB = loadLocalDB() withAnimation { self.emojis = localDB } - buildTrie() + if !skipIndex { buildTrie() } withAnimation { self.filteredEmojis = [] } guard !localOnly else { return } @@ -37,7 +37,7 @@ class EmojiHoarder: ObservableObject { print("start loading remote db") await self.loadRemoteDB() print("end") - await self.buildTrie() + if !skipIndex { await self.buildTrie() } } } diff --git a/StickerSlack/SwiftUI/BrowseView.swift b/StickerSlack/SwiftUI/BrowseView.swift new file mode 100644 index 0000000..199d375 --- /dev/null +++ b/StickerSlack/SwiftUI/BrowseView.swift @@ -0,0 +1,24 @@ +// +// BrowseView.swift +// StickerSlack +// +// Created by neon443 on 10/11/2025. +// + +import SwiftUI + +struct BrowseView: View { + @ObservedObject var hoarder: EmojiHoarder = .shared + + var body: some View { + List { + ForEach(hoarder.emojis, id: \.self) { emoji in + EmojiRow(emoji: emoji) + } + } + } +} + +#Preview { + BrowseView() +} diff --git a/StickerSlack/SwiftUI/ContentView.swift b/StickerSlack/SwiftUI/ContentView.swift index 0363315..90d0bc0 100644 --- a/StickerSlack/SwiftUI/ContentView.swift +++ b/StickerSlack/SwiftUI/ContentView.swift @@ -11,95 +11,73 @@ import Haptics struct ContentView: View { @StateObject var hoarder: EmojiHoarder = .shared - @State var searchTerm: String = "" - - var minColWidth: CGFloat { 75 } - var spacing: CGFloat { 10 } - var col: GridItem { - GridItem( - .flexible(minimum: minColWidth, maximum: 125), - spacing: spacing, - alignment: .center - ) - } - - @Environment(\.colorScheme) var colorScheme - var isDark: Bool { colorScheme == .dark } var body: some View { - TabView { - ScrollView { - let columns: Int = max(1, Int((UIScreen.main.bounds.width - 2*spacing) / (minColWidth + spacing))) - let layout = Array(repeating: col, count: columns) - LazyVGrid(columns: layout, spacing: 10) { - ForEach(hoarder.emojis, id: \.self) { emoji in - if hoarder.downloadedEmojis.contains(emoji.name) { - ZStack { - Rectangle() - .foregroundStyle(isDark ? .black : .white) - EmojiPreview(emoji: emoji) - RoundedRectangle(cornerRadius: 15) - .stroke(.gray, lineWidth: 1) - } - .aspectRatio(1, contentMode: .fit) - .clipShape(RoundedRectangle(cornerRadius: 15)) - .contextMenu { - Text(emoji.name) - Button("Share", systemImage: "square.and.arrow.up") { - - } - ShareLink("Share", item: emoji.localImageURL, subject: nil, message: nil) - ShareLink("Share", item: emoji.remoteImageURL, subject: nil, message: nil) - Divider() - Button("Delete", systemImage: "trash.fill", role: .destructive) { - hoarder.delete(emoji: emoji) - } - } + NavigationSplitView { + if #available(iOS 18, *) { + TabView { + Tab("Downloaded", systemImage: "arrow.down.circle.fill") { + DownloadedView() + } + + Tab("Browse", systemImage: "square.grid.2x2.fill") { + BrowseView() + } + +// Tab { +// List { +// Text("\(searchTerm.isEmpty ? hoarder.emojis.count : hoarder.filteredEmojis.count) Emoji") +// +// ForEach(hoarder.filteredEmojis, id: \.self) { name in +// if let emoji = hoarder.trie.dict[name] { +// EmojiRow(emoji: emoji) +// } +// } +// } +// .onChange(of: searchTerm) { _ in +// hoarder.filterEmojis(by: searchTerm) +// } +// .refreshable { +// Task.detached { +// await hoarder.refreshDB() +// } +// searchTerm = "" +// } +// } label: { +// Label("Search", systemImage: "magnifyingglass") +// } + + Tab("Tree", systemImage: "tree.fill") { + TrieTestingView() + } + + Tab(role: .search) { + SearchView() + } + } + .searchable(text: $hoarder.searchTerm, placement: .automatic) + } else { + TabView { + DownloadedView() + .tabItem { + Label("Downloaded", systemImage: "arrow.down.circle.fill") + } + BrowseView() + .tabItem { + Label("Browse", systemImage: "square.grid.2x2.fill") + } + TrieTestingView() + .tabItem { + Label("Trie", systemImage: "tree.fill") + } + SearchView() + .tabItem { + Label("Search", systemImage: "magnifyingglass") } - } - } - .padding(.horizontal, spacing) - } - .tabItem { - Label("Downloaded", systemImage: "arrow.down.circle.fill") - } - - List { - ForEach(hoarder.emojis, id: \.self) { emoji in - EmojiRow(emoji: emoji) } } - .tabItem { - Label("Browse", systemImage: "square.grid.2x2.fill") - } - - List { - Text("\(searchTerm.isEmpty ? hoarder.emojis.count : hoarder.filteredEmojis.count) Emoji") - - ForEach(hoarder.filteredEmojis, id: \.self) { name in - if let emoji = hoarder.trie.dict[name] { - EmojiRow(emoji: emoji) - } - } - } - .onChange(of: searchTerm) { _ in - hoarder.filterEmojis(by: searchTerm) - } - .refreshable { - Task.detached { - await hoarder.refreshDB() - } - searchTerm = "" - } - .tabItem { - Label("Search", systemImage: "magnifyingglass") - } - - TrieTestingView() - .tabItem { - Label("Tree", systemImage: "tree.fill") - } + } detail: { + Text("") } - .searchable(text: $searchTerm, placement: .automatic) } } diff --git a/StickerSlack/SwiftUI/DownloadedView.swift b/StickerSlack/SwiftUI/DownloadedView.swift new file mode 100644 index 0000000..3851bbd --- /dev/null +++ b/StickerSlack/SwiftUI/DownloadedView.swift @@ -0,0 +1,64 @@ +// +// DownloadedView.swift +// StickerSlack +// +// Created by neon443 on 10/11/2025. +// + +import SwiftUI + +struct DownloadedView: View { + @ObservedObject var hoarder: EmojiHoarder = .shared + + @Environment(\.colorScheme) var colorScheme + var isDark: Bool { colorScheme == .dark } + + var minColWidth: CGFloat { 75 } + var spacing: CGFloat { 10 } + var col: GridItem { + GridItem( + .flexible(minimum: minColWidth, maximum: 125), + spacing: spacing, + alignment: .center + ) + } + + var body: some View { + ScrollView { + let columns: Int = max(1, Int((UIScreen.main.bounds.width - 2*spacing) / (minColWidth + spacing))) + let layout = Array(repeating: col, count: columns) + LazyVGrid(columns: layout, spacing: 10) { + ForEach(hoarder.emojis, id: \.self) { emoji in + if hoarder.downloadedEmojis.contains(emoji.name) { + ZStack { + Rectangle() + .foregroundStyle(isDark ? .black : .white) + EmojiPreview(emoji: emoji) + RoundedRectangle(cornerRadius: 15) + .stroke(.gray, lineWidth: 1) + } + .aspectRatio(1, contentMode: .fit) + .clipShape(RoundedRectangle(cornerRadius: 15)) + .contextMenu { + Text(emoji.name) + Button("Share", systemImage: "square.and.arrow.up") { + + } + ShareLink("Share", item: emoji.localImageURL, subject: nil, message: nil) + ShareLink("Share", item: emoji.remoteImageURL, subject: nil, message: nil) + Divider() + Button("Delete", systemImage: "trash.fill", role: .destructive) { + hoarder.delete(emoji: emoji) + } + } + } + } + } + .padding(.horizontal, spacing) + } + } +} + +#Preview { + DownloadedView() +} diff --git a/StickerSlack/SwiftUI/SearchView.swift b/StickerSlack/SwiftUI/SearchView.swift new file mode 100644 index 0000000..2557bc8 --- /dev/null +++ b/StickerSlack/SwiftUI/SearchView.swift @@ -0,0 +1,33 @@ +// +// SearchView.swift +// StickerSlack +// +// Created by neon443 on 10/11/2025. +// + +import SwiftUI + +struct SearchView: View { + @ObservedObject var hoarder: EmojiHoarder = .shared + + var body: some View { + NavigationStack { + List { + Text("\(hoarder.searchTerm.isEmpty ? hoarder.emojis.count : hoarder.filteredEmojis.count) Emoji") + + ForEach(hoarder.filteredEmojis, id: \.self) { name in + if let emoji = hoarder.trie.dict[name] { + EmojiRow(emoji: emoji) + } + } + } + .onChange(of: hoarder.searchTerm) { _ in + hoarder.filterEmojis(by: hoarder.searchTerm) + } + } + } +} + +#Preview { + SearchView() +} diff --git a/StickerSlack/UIKit/EmojiCollectionView.swift b/StickerSlack/UIKit/EmojiCollectionView.swift index 2735fd5..6666f7f 100644 --- a/StickerSlack/UIKit/EmojiCollectionView.swift +++ b/StickerSlack/UIKit/EmojiCollectionView.swift @@ -73,3 +73,15 @@ struct EmojiCollectionView: UIViewRepresentable { } } } +// +//class EmojiCell: UITableViewCell { +// override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { +// let l = UILabel() +// l.text = "ifosa" +// self.view = l +// } +// +// required init?(coder: NSCoder) { +// fatalError("init(coder:) has not been implemented") +// } +//} diff --git a/StickerSlackiMessageApp/StickerBrowserDataSource.swift b/StickerSlackiMessageApp/StickerBrowserDataSource.swift index 49746f6..2b6b048 100644 --- a/StickerSlackiMessageApp/StickerBrowserDataSource.swift +++ b/StickerSlackiMessageApp/StickerBrowserDataSource.swift @@ -9,7 +9,7 @@ import Foundation import Messages class StickerBrowserDataSource: NSObject, MSStickerBrowserViewDataSource { - var hoarder: EmojiHoarder = EmojiHoarder(localOnly: true) + var hoarder: EmojiHoarder = EmojiHoarder(localOnly: true, skipIndex: true) var emojis: [MSSticker] = []