Skip to content

Commit 7503dd4

Browse files
committed
fix: ios 14 searchable and refreshable
Signed-off-by: Lessica <82flex@gmail.com>
1 parent 073b463 commit 7503dd4

File tree

4 files changed

+126
-4
lines changed

4 files changed

+126
-4
lines changed

TrollFools.xcodeproj/project.pbxproj

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
61EFA3792D3108BD00159442 /* InjectorV3+Eject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61EFA3782D3108B700159442 /* InjectorV3+Eject.swift */; };
3434
61EFA37B2D31165700159442 /* InjectorV3+Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61EFA37A2D31165000159442 /* InjectorV3+Backup.swift */; };
3535
61EFA37D2D311DA800159442 /* InjectorV3+Inject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61EFA37C2D311DA300159442 /* InjectorV3+Inject.swift */; };
36+
61F595622D6B42340034DD83 /* SwiftUIIntrospect-Static in Frameworks */ = {isa = PBXBuildFile; productRef = 61F595612D6B42340034DD83 /* SwiftUIIntrospect-Static */; };
3637
CC0E80FB2C54F84000B137B4 /* mv-15 in Resources */ = {isa = PBXBuildFile; fileRef = CC0E80FA2C54F84000B137B4 /* mv-15 */; };
3738
CC1548C92C4A6B2100A4173E /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = CC1548C82C4A6B2100A4173E /* ZIPFoundation */; };
3839
CC1548D12C4A6B8200A4173E /* ct_bypass in Resources */ = {isa = PBXBuildFile; fileRef = CC1548CF2C4A6B8200A4173E /* ct_bypass */; };
@@ -155,6 +156,7 @@
155156
61EFA3692D3026D400159442 /* CocoaLumberjackSwift in Frameworks */,
156157
CC1548FC2C4AADBB00A4173E /* MachOKit in Frameworks */,
157158
CC1548C92C4A6B2100A4173E /* ZIPFoundation in Frameworks */,
159+
61F595622D6B42340034DD83 /* SwiftUIIntrospect-Static in Frameworks */,
158160
);
159161
runOnlyForDeploymentPostprocessing = 0;
160162
};
@@ -336,6 +338,7 @@
336338
61EFA3662D3026D400159442 /* CocoaLumberjack */,
337339
61EFA3682D3026D400159442 /* CocoaLumberjackSwift */,
338340
61EFA36A2D3026D400159442 /* CocoaLumberjackSwiftLogBackend */,
341+
61F595612D6B42340034DD83 /* SwiftUIIntrospect-Static */,
339342
);
340343
productName = TrollFools;
341344
productReference = CCF470562C4A4649008D8197 /* TrollFools.app */;
@@ -373,6 +376,7 @@
373376
CC1548FA2C4AADBB00A4173E /* XCRemoteSwiftPackageReference "MachOKit" */,
374377
61946B242D2FD8AB009E0AC4 /* XCRemoteSwiftPackageReference "swift-collections" */,
375378
61EFA3652D3026D400159442 /* XCRemoteSwiftPackageReference "CocoaLumberjack" */,
379+
61F595602D6B42340034DD83 /* XCRemoteSwiftPackageReference "swiftui-introspect" */,
376380
);
377381
productRefGroup = CCF470572C4A4649008D8197 /* Products */;
378382
projectDirPath = "";
@@ -722,6 +726,14 @@
722726
minimumVersion = 3.8.5;
723727
};
724728
};
729+
61F595602D6B42340034DD83 /* XCRemoteSwiftPackageReference "swiftui-introspect" */ = {
730+
isa = XCRemoteSwiftPackageReference;
731+
repositoryURL = "https://github.com/siteline/swiftui-introspect.git";
732+
requirement = {
733+
kind = exactVersion;
734+
version = 1.0.0;
735+
};
736+
};
725737
CC1548C72C4A6B2100A4173E /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = {
726738
isa = XCRemoteSwiftPackageReference;
727739
repositoryURL = "https://github.com/weichsel/ZIPFoundation.git";
@@ -761,6 +773,11 @@
761773
package = 61EFA3652D3026D400159442 /* XCRemoteSwiftPackageReference "CocoaLumberjack" */;
762774
productName = CocoaLumberjackSwiftLogBackend;
763775
};
776+
61F595612D6B42340034DD83 /* SwiftUIIntrospect-Static */ = {
777+
isa = XCSwiftPackageProductDependency;
778+
package = 61F595602D6B42340034DD83 /* XCRemoteSwiftPackageReference "swiftui-introspect" */;
779+
productName = "SwiftUIIntrospect-Static";
780+
};
764781
CC1548C82C4A6B2100A4173E /* ZIPFoundation */ = {
765782
isa = XCSwiftPackageProductDependency;
766783
package = CC1548C72C4A6B2100A4173E /* XCRemoteSwiftPackageReference "ZIPFoundation" */;

TrollFools.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"originHash" : "49389104b8f7c5e7748f8b2d001d5306d97f420c084d744c8074f907de6f8af3",
2+
"originHash" : "a907ffaa2503d231886aa36022355e9b74e06eb63a5667ed29b71df156442fe6",
33
"pins" : [
44
{
55
"identity" : "cocoalumberjack",
@@ -37,6 +37,15 @@
3737
"version" : "1.6.2"
3838
}
3939
},
40+
{
41+
"identity" : "swiftui-introspect",
42+
"kind" : "remoteSourceControl",
43+
"location" : "https://github.com/siteline/swiftui-introspect.git",
44+
"state" : {
45+
"revision" : "3ba734dd20faada0e3234b68e78db97005315f0e",
46+
"version" : "1.0.0"
47+
}
48+
},
4049
{
4150
"identity" : "zipfoundation",
4251
"kind" : "remoteSourceControl",

TrollFools/AppListView.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77

88
import CocoaLumberjackSwift
99
import SwiftUI
10+
import SwiftUIIntrospect
1011

1112
struct AppListView: View {
13+
14+
@StateObject var searchViewModel = AppListSearchViewModel()
1215
@EnvironmentObject var appList: AppListModel
1316

1417
@State var isErrorOccurred: Bool = false
@@ -269,6 +272,44 @@ struct AppListView: View {
269272
} else {
270273
// Fallback on earlier versions
271274
appListView
275+
.onChange(of: appList.filter.showPatchedOnly) { showPatchedOnly in
276+
if let searchBar = searchViewModel.searchController?.searchBar {
277+
searchBar.placeholder = (showPatchedOnly
278+
? NSLocalizedString("Search Patched…", comment: "")
279+
: NSLocalizedString("Search…", comment: ""))
280+
}
281+
}
282+
.onReceive(searchViewModel.$searchKeyword) {
283+
appList.filter.searchKeyword = $0
284+
}
285+
.introspect(.list, on: .iOS(.v14)) { tableView in
286+
if tableView.refreshControl == nil {
287+
tableView.refreshControl = {
288+
let refreshControl = UIRefreshControl()
289+
refreshControl.addAction(UIAction { action in
290+
appList.reload()
291+
if let control = action.sender as? UIRefreshControl {
292+
control.endRefreshing()
293+
}
294+
}, for: .valueChanged)
295+
return refreshControl
296+
}()
297+
}
298+
}
299+
.introspect(.viewController, on: .iOS(.v14)) { viewController in
300+
if searchViewModel.searchController == nil {
301+
viewController.navigationItem.hidesSearchBarWhenScrolling = true
302+
viewController.navigationItem.searchController = {
303+
let searchController = UISearchController(searchResultsController: nil)
304+
searchController.searchResultsUpdater = searchViewModel
305+
searchController.obscuresBackgroundDuringPresentation = false
306+
searchController.hidesNavigationBarDuringPresentation = true
307+
searchController.searchBar.placeholder = NSLocalizedString("Search…", comment: "")
308+
return searchController
309+
}()
310+
searchViewModel.searchController = viewController.navigationItem.searchController
311+
}
312+
}
272313
}
273314
}
274315
.sheet(item: $selectorOpenedURL) { url in
@@ -342,3 +383,13 @@ struct AppListView: View {
342383
extension URL: Identifiable {
343384
public var id: String { absoluteString }
344385
}
386+
387+
final class AppListSearchViewModel: NSObject, UISearchResultsUpdating, ObservableObject {
388+
@Published var searchKeyword: String = ""
389+
390+
weak var searchController: UISearchController?
391+
392+
func updateSearchResults(for searchController: UISearchController) {
393+
searchKeyword = searchController.searchBar.text ?? ""
394+
}
395+
}

TrollFools/EjectListView.swift

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77

88
import CocoaLumberjackSwift
99
import SwiftUI
10+
import SwiftUIIntrospect
1011

1112
struct EjectListView: View {
13+
14+
@StateObject var searchViewModel = AppListSearchViewModel()
1215
@StateObject var ejectList: EjectListModel
1316

1417
init(_ app: App) {
@@ -111,14 +114,14 @@ struct EjectListView: View {
111114
)
112115
} label: { }
113116
})
114-
.onViewWillAppear { viewController in
115-
viewControllerHost.viewController = viewController
116-
}
117117
}
118118

119119
var body: some View {
120120
if #available(iOS 15, *) {
121121
ejectListView
122+
.onViewWillAppear { viewController in
123+
viewControllerHost.viewController = viewController
124+
}
122125
.refreshable {
123126
withAnimation {
124127
ejectList.reload()
@@ -134,6 +137,38 @@ struct EjectListView: View {
134137
} else {
135138
// Fallback on earlier versions
136139
ejectListView
140+
.onReceive(searchViewModel.$searchKeyword) {
141+
ejectList.filter.searchKeyword = $0
142+
}
143+
.introspect(.list, on: .iOS(.v14)) { tableView in
144+
if tableView.refreshControl == nil {
145+
tableView.refreshControl = {
146+
let refreshControl = UIRefreshControl()
147+
refreshControl.addAction(UIAction { action in
148+
ejectList.reload()
149+
if let control = action.sender as? UIRefreshControl {
150+
control.endRefreshing()
151+
}
152+
}, for: .valueChanged)
153+
return refreshControl
154+
}()
155+
}
156+
}
157+
.introspect(.viewController, on: .iOS(.v14)) { viewController in
158+
viewControllerHost.viewController = viewController
159+
if searchViewModel.searchController == nil {
160+
viewController.navigationItem.hidesSearchBarWhenScrolling = true
161+
viewController.navigationItem.searchController = {
162+
let searchController = UISearchController(searchResultsController: nil)
163+
searchController.searchResultsUpdater = searchViewModel
164+
searchController.obscuresBackgroundDuringPresentation = false
165+
searchController.hidesNavigationBarDuringPresentation = true
166+
searchController.searchBar.placeholder = NSLocalizedString("Search…", comment: "")
167+
return searchController
168+
}()
169+
searchViewModel.searchController = viewController.navigationItem.searchController
170+
}
171+
}
137172
}
138173
}
139174

@@ -200,3 +235,13 @@ struct EjectListView: View {
200235
}
201236
}
202237
}
238+
239+
final class EjectListSearchViewModel: NSObject, UISearchResultsUpdating, ObservableObject {
240+
@Published var searchKeyword: String = ""
241+
242+
weak var searchController: UISearchController?
243+
244+
func updateSearchResults(for searchController: UISearchController) {
245+
searchKeyword = searchController.searchBar.text ?? ""
246+
}
247+
}

0 commit comments

Comments
 (0)