Skip to content

Commit 538eda8

Browse files
committed
feat: add settings
Signed-off-by: 82Flex <[email protected]>
1 parent 5a23ef7 commit 538eda8

File tree

9 files changed

+141
-38
lines changed

9 files changed

+141
-38
lines changed

TrollFools.xcodeproj/project.pbxproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
CC1549022C4B62E300A4173E /* cp-15 in Resources */ = {isa = PBXBuildFile; fileRef = CC1549012C4B62E300A4173E /* cp-15 */; };
2525
CC15490C2C4B79D800A4173E /* optool in Resources */ = {isa = PBXBuildFile; fileRef = CC15490B2C4B79D800A4173E /* optool */; };
2626
CC15490E2C4B80AF00A4173E /* EjectListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC15490D2C4B80AF00A4173E /* EjectListView.swift */; };
27+
CC19E4BB2C561D7300E0F1B5 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC19E4BA2C561D7300E0F1B5 /* SettingsView.swift */; };
2728
CC5E54BE2C4E12F900FDE4A8 /* install_name_tool in Resources */ = {isa = PBXBuildFile; fileRef = CC5E54BC2C4E12F900FDE4A8 /* install_name_tool */; };
2829
CC5E54BF2C4E131000FDE4A8 /* libxar.1.dylib in Resources */ = {isa = PBXBuildFile; fileRef = CC5E54BB2C4E12F900FDE4A8 /* libxar.1.dylib */; };
2930
CC61A87C2C4A677B003BD9A0 /* CydiaSubstrate.framework.zip in Resources */ = {isa = PBXBuildFile; fileRef = CC61A87B2C4A677B003BD9A0 /* CydiaSubstrate.framework.zip */; };
@@ -64,6 +65,7 @@
6465
CC1549012C4B62E300A4173E /* cp-15 */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = "cp-15"; sourceTree = "<group>"; };
6566
CC15490B2C4B79D800A4173E /* optool */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = optool; sourceTree = "<group>"; };
6667
CC15490D2C4B80AF00A4173E /* EjectListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EjectListView.swift; sourceTree = "<group>"; };
68+
CC19E4BA2C561D7300E0F1B5 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
6769
CC5E54BB2C4E12F900FDE4A8 /* libxar.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libxar.1.dylib; sourceTree = "<group>"; };
6870
CC5E54BC2C4E12F900FDE4A8 /* install_name_tool */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = install_name_tool; sourceTree = "<group>"; };
6971
CC61A87B2C4A677B003BD9A0 /* CydiaSubstrate.framework.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = CydiaSubstrate.framework.zip; sourceTree = "<group>"; };
@@ -168,6 +170,7 @@
168170
CCF470592C4A4649008D8197 /* TrollFoolsApp.swift */,
169171
CCF4706D2C4A4BAB008D8197 /* AppListView.swift */,
170172
CCB6A1182C4A58C7000D75B0 /* OptionView.swift */,
173+
CC19E4BA2C561D7300E0F1B5 /* SettingsView.swift */,
171174
CCB6A11A2C4A6066000D75B0 /* InjectView.swift */,
172175
CC15490D2C4B80AF00A4173E /* EjectListView.swift */,
173176
CC1548D22C4A743200A4173E /* SuccessView.swift */,
@@ -295,6 +298,7 @@
295298
CC1548DB2C4A7C7000A4173E /* Execute.swift in Sources */,
296299
CCF5A0A42C4D45160097D48D /* AuxiliaryExecute.swift in Sources */,
297300
CCF4705A2C4A4649008D8197 /* TrollFoolsApp.swift in Sources */,
301+
CC19E4BB2C561D7300E0F1B5 /* SettingsView.swift in Sources */,
298302
CC1548D72C4A768700A4173E /* Injector.swift in Sources */,
299303
CCB6A1192C4A58C7000D75B0 /* OptionView.swift in Sources */,
300304
CCF5A0A22C4D417F0097D48D /* main.swift in Sources */,
@@ -467,7 +471,7 @@
467471
"$(inherited)",
468472
"$(PROJECT_DIR)/TrollFools",
469473
);
470-
MARKETING_VERSION = 2.4;
474+
MARKETING_VERSION = 2.5;
471475
PRODUCT_BUNDLE_IDENTIFIER = wiki.qaq.TrollFools;
472476
PRODUCT_NAME = "$(TARGET_NAME)";
473477
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -509,7 +513,7 @@
509513
"$(inherited)",
510514
"$(PROJECT_DIR)/TrollFools",
511515
);
512-
MARKETING_VERSION = 2.4;
516+
MARKETING_VERSION = 2.5;
513517
PRODUCT_BUNDLE_IDENTIFIER = wiki.qaq.TrollFools;
514518
PRODUCT_NAME = "$(TARGET_NAME)";
515519
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

TrollFools/AppListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ struct AppListCell: View {
277277
if app.isDetached {
278278
Button {
279279
do {
280-
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
280+
let injector = try Injector(app.url, appID: app.id, teamID: app.teamID)
281281
try injector.setDetached(false)
282282
withAnimation {
283283
app.reload()
@@ -290,7 +290,7 @@ struct AppListCell: View {
290290
} else {
291291
Button {
292292
do {
293-
let injector = try Injector(bundleURL: app.url, teamID: app.teamID)
293+
let injector = try Injector(app.url, appID: app.id, teamID: app.teamID)
294294
try injector.setDetached(true)
295295
withAnimation {
296296
app.reload()

TrollFools/EjectListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ struct EjectListView: View {
250250
do {
251251
let plugInsToRemove = offsets.map { vm.filteredPlugIns[$0] }
252252
let plugInURLsToRemove = plugInsToRemove.map { $0.url }
253-
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)
253+
let injector = try Injector(vm.app.url, appID: vm.app.id, teamID: vm.app.teamID)
254254
try injector.eject(plugInURLsToRemove)
255255

256256
vm.app.reload()
@@ -265,7 +265,7 @@ struct EjectListView: View {
265265

266266
func deleteAll() {
267267
do {
268-
let injector = try Injector(bundleURL: vm.app.url, teamID: vm.app.teamID)
268+
let injector = try Injector(vm.app.url, appID: vm.app.id, teamID: vm.app.teamID)
269269

270270
let view = viewControllerHost.viewController?
271271
.navigationController?.view

TrollFools/InjectView.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ struct InjectView: View {
6363

6464
func inject() -> Result<Void, Error> {
6565
do {
66-
let injector = try Injector(
67-
bundleURL: app.url,
68-
teamID: app.teamID
69-
)
66+
let injector = try Injector(app.url, appID: app.id, teamID: app.teamID)
7067
try injector.inject(urlList)
7168
return .success(())
7269
} catch {

TrollFools/Injector.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import CocoaLumberjackSwift
99
import Foundation
1010
import MachOKit
11+
import SwiftUI
1112
import ZIPFoundation
1213

1314
final class Injector {
@@ -104,6 +105,9 @@ final class Injector {
104105
private let tempURL: URL
105106
private var teamID: String
106107

108+
@AppStorage var useWeakReference: Bool
109+
@AppStorage var preferMainExecutable: Bool
110+
107111
private lazy var infoPlistURL: URL = bundleURL.appendingPathComponent("Info.plist")
108112
private lazy var mainExecutableURL: URL = {
109113
let infoPlist = NSDictionary(contentsOf: infoPlistURL)!
@@ -125,7 +129,7 @@ final class Injector {
125129

126130
private init() { fatalError("Not implemented") }
127131

128-
init(bundleURL: URL, teamID: String) throws {
132+
init(_ bundleURL: URL, appID: String, teamID: String) throws {
129133
self.bundleURL = bundleURL
130134
self.teamID = teamID
131135
self.tempURL = try FileManager.default.url(
@@ -134,6 +138,8 @@ final class Injector {
134138
appropriateFor: URL(fileURLWithPath: NSHomeDirectory()),
135139
create: true
136140
)
141+
_useWeakReference = AppStorage(wrappedValue: true, "UseWeakReference-\(appID)")
142+
_preferMainExecutable = AppStorage(wrappedValue: false, "PreferMainExecutable-\(appID)")
137143
try updateTeamIdentifier(bundleURL)
138144
}
139145

@@ -219,10 +225,18 @@ final class Injector {
219225
}
220226
}
221227

222-
return executableURLs
228+
var fwkURLs = executableURLs
223229
.intersection(initialDylibs)
224230
.filter { isMachOURL($0) }
225-
.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }) + [target]
231+
.sorted(by: { $0.lastPathComponent < $1.lastPathComponent })
232+
233+
if preferMainExecutable {
234+
fwkURLs.insert(target, at: 0)
235+
} else {
236+
fwkURLs.append(target)
237+
}
238+
239+
return fwkURLs
226240
}
227241

228242
private func copyTempInjectURLs(_ injectURLs: [URL]) throws -> [URL] {
@@ -568,7 +582,7 @@ final class Injector {
568582
}
569583

570584
try _insertLoadCommandRpath(target, name: "@executable_path/Frameworks")
571-
try _insertLoadCommandDylib(target, name: name, isWeak: true)
585+
try _insertLoadCommandDylib(target, name: name, isWeak: useWeakReference)
572586
try applyTargetFixes(target, name: name)
573587
}
574588

TrollFools/OptionView.swift

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,49 +59,61 @@ struct OptionView: View {
5959
@State var isImporterPresented = false
6060
@State var isImporterSelected = false
6161

62+
@State var isSettingsPresented = false
63+
6264
@State var importerResult: Result<[URL], any Error>?
6365

6466
init(_ app: App) {
6567
self.app = app
6668
}
6769

6870
var body: some View {
69-
HStack {
70-
Spacer()
71+
VStack(spacing: 80) {
72+
HStack {
73+
Spacer()
74+
75+
Button {
76+
isImporterPresented = true
77+
} label: {
78+
OptionCell(option: .attach)
79+
}
80+
.accessibilityLabel(NSLocalizedString("Inject", comment: ""))
81+
82+
Spacer()
83+
84+
NavigationLink {
85+
EjectListView(app)
86+
} label: {
87+
OptionCell(option: .detach)
88+
}
89+
.accessibilityLabel(NSLocalizedString("Eject", comment: ""))
90+
91+
Spacer()
92+
}
7193

94+
Button {
95+
isSettingsPresented = true
96+
} label: {
97+
Label(NSLocalizedString("Advanced Settings", comment: ""),
98+
systemImage: "gear")
99+
}
100+
}
101+
.padding()
102+
.navigationTitle(app.name)
103+
.background(Group {
72104
NavigationLink(isActive: $isImporterSelected) {
73105
if let result = importerResult {
74106
switch result {
75107
case .success(let urls):
76108
InjectView(app: app, urlList: urls
77109
.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }))
78110
case .failure(let message):
79-
FailureView(title: NSLocalizedString("Error", comment: ""),
111+
FailureView(title: NSLocalizedString("Error", comment: ""),
80112
message: message.localizedDescription)
81113
}
82114
}
83115
} label: { }
84-
85-
Button {
86-
isImporterPresented = true
87-
} label: {
88-
OptionCell(option: .attach)
89-
}
90-
.accessibilityLabel(NSLocalizedString("Inject", comment: ""))
91-
92-
Spacer()
93-
94-
NavigationLink {
95-
EjectListView(app)
96-
} label: {
97-
OptionCell(option: .detach)
98-
}
99-
.accessibilityLabel(NSLocalizedString("Eject", comment: ""))
100-
101-
Spacer()
102-
}
103-
.padding()
104-
.navigationTitle(app.name)
116+
})
105117
.fileImporter(
106118
isPresented: $isImporterPresented,
107119
allowedContentTypes: [
@@ -117,5 +129,13 @@ struct OptionView: View {
117129
importerResult = result
118130
isImporterSelected = true
119131
}
132+
.sheet(isPresented: $isSettingsPresented) {
133+
if #available(iOS 16.0, *) {
134+
SettingsView(app)
135+
.presentationDetents([.medium, .large])
136+
} else {
137+
SettingsView(app)
138+
}
139+
}
120140
}
121141
}

TrollFools/SettingsView.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// SettingsView.swift
3+
// TrollFools
4+
//
5+
// Created by Lessica on 2024/7/28.
6+
//
7+
8+
import SwiftUI
9+
10+
struct SettingsView: View {
11+
let app: App
12+
13+
init(_ app: App) {
14+
self.app = app
15+
self._useWeakReference = AppStorage(wrappedValue: true, "UseWeakReference-\(app.id)")
16+
self._preferMainExecutable = AppStorage(wrappedValue: false, "PreferMainExecutable-\(app.id)")
17+
}
18+
19+
@AppStorage var useWeakReference: Bool
20+
@AppStorage var preferMainExecutable: Bool
21+
22+
var body: some View {
23+
NavigationView {
24+
Form {
25+
Section {
26+
Toggle(NSLocalizedString("Use Weak Reference", comment: ""), systemImage: "link", isOn: $useWeakReference)
27+
Toggle(NSLocalizedString("Prefer Main Executable", comment: ""), systemImage: "doc.badge.gearshape", isOn: $preferMainExecutable)
28+
} header: {
29+
Text(NSLocalizedString("Injection", comment: ""))
30+
} footer: {
31+
Text(NSLocalizedString("If you do not know what these options mean, please do not change them.", comment: ""))
32+
}
33+
}
34+
.navigationTitle(NSLocalizedString("Advanced Settings", comment: ""))
35+
.navigationBarTitleDisplayMode(.inline)
36+
}
37+
}
38+
}

TrollFools/en.lproj/Localizable.strings

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
/* No comment provided by engineer. */
88
"A pure TrollStore software channel!" = "A pure TrollStore software channel!";
99

10+
/* No comment provided by engineer. */
11+
"Advanced Settings" = "Advanced Settings";
12+
1013
/* No comment provided by engineer. */
1114
"AE86 TrollStore Channel" = "AE86 TrollStore Channel";
1215

@@ -40,6 +43,9 @@
4043
/* No comment provided by engineer. */
4144
"Failed to parse: %@" = "Failed to parse: %@";
4245

46+
/* No comment provided by engineer. */
47+
"If you do not know what these options mean, please do not change them." = "If you do not know what these options mean, please do not change them.";
48+
4349
/* No comment provided by engineer. */
4450
"Inject" = "Inject";
4551

@@ -52,6 +58,9 @@
5258
/* No comment provided by engineer. */
5359
"Injecting" = "Injecting";
5460

61+
/* No comment provided by engineer. */
62+
"Injection" = "Injection";
63+
5564
/* No comment provided by engineer. */
5665
"Launch" = "Launch";
5766

@@ -85,6 +94,9 @@
8594
/* No comment provided by engineer. */
8695
"Plug-Ins" = "Plug-Ins";
8796

97+
/* No comment provided by engineer. */
98+
"Prefer Main Executable" = "Prefer Main Executable";
99+
88100
/* No comment provided by engineer. */
89101
"Rebuild Icon Cache" = "Rebuild Icon Cache";
90102

@@ -118,6 +130,9 @@
118130
/* No comment provided by engineer. */
119131
"Unlock Version" = "Unlock Version";
120132

133+
/* No comment provided by engineer. */
134+
"Use Weak Reference" = "Use Weak Reference";
135+
121136
/* No comment provided by engineer. */
122137
"User Applications" = "User Applications";
123138

0 commit comments

Comments
 (0)