From 3aa90762cced2b23909ff993c4bf133719752f03 Mon Sep 17 00:00:00 2001 From: Till JS Date: Mon, 25 May 2026 14:04:02 +0200 Subject: [PATCH] ManaWebShell: Retry-Button in der Fehler-Leiste MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ein WebView-Lade-Fehler war bisher eine Sackgasse — Meldung sichtbar, aber kein Weg zum Neuladen. Jetzt: "Erneut laden"-Button erhöht einen internen reloadNudge, der in effectiveTarget.reloadToken einfließt → updateUIView/updateNSView lädt die URL neu. WebTargetTests sichern die Token-Ungleichheit ab (4/4 grün via swift test). Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 7 ++++ Sources/ManaWebShell/WebShellView.swift | 21 +++++++++-- Tests/ManaWebShellTests/WebTargetTests.swift | 38 ++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 Tests/ManaWebShellTests/WebTargetTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 8edfcf3..87bfc2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ Alle Änderungen werden hier dokumentiert. Format orientiert an ## [Unreleased] +### Geändert + +- `ManaWebShell`: Die Fehler-Leiste in `WebShellView` hat jetzt einen + „Erneut laden"-Button. Bisher war ein Lade-Fehler eine Sackgasse — + der User sah die Meldung, konnte die Seite aber nicht neu laden. + Intern via `reloadNudge` → `effectiveTarget.reloadToken`. + ## [0.8.0] — 2026-05-22 Minor — **neues Library-Product `ManaLLMUI`**. Drop-in-Settings-UI diff --git a/Sources/ManaWebShell/WebShellView.swift b/Sources/ManaWebShell/WebShellView.swift index 98cc341..fbd5997 100644 --- a/Sources/ManaWebShell/WebShellView.swift +++ b/Sources/ManaWebShell/WebShellView.swift @@ -24,8 +24,16 @@ public struct WebShellView: View { let config: WebShellConfig @State private var navState = WebNavState() + @State private var reloadNudge = 0 @Environment(\.openURL) private var openURL + /// `target` plus interner Reload-Zähler. Der „Erneut laden"-Button in + /// der Fehler-Leiste erhöht `reloadNudge` → neuer `reloadToken` → + /// `updateUIView`/`updateNSView` lädt die URL neu. + private var effectiveTarget: WebTarget { + WebTarget(url: target.url, reloadToken: target.reloadToken + reloadNudge) + } + public init(target: WebTarget, config: WebShellConfig) { self.target = target self.config = config @@ -41,7 +49,7 @@ public struct WebShellView: View { } #if canImport(UIKit) WebViewRepresentable( - target: target, + target: effectiveTarget, navState: navState, openURL: openURL, config: config @@ -50,7 +58,7 @@ public struct WebShellView: View { .background(config.backgroundColor) #elseif canImport(AppKit) MacWebViewRepresentable( - target: target, + target: effectiveTarget, navState: navState, openURL: openURL, config: config @@ -74,6 +82,15 @@ public struct WebShellView: View { .lineLimit(2) .foregroundStyle(config.errorForegroundColor) Spacer() + Button { + navState.lastError = nil + reloadNudge += 1 + } label: { + Text("Erneut laden") + .font(.caption.weight(.semibold)) + .foregroundStyle(config.errorForegroundColor) + } + .buttonStyle(.plain) } .padding(.horizontal, 12) .padding(.vertical, 8) diff --git a/Tests/ManaWebShellTests/WebTargetTests.swift b/Tests/ManaWebShellTests/WebTargetTests.swift new file mode 100644 index 0000000..291b999 --- /dev/null +++ b/Tests/ManaWebShellTests/WebTargetTests.swift @@ -0,0 +1,38 @@ +import Foundation +import Testing +@testable import ManaWebShell + +/// `WebShellView.updateUIView`/`updateNSView` lädt nur neu, wenn +/// `lastTarget != target`. Der „Erneut laden"-Button erhöht den +/// `reloadToken` — diese Tests sichern, dass das tatsächlich +/// Ungleichheit erzeugt (sonst bliebe der Retry wirkungslos). +@Suite("WebTarget — Reload-Token-Gleichheit") +struct WebTargetTests { + private let url = URL(string: "https://seepuls.com/heute")! + + @Test("Gleiche URL + gleicher Token → gleich") + func equalWhenSameTokenAndURL() { + let a = WebTarget(url: url, reloadToken: 3) + let b = WebTarget(url: url, reloadToken: 3) + #expect(a == b) + } + + @Test("Erhöhter Token → ungleich (treibt den Reload)") + func differsWhenTokenIncremented() { + let before = WebTarget(url: url, reloadToken: 1) + let after = WebTarget(url: url, reloadToken: before.reloadToken + 1) + #expect(before != after) + } + + @Test("Andere URL → ungleich") + func differsWhenURLDiffers() { + let a = WebTarget(url: url, reloadToken: 0) + let b = WebTarget(url: URL(string: "https://seepuls.com/alle")!, reloadToken: 0) + #expect(a != b) + } + + @Test("Default-Token ist 0") + func defaultTokenIsZero() { + #expect(WebTarget(url: url).reloadToken == 0) + } +}