Fix browser devtools X-close persistence
This commit is contained in:
parent
66f8f8b022
commit
fabcb06891
2 changed files with 62 additions and 0 deletions
|
|
@ -2152,6 +2152,9 @@ final class BrowserPanel: Panel, ObservableObject {
|
|||
private var pendingDeveloperToolsTransitionTargetVisible: Bool?
|
||||
private var developerToolsTransitionSettleWorkItem: DispatchWorkItem?
|
||||
private let developerToolsTransitionSettleDelay: TimeInterval = 0.15
|
||||
private let developerToolsAttachedManualCloseDetectionDelay: TimeInterval = 0.35
|
||||
private var developerToolsLastAttachedHostAt: Date?
|
||||
private var developerToolsLastKnownVisibleAt: Date?
|
||||
private var detachedDeveloperToolsWindowCloseObserver: NSObjectProtocol?
|
||||
private var preferredAttachedDeveloperToolsWidth: CGFloat?
|
||||
private var preferredAttachedDeveloperToolsWidthFraction: CGFloat?
|
||||
|
|
@ -3971,6 +3974,7 @@ extension BrowserPanel {
|
|||
let isVisibleSelector = NSSelectorFromString("isVisible")
|
||||
if inspector.cmuxCallBool(selector: isVisibleSelector) ?? false {
|
||||
developerToolsDetachedOpenGraceDeadline = nil
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -3980,6 +3984,9 @@ extension BrowserPanel {
|
|||
guard inspector.responds(to: showSelector) else { return false }
|
||||
inspector.cmuxCallVoid(selector: showSelector)
|
||||
let visibleAfterShow = inspector.cmuxCallBool(selector: isVisibleSelector) ?? false
|
||||
if visibleAfterShow {
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
}
|
||||
if preferredDeveloperToolsPresentation == .detached {
|
||||
developerToolsDetachedOpenGraceDeadline = visibleAfterShow
|
||||
? nil
|
||||
|
|
@ -4196,6 +4203,7 @@ extension BrowserPanel {
|
|||
developerToolsDetachedOpenGraceDeadline = nil
|
||||
syncDeveloperToolsPresentationPreferenceFromUI()
|
||||
preferredDeveloperToolsVisible = true
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
cancelDeveloperToolsRestoreRetry()
|
||||
return
|
||||
}
|
||||
|
|
@ -4203,9 +4211,47 @@ extension BrowserPanel {
|
|||
return
|
||||
}
|
||||
preferredDeveloperToolsVisible = false
|
||||
developerToolsLastKnownVisibleAt = nil
|
||||
cancelDeveloperToolsRestoreRetry()
|
||||
}
|
||||
|
||||
func noteDeveloperToolsHostAttached() {
|
||||
developerToolsLastAttachedHostAt = Date()
|
||||
developerToolsLastKnownVisibleAt = isDeveloperToolsVisible() ? Date() : nil
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func consumeAttachedDeveloperToolsManualCloseIfNeeded(inspector: NSObject? = nil) -> Bool {
|
||||
guard preferredDeveloperToolsVisible else { return false }
|
||||
guard preferredDeveloperToolsPresentation != .detached else { return false }
|
||||
guard !isDeveloperToolsTransitionInFlight else { return false }
|
||||
guard webView.superview != nil, webView.window != nil else { return false }
|
||||
guard let developerToolsLastAttachedHostAt else { return false }
|
||||
guard Date().timeIntervalSince(developerToolsLastAttachedHostAt) >= developerToolsAttachedManualCloseDetectionDelay else {
|
||||
return false
|
||||
}
|
||||
guard developerToolsLastKnownVisibleAt != nil else { return false }
|
||||
guard let inspector = inspector ?? webView.cmuxInspectorObject() else { return false }
|
||||
guard let visible = inspector.cmuxCallBool(selector: NSSelectorFromString("isVisible")) else { return false }
|
||||
guard !visible else {
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
return false
|
||||
}
|
||||
|
||||
preferredDeveloperToolsVisible = false
|
||||
developerToolsDetachedOpenGraceDeadline = nil
|
||||
developerToolsLastKnownVisibleAt = nil
|
||||
forceDeveloperToolsRefreshOnNextAttach = false
|
||||
cancelDeveloperToolsRestoreRetry()
|
||||
#if DEBUG
|
||||
dlog(
|
||||
"browser.devtools attachedClose.consume panel=\(id.uuidString.prefix(5)) " +
|
||||
"\(debugDeveloperToolsStateSummary()) \(debugDeveloperToolsGeometrySummary())"
|
||||
)
|
||||
#endif
|
||||
return true
|
||||
}
|
||||
|
||||
/// Called after WKWebView reattaches to keep inspector stable across split/layout churn.
|
||||
func restoreDeveloperToolsAfterAttachIfNeeded() {
|
||||
guard preferredDeveloperToolsVisible else {
|
||||
|
|
@ -4226,6 +4272,7 @@ extension BrowserPanel {
|
|||
if visible {
|
||||
developerToolsDetachedOpenGraceDeadline = nil
|
||||
syncDeveloperToolsPresentationPreferenceFromUI()
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
#if DEBUG
|
||||
if shouldForceRefresh {
|
||||
dlog("browser.devtools refresh.consumeVisible panel=\(id.uuidString.prefix(5)) \(debugDeveloperToolsStateSummary())")
|
||||
|
|
@ -4249,6 +4296,10 @@ extension BrowserPanel {
|
|||
return
|
||||
}
|
||||
|
||||
if consumeAttachedDeveloperToolsManualCloseIfNeeded(inspector: inspector) {
|
||||
return
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if shouldForceRefresh {
|
||||
dlog("browser.devtools refresh.forceShowWhenHidden panel=\(id.uuidString.prefix(5)) \(debugDeveloperToolsStateSummary())")
|
||||
|
|
@ -4264,6 +4315,7 @@ extension BrowserPanel {
|
|||
let visibleAfterShow = inspector.cmuxCallBool(selector: NSSelectorFromString("isVisible")) ?? false
|
||||
if visibleAfterShow {
|
||||
syncDeveloperToolsPresentationPreferenceFromUI()
|
||||
developerToolsLastKnownVisibleAt = Date()
|
||||
cancelDeveloperToolsRestoreRetry()
|
||||
scheduleDetachedDeveloperToolsWindowDismissal()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -513,6 +513,14 @@ struct BrowserPanelView: View {
|
|||
refreshSuggestions()
|
||||
}
|
||||
}
|
||||
.onChange(of: isVisibleInUI) { visibleInUI in
|
||||
guard !visibleInUI else { return }
|
||||
// The attached WebKit inspector close button can hide DevTools without
|
||||
// touching BrowserPanel's persisted intent. Capture the actual inspector
|
||||
// visibility before the surface detaches so switching away and back
|
||||
// does not resurrect a manually closed inspector.
|
||||
panel.syncDeveloperToolsPreferenceFromInspector()
|
||||
}
|
||||
.onChange(of: isFocused) { focused in
|
||||
#if DEBUG
|
||||
logBrowserFocusState(
|
||||
|
|
@ -5689,6 +5697,7 @@ struct WebViewRepresentable: NSViewRepresentable {
|
|||
coordinator.lastPortalHostId = nil
|
||||
coordinator.lastSynchronizedHostGeometryRevision = 0
|
||||
if didAttachWebViewToLocalHost {
|
||||
panel.noteDeveloperToolsHostAttached()
|
||||
panel.restoreDeveloperToolsAfterAttachIfNeeded()
|
||||
webView.needsLayout = true
|
||||
webView.layoutSubtreeIfNeeded()
|
||||
|
|
@ -5702,6 +5711,7 @@ struct WebViewRepresentable: NSViewRepresentable {
|
|||
host.scheduleHostedInspectorDockConfigurationSync(reason: "localInline.update.async")
|
||||
}
|
||||
} else {
|
||||
panel.consumeAttachedDeveloperToolsManualCloseIfNeeded()
|
||||
host.scheduleHostedInspectorDockConfigurationSync(reason: "localInline.update")
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue