fix: admin/fs: couldn't close file dialog after save button in "base address" dialog
Massimo Melina committed
Apr 14, 2024 at 16:16 UTC
b83384152fa8f1aaa37abd3544aaefe77b50cd5b
1 file changed
+16
-5
shared/dialogs.ts
+16
-5
@@ -3,7 +3,7 @@
3
import { createElement as h, Fragment, FunctionComponent, isValidElement, ReactNode, useEffect, useRef,
4
HTMLAttributes, useState } from 'react'
5
import { proxy, ref, useSnapshot } from 'valtio'
6
-import { domOn, isPrimitive, objSameKeys } from '.'
6
+import { domOn, isPrimitive, objSameKeys, wait } from '.'
7
8
export interface DialogOptions {
9
Content: FunctionComponent<any>,
@@ -26,6 +26,7 @@ export interface DialogOptions {
26
27
const dialogs = proxy<DialogOptions[]>([])
28
const focusBak: (Element | null)[] = []
29
+const { history } = window
30
31
export const dialogsDefaults: Partial<DialogOptions> = {
32
closableProps: { children: 'x', 'aria-label': "Close", },
@@ -66,14 +67,22 @@ function isDescendant(child: Node | null, parent: Node) {
67
let ignorePopState = false
68
function back() {
69
ignorePopState = true
69
- window.history.back()
70
+ history.back()
71
}
72
73
+;(async () => {
74
+ while (history.state.$dialog) { // it happens if the user reloads the browser leaving open dialogs
75
+ history.back()
76
+ await wait(1) // history.state is not changed without this, on chrome123
77
+ }
78
+})()
79
+
80
+
81
export function Dialogs(props: HTMLAttributes<HTMLDivElement>) {
82
useEffect(() => domOn('popstate', () => {
83
if (ignorePopState)
84
return ignorePopState = false
76
- const { $dialog } = window.history.state
85
+ const { $dialog } = history.state
86
if ($dialog && !dialogs.find(x => x.$id === $dialog)) // it happens if the user, after closing a dialog, goes forward in the history
87
return back()
88
closeDialog(undefined, true)
@@ -169,12 +178,14 @@ export function newDialog(options: DialogOptions) {
178
options = objSameKeys(options, x => isValidElement(x) ? ref(x) : x) as typeof options // encapsulate elements as react will try to write, but valtio makes them readonly
179
dialogs.push(options)
180
if (options.closable !== false)
172
- window.history.pushState({ $dialog: $id, ts }, '')
181
+ history.pushState({ $dialog: $id, ts, idx: history.state.idx + 1 }, '')
182
return { close }
183
184
function close(v?:any) {
185
const i = dialogs.findIndex(x => (x as any).$id === $id)
186
if (i < 0) return
187
+ if (history.state.$dialog === $id)
188
+ back()
189
return closeDialogAt(i, v)
190
}
191
}
@@ -187,7 +198,7 @@ export function closeDialog(v?:any, skipHistory=false) {
198
if (d.reserveClosing)
199
continue
200
if (!skipHistory) {
190
- if (window.history.state.$dialog !== d.$id) return
201
+ if (history.state.$dialog !== d.$id) return
202
back()
203
}
204
closeDialogAt(i, v)