From db694543c13bbcc84e3919d90345381a5b8f6639 Mon Sep 17 00:00:00 2001 From: Hermes Date: Wed, 12 Aug 2026 21:36:34 +0000 Subject: [PATCH] Fix diff screen hang/crash: stable DiffLine id + request timeout; bump to 1.5 DiffLine.id was a computed property returning a fresh UUID() on every access. SwiftUI's ForEach requires stable identities; regenerating each read churned the main thread, hanging the diff screen and eventually crashing. Store the UUID once per line. Also add a 30s URLRequest timeout so a hung request can't leave the 'Loading diff...' spinner forever. Bump to 1.5. --- GiteaPR.xcodeproj/project.pbxproj | 8 ++++---- GiteaPR/Detail/DiffView.swift | 5 ++++- GiteaPR/Networking/GiteaClient.swift | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/GiteaPR.xcodeproj/project.pbxproj b/GiteaPR.xcodeproj/project.pbxproj index a56c2bf..5efb1e1 100644 --- a/GiteaPR.xcodeproj/project.pbxproj +++ b/GiteaPR.xcodeproj/project.pbxproj @@ -187,7 +187,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "GiteaPR"; @@ -197,7 +197,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = com.bueso.giteapr; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -211,7 +211,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = "GiteaPR"; @@ -221,7 +221,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.5; PRODUCT_BUNDLE_IDENTIFIER = com.bueso.giteapr; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/GiteaPR/Detail/DiffView.swift b/GiteaPR/Detail/DiffView.swift index 27977cc..e31af1d 100644 --- a/GiteaPR/Detail/DiffView.swift +++ b/GiteaPR/Detail/DiffView.swift @@ -120,7 +120,10 @@ struct DiffView: View { private enum DiffLineType { case context, addition, deletion, hunk, meta } private struct DiffLine: Identifiable { + // Stable id: a fresh UUID() on EVERY access (computed property) makes + // SwiftUI's ForEach re-identify on every render, churning the main thread + // and eventually crashing. Store it once. + let id: UUID = UUID() let text: String let type: DiffLineType - var id: UUID { UUID() } } diff --git a/GiteaPR/Networking/GiteaClient.swift b/GiteaPR/Networking/GiteaClient.swift index dc76ce3..5463d68 100644 --- a/GiteaPR/Networking/GiteaClient.swift +++ b/GiteaPR/Networking/GiteaClient.swift @@ -71,6 +71,8 @@ struct GiteaClient { req.httpMethod = method req.setValue("token \(token)", forHTTPHeaderField: "Authorization") req.setValue("application/json", forHTTPHeaderField: "Accept") + // Bound every request so a hung call can't leave a spinner forever. + req.timeoutInterval = 30 if let body { req.setValue("application/json", forHTTPHeaderField: "Content-Type") req.httpBody = body