Add per-app script mapping (#224)

* Add per-app script mapping

* Add PiP toggle under advanced options

* Fix PiP visibility condition
This commit is contained in:
Stephen B 2025-07-12 23:31:14 -04:00 • committed by GitHub
parent aaacd75432
commit 1441520ba0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 72 additions and 27 deletions

View file

@ -14,36 +14,53 @@ struct ScriptListView: View {
@State private var newFileName = ""
@State private var showImporter = false
@AppStorage("DefaultScriptName") private var defaultScriptName = "attachDetach.js"
var onSelectScript: ((URL) -> Void)? = nil
var body: some View {
NavigationStack {
List {
Section {
ForEach(scripts, id: \.self) { script in
NavigationLink {
ScriptEditorView(scriptURL: script)
} label: {
HStack {
Text(script.lastPathComponent)
.font(.headline)
if defaultScriptName == script.lastPathComponent {
Spacer()
Image(systemName: "star.fill")
if let onSelectScript {
Button {
onSelectScript(script)
} label: {
HStack {
Text(script.lastPathComponent)
.font(.headline)
if defaultScriptName == script.lastPathComponent {
Spacer()
Image(systemName: "star.fill")
}
}
}
}
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
deleteScript(script)
} else {
NavigationLink {
ScriptEditorView(scriptURL: script)
} label: {
Label("Delete", systemImage: "trash")
HStack {
Text(script.lastPathComponent)
.font(.headline)
if defaultScriptName == script.lastPathComponent {
Spacer()
Image(systemName: "star.fill")
}
}
}
Button {
saveDefaultScript(script)
} label: {
Label("Set Default", systemImage: "star")
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
deleteScript(script)
} label: {
Label("Delete", systemImage: "trash")
}
Button {
saveDefaultScript(script)
} label: {
Label("Set Default", systemImage: "star")
}
.tint(.blue)
}
.tint(.blue)
}
}
} footer: {

View file

@ -40,8 +40,9 @@ struct HomeView: View {
@State private var pendingBundleIdToEnableJIT : String? = nil
@State private var pendingPIDToEnableJIT : Int? = nil
@AppStorage("enableAdvancedOptions") private var enableAdvancedOptions = false
@AppStorage("useDefaultScript") private var useDefaultScript = false
@AppStorage("enablePiP") private var enablePiP = true
@State var scriptViewShow = false
@AppStorage("DefaultScriptName") var selectedScript = "attachDetach.js"
@State var jsModel: RunJSViewModel?
@ -304,7 +305,7 @@ struct HomeView: View {
}
}
.pipify(isPresented: Binding(
get: { useDefaultScript && isProcessing },
get: { enablePiP && isProcessing },
set: { newValue in isProcessing = newValue }
)) {
RunJSViewPiP(model: $jsModel)
@ -355,8 +356,8 @@ struct HomeView: View {
}
)
.onOpenURL { url in
print(url.path())
if url.host() != "enable-jit" {
print(url.path)
if url.host != "enable-jit" {
return
}
@ -409,11 +410,12 @@ struct HomeView: View {
// but we'll keep it empty to avoid breaking anything
}
private func getJsCallback() -> DebugAppCallback? {
private func getJsCallback(for scriptName: String? = nil) -> DebugAppCallback? {
let name = scriptName ?? selectedScript
let selectedScriptURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
.appendingPathComponent("scripts").appendingPathComponent(selectedScript)
.appendingPathComponent("scripts").appendingPathComponent(name)
if !FileManager.default.fileExists(atPath: selectedScriptURL.path()) {
if !FileManager.default.fileExists(atPath: selectedScriptURL.path) {
return nil
}
@ -438,13 +440,16 @@ struct HomeView: View {
LogManager.shared.addInfoLog("Starting Debug for \(bundleID)")
DispatchQueue.global(qos: .background).async {
let mapping = UserDefaults.standard.dictionary(forKey: "BundleScriptMap") as? [String: String]
let mappedScript = mapping?[bundleID]
let callback = mappedScript != nil ? getJsCallback(for: mappedScript) : (useDefaultScript ? getJsCallback() : nil)
let success = JITEnableContext.shared.debugApp(withBundleID: bundleID, logger: { message in
if let message = message {
// Log messages from the JIT process
LogManager.shared.addInfoLog(message)
}
}, jsCallback: useDefaultScript ? getJsCallback() : nil)
}, jsCallback: callback)
DispatchQueue.main.async {
LogManager.shared.addInfoLog("Debug process completed for \(bundleID)")

View file

@ -141,6 +141,7 @@ struct AppButton: View {
let sharedDefaults: UserDefaults
@Environment(\.colorScheme) private var colorScheme
@State private var showScriptPicker = false
var body: some View {
Button(action: selectApp) {
@ -162,6 +163,17 @@ struct AppButton: View {
Button { UIPasteboard.general.string = bundleID } label: {
Label("Copy Bundle ID", systemImage: "doc.on.doc")
}
Button {
showScriptPicker = true
} label: {
Label("Assign Script", systemImage: "chevron.left.slash.chevron.right")
}
}
.sheet(isPresented: $showScriptPicker) {
ScriptListView { url in
assignScript(url)
showScriptPicker = false
}
}
}
@ -223,6 +235,12 @@ struct AppButton: View {
WidgetCenter.shared.reloadAllTimelines()
}
private func assignScript(_ url: URL) {
var mapping = UserDefaults.standard.dictionary(forKey: "BundleScriptMap") as? [String: String] ?? [:]
mapping[bundleID] = url.lastPathComponent
UserDefaults.standard.set(mapping, forKey: "BundleScriptMap")
}
private func loadAppIcon(for bundleID: String) {
guard loadAppIconsOnJIT else { return }

View file

@ -13,6 +13,7 @@ struct SettingsView: View {
@AppStorage("selectedAppIcon") private var selectedAppIcon: String = "AppIcon"
@AppStorage("useDefaultScript") private var useDefaultScript = false
@AppStorage("enableAdvancedOptions") private var enableAdvancedOptions = false
@AppStorage("enablePiP") private var enablePiP = true
@State private var isShowingPairingFilePicker = false
@Environment(\.colorScheme) private var colorScheme
@ -280,6 +281,9 @@ struct SettingsView: View {
Toggle("Run Default Script After Connecting", isOn: $useDefaultScript)
.foregroundColor(.primary)
.padding(.vertical, 6)
Toggle("Picture in Picture", isOn: $enablePiP)
.foregroundColor(.primary)
.padding(.vertical, 6)
}
}
.padding(.vertical, 20)
@ -287,6 +291,7 @@ struct SettingsView: View {
.onChange(of: enableAdvancedOptions) { _, newValue in
if !newValue {
useDefaultScript = false
enablePiP = false
}
}
}