From 8d5eb74fbad17a2b614d413f7eede06c89c4338f Mon Sep 17 00:00:00 2001 From: nimbold <11913706+nimbold@users.noreply.github.com> Date: Mon, 8 Jun 2026 00:17:32 +0330 Subject: [PATCH] fix: restore Download Properties routing and gestures - Fix: Revert WindowGroup to expect UUID and update ALL openWindow calls to explicitly use id: 'download-properties' to prevent routing poisoning - Fix: Wrap the File Name cell in doubleClickableCell using .simultaneousGesture so double clicks trigger the action without eating single click row selection --- Scripts/fix_table_final.py | 86 ++++++++++++++++++++++++++++ Sources/Firelink/DownloadTable.swift | 21 ++++--- Sources/Firelink/FirelinkApp.swift | 4 +- 3 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 Scripts/fix_table_final.py diff --git a/Scripts/fix_table_final.py b/Scripts/fix_table_final.py new file mode 100644 index 0000000..7007377 --- /dev/null +++ b/Scripts/fix_table_final.py @@ -0,0 +1,86 @@ +with open("Sources/Firelink/FirelinkApp.swift", "r") as f: + app_content = f.read() + +app_content = app_content.replace( + 'WindowGroup("Download Properties", id: "download-properties", for: String.self) { $downloadIDString in\n if let idString = downloadIDString, let downloadID = UUID(uuidString: idString) {', + 'WindowGroup("Download Properties", id: "download-properties", for: UUID.self) { $downloadID in\n if let downloadID {' +) + +with open("Sources/Firelink/FirelinkApp.swift", "w") as f: + f.write(app_content) + +with open("Sources/Firelink/DownloadTable.swift", "r") as f: + table_content = f.read() + +# Fix openWindow in performPrimaryAction +table_content = table_content.replace( + 'openWindow(id: "download-properties", value: item.id.uuidString)', + 'openWindow(id: "download-properties", value: item.id)' +) + +# Fix openWindow in rowContextMenu +table_content = table_content.replace( + 'openWindow(value: target.id)', + 'openWindow(id: "download-properties", value: target.id)' +) + +# Remove simultaneousGesture from Table +import re +table_content = re.sub( + r'\s*\.simultaneousGesture\(TapGesture\(count: 2\)\.onEnded \{\s*if let id = selection\.first, let item = controller\.downloads\.first\(where: \{ \$0\.id == id \}\) \{\s*performPrimaryAction\(for: item\)\s*\}\s*\}\)', + '', + table_content +) + +# Replace the File Name TableColumn to use doubleClickableCell +old_column = ''' TableColumn("File Name", value: \\.fileName) { item in + HStack(alignment: .top, spacing: 8) { + Image(systemName: item.category.symbolName) + .font(.title3) + .foregroundStyle(categoryColor(for: item.category)) + .frame(width: 22) + Text(item.fileName) + .font(.headline) + .lineLimit(1) + .truncationMode(.tail) + .allowsHitTesting(false) + .draggable(item.id.uuidString) + } + }''' + +new_column = ''' TableColumn("File Name", value: \\.fileName) { item in + doubleClickableCell(for: item) { + HStack(alignment: .top, spacing: 8) { + Image(systemName: item.category.symbolName) + .font(.title3) + .foregroundStyle(categoryColor(for: item.category)) + .frame(width: 22) + Text(item.fileName) + .font(.headline) + .lineLimit(1) + .truncationMode(.tail) + .allowsHitTesting(false) + } + .draggable(item.id.uuidString) + } + }''' + +table_content = table_content.replace(old_column, new_column) + +# Add doubleClickableCell helper +helper = ''' private func performPrimaryAction(for item: DownloadItem) {''' + +helper_new = ''' private func doubleClickableCell(for item: DownloadItem, @ViewBuilder content: () -> Content) -> some View { + content() + .contentShape(Rectangle()) + .simultaneousGesture(TapGesture(count: 2).onEnded { + performPrimaryAction(for: item) + }) + } + + private func performPrimaryAction(for item: DownloadItem) {''' + +table_content = table_content.replace(helper, helper_new) + +with open("Sources/Firelink/DownloadTable.swift", "w") as f: + f.write(table_content) diff --git a/Sources/Firelink/DownloadTable.swift b/Sources/Firelink/DownloadTable.swift index 42f08ef..476ee7d 100644 --- a/Sources/Firelink/DownloadTable.swift +++ b/Sources/Firelink/DownloadTable.swift @@ -37,7 +37,8 @@ struct DownloadTable: View { Table(sortedItems, selection: $selection, sortOrder: $sortOrder) { TableColumn("File Name", value: \.fileName) { item in - HStack(alignment: .top, spacing: 8) { + doubleClickableCell(for: item) { + HStack(alignment: .top, spacing: 8) { Image(systemName: item.category.symbolName) .font(.title3) .foregroundStyle(categoryColor(for: item.category)) @@ -47,6 +48,7 @@ struct DownloadTable: View { .lineLimit(1) .truncationMode(.tail) .allowsHitTesting(false) + } .draggable(item.id.uuidString) } } @@ -103,11 +105,6 @@ struct DownloadTable: View { } .width(min: 100, ideal: 155) } - .simultaneousGesture(TapGesture(count: 2).onEnded { - if let id = selection.first, let item = controller.downloads.first(where: { $0.id == id }) { - performPrimaryAction(for: item) - } - }) .environment(\.defaultMinListRowHeight, settings.listRowDensity.minRowHeight) .contextMenu(forSelectionType: DownloadItem.ID.self) { itemIDs in rowContextMenu(for: itemIDs) @@ -161,11 +158,19 @@ struct DownloadTable: View { } } + private func doubleClickableCell(for item: DownloadItem, @ViewBuilder content: () -> Content) -> some View { + content() + .contentShape(Rectangle()) + .simultaneousGesture(TapGesture(count: 2).onEnded { + performPrimaryAction(for: item) + }) + } + private func performPrimaryAction(for item: DownloadItem) { if item.status == .completed { openFile(item) } else { - openWindow(id: "download-properties", value: item.id.uuidString) + openWindow(id: "download-properties", value: item.id) } } @@ -266,7 +271,7 @@ struct DownloadTable: View { Button { for target in targetItems { - openWindow(value: target.id) + openWindow(id: "download-properties", value: target.id) } } label: { Label(targetItems.count > 1 ? "Properties (\(targetItems.count))" : "Properties", systemImage: "info.circle") diff --git a/Sources/Firelink/FirelinkApp.swift b/Sources/Firelink/FirelinkApp.swift index 8e919d3..a9b21f9 100644 --- a/Sources/Firelink/FirelinkApp.swift +++ b/Sources/Firelink/FirelinkApp.swift @@ -115,8 +115,8 @@ struct FirelinkApp: App { } .windowResizability(.contentSize) - WindowGroup("Download Properties", id: "download-properties", for: String.self) { $downloadIDString in - if let idString = downloadIDString, let downloadID = UUID(uuidString: idString) { + WindowGroup("Download Properties", id: "download-properties", for: UUID.self) { $downloadID in + if let downloadID { DownloadPropertiesWindow(downloadID: downloadID) .environmentObject(controller) .environmentObject(settings)