Skip to content

Commit 3798437

Browse files
committed
bump version
Signed-off-by: 82Flex <[email protected]>
1 parent b1a4e7d commit 3798437

File tree

4 files changed

+65
-53
lines changed

4 files changed

+65
-53
lines changed

TrollFools.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@
439439
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
440440
CLANG_ENABLE_MODULES = YES;
441441
CODE_SIGN_STYLE = Automatic;
442-
CURRENT_PROJECT_VERSION = 3;
442+
CURRENT_PROJECT_VERSION = 5;
443443
DEVELOPMENT_TEAM = GXZ23M5TP2;
444444
ENABLE_PREVIEWS = NO;
445445
GENERATE_INFOPLIST_FILE = YES;
@@ -481,7 +481,7 @@
481481
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
482482
CLANG_ENABLE_MODULES = YES;
483483
CODE_SIGN_STYLE = Automatic;
484-
CURRENT_PROJECT_VERSION = 3;
484+
CURRENT_PROJECT_VERSION = 5;
485485
DEVELOPMENT_TEAM = GXZ23M5TP2;
486486
ENABLE_PREVIEWS = NO;
487487
GENERATE_INFOPLIST_FILE = YES;

TrollFools/AppListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ final class AppListModel: ObservableObject {
7070
filter.$searchKeyword
7171
.combineLatest(filter.$showPatchedOnly)
7272
.throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true)
73-
.sink { _ in
73+
.sink { [weak self] _ in
7474
withAnimation {
75-
self.performFilter()
75+
self?.performFilter()
7676
}
7777
}
7878
.store(in: &cancellables)

TrollFools/EjectListView.swift

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
import CocoaLumberjackSwift
9+
import Combine
910
import SwiftUI
1011

1112
private let gDateFormatter: DateFormatter = {
@@ -30,13 +31,13 @@ struct InjectedPlugIn: Identifiable {
3031
struct PlugInCell: View {
3132
let plugIn: InjectedPlugIn
3233

33-
@EnvironmentObject var searchOptions: FilterOptions
34+
@EnvironmentObject var filter: FilterOptions
3435

3536
@available(iOS 15.0, *)
3637
var highlightedName: AttributedString {
3738
let name = plugIn.url.lastPathComponent
3839
var attributedString = AttributedString(name)
39-
if let range = attributedString.range(of: searchOptions.searchKeyword, options: [.caseInsensitive, .diacriticInsensitive]) {
40+
if let range = attributedString.range(of: filter.searchKeyword, options: [.caseInsensitive, .diacriticInsensitive]) {
4041
attributedString[range].foregroundColor = .accentColor
4142
}
4243
return attributedString
@@ -80,31 +81,61 @@ struct PlugInCell: View {
8081
}
8182
}
8283

83-
struct EjectListView: View {
84+
final class EjectListModel: ObservableObject {
8485
let app: App
86+
private var _injectedPlugIns: [InjectedPlugIn] = []
87+
88+
@Published var filter = FilterOptions()
89+
@Published var filteredPlugIns: [InjectedPlugIn] = []
90+
91+
private var cancellables = Set<AnyCancellable>()
8592

8693
init(_ app: App) {
8794
self.app = app
95+
reload()
96+
97+
filter.$searchKeyword
98+
.throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true)
99+
.sink { [weak self] _ in
100+
withAnimation {
101+
self?.performFilter()
102+
}
103+
}
104+
.store(in: &cancellables)
88105
}
89106

90-
@State var injectedPlugIns: [InjectedPlugIn] = []
91-
@State var isErrorOccurred: Bool = false
92-
@State var errorMessage: String = ""
107+
func reload() {
108+
self._injectedPlugIns = Injector.injectedPlugInURLs(app.url)
109+
.map { InjectedPlugIn(url: $0) }
110+
performFilter()
111+
}
93112

94-
@State var searchResults: [InjectedPlugIn] = []
95-
@StateObject var searchOptions = FilterOptions()
113+
func performFilter() {
114+
var filteredPlugIns = _injectedPlugIns
96115

97-
@State var isDeletingAll = false
98-
@StateObject var viewControllerHost = ViewControllerHost()
116+
if !filter.searchKeyword.isEmpty {
117+
filteredPlugIns = filteredPlugIns.filter {
118+
$0.url.lastPathComponent.localizedCaseInsensitiveContains(filter.searchKeyword)
119+
}
120+
}
99121

100-
var isSearching: Bool {
101-
return !searchOptions.searchKeyword.isEmpty
122+
self.filteredPlugIns = filteredPlugIns
102123
}
124+
}
125+
126+
struct EjectListView: View {
127+
@StateObject var vm: EjectListModel
103128

104-
var filteredPlugIns: [InjectedPlugIn] {
105-
isSearching ? searchResults : injectedPlugIns
129+
init(_ app: App) {
130+
_vm = StateObject(wrappedValue: EjectListModel(app))
106131
}
107132

133+
@State var isErrorOccurred: Bool = false
134+
@State var errorMessage: String = ""
135+
136+
@State var isDeletingAll = false
137+
@StateObject var viewControllerHost = ViewControllerHost()
138+
108139
var deleteAllButtonLabel: some View {
109140
HStack {
110141
Label(NSLocalizedString("Eject All", comment: ""), systemImage: "eject")
@@ -135,31 +166,31 @@ struct EjectListView: View {
135166
var ejectList: some View {
136167
List {
137168
Section {
138-
ForEach(filteredPlugIns) { plugin in
169+
ForEach(vm.filteredPlugIns) { plugin in
139170
if #available(iOS 16.0, *) {
140171
PlugInCell(plugIn: plugin)
141-
.environmentObject(searchOptions)
172+
.environmentObject(vm.filter)
142173
} else {
143174
PlugInCell(plugIn: plugin)
144-
.environmentObject(searchOptions)
175+
.environmentObject(vm.filter)
145176
.padding(.vertical, 4)
146177
}
147178
}
148179
.onDelete(perform: delete)
149180
} header: {
150-
Text(filteredPlugIns.isEmpty
181+
Text(vm.filteredPlugIns.isEmpty
151182
? NSLocalizedString("No Injected Plug-Ins", comment: "")
152183
: NSLocalizedString("Injected Plug-Ins", comment: ""))
153184
.font(.footnote)
154185
}
155186

156-
if !isSearching && !filteredPlugIns.isEmpty {
187+
if !vm.filter.isSearching && !vm.filteredPlugIns.isEmpty {
157188
Section {
158189
deleteAllButton
159190
.disabled(isDeletingAll)
160191
.foregroundColor(isDeletingAll ? .secondary : .red)
161192
} footer: {
162-
if app.isFromTroll {
193+
if vm.app.isFromTroll {
163194
Text(NSLocalizedString("Some plug-ins were not injected by TrollFools, please eject them with caution.", comment: ""))
164195
.font(.footnote)
165196
}
@@ -173,53 +204,41 @@ struct EjectListView: View {
173204
}
174205
.listStyle(.insetGrouped)
175206
.navigationTitle(NSLocalizedString("Plug-Ins", comment: ""))
176-
.navigationBarTitleDisplayMode(.inline)
207+
.animation(.easeOut, value: vm.filter.isSearching)
177208
.onViewWillAppear { viewController in
178209
viewControllerHost.viewController = viewController
179210
}
180-
.onAppear {
181-
reloadPlugIns()
182-
}
183211
}
184212

185213
var body: some View {
186214
if #available(iOS 15.0, *) {
187215
ejectList
188216
.refreshable {
189217
withAnimation {
190-
reloadPlugIns()
218+
vm.reload()
191219
}
192220
}
193221
.searchable(
194-
text: $searchOptions.searchKeyword,
222+
text: $vm.filter.searchKeyword,
195223
placement: .automatic,
196224
prompt: NSLocalizedString("Search…", comment: "")
197225
)
198226
.textInputAutocapitalization(.never)
199-
.onChange(of: searchOptions.searchKeyword) { keyword in
200-
fetchSearchResults(for: keyword)
201-
}
202227
} else {
203228
// Fallback on earlier versions
204229
ejectList
205230
}
206231
}
207232

208-
func reloadPlugIns() {
209-
searchOptions.reset()
210-
injectedPlugIns = Injector.injectedPlugInURLs(app.url)
211-
.map { InjectedPlugIn(url: $0) }
212-
}
213-
214233
func delete(at offsets: IndexSet) {
215234
do {
216-
let plugInsToRemove = offsets.map { filteredPlugIns[$0] }
235+
let plugInsToRemove = offsets.map { vm.filteredPlugIns[$0] }
217236
let plugInURLsToRemove = plugInsToRemove.map { $0.url }
218-
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
237+
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)
219238
try injector.eject(plugInURLsToRemove)
220239

221-
app.reloadInjectedStatus()
222-
reloadPlugIns()
240+
vm.app.reloadInjectedStatus()
241+
vm.reload()
223242
} catch {
224243
DDLogError("\(error)")
225244

@@ -230,7 +249,7 @@ struct EjectListView: View {
230249

231250
func deleteAll() {
232251
do {
233-
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
252+
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)
234253

235254
let view = viewControllerHost.viewController?
236255
.navigationController?.view
@@ -245,8 +264,8 @@ struct EjectListView: View {
245264
defer {
246265
DispatchQueue.main.async {
247266
withAnimation {
248-
app.reloadInjectedStatus()
249-
reloadPlugIns()
267+
vm.app.reloadInjectedStatus()
268+
vm.reload()
250269
isDeletingAll = false
251270
}
252271

@@ -274,10 +293,4 @@ struct EjectListView: View {
274293
isErrorOccurred = true
275294
}
276295
}
277-
278-
func fetchSearchResults(for query: String) {
279-
searchResults = injectedPlugIns.filter { plugin in
280-
plugin.url.lastPathComponent.localizedCaseInsensitiveContains(query)
281-
}
282-
}
283296
}

TrollFools/OptionView.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ struct OptionView: View {
102102
}
103103
.padding()
104104
.navigationTitle(app.name)
105-
.navigationBarTitleDisplayMode(.inline)
106105
.fileImporter(
107106
isPresented: $isImporterPresented,
108107
allowedContentTypes: [

0 commit comments

Comments
 (0)