ManaWebShell: Retry-Button in der Fehler-Leiste

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) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-25 14:04:02 +02:00
parent ad9dc1abba
commit 3aa90762cc
3 changed files with 64 additions and 2 deletions

View file

@ -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

View file

@ -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)

View file

@ -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)
}
}