Skip to content

Commit eef989d

Browse files
authored
fix: test URL equivalency before replacing iframe location to avoid reloads (#46)
1 parent 9f2c979 commit eef989d

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

src/components/PluginLoader.jsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,33 @@ const handleExternalNavigation = (iframeLoadEvent, pluginHref) => {
9797
}
9898
}
9999

100+
/**
101+
* Equivalent URLs:
102+
* <appRoot>/
103+
* <appRoot>/index.html
104+
* <appRoot>/index.html?redirect=false
105+
*
106+
* newUrl is expected to come from pluginHref,
107+
* and will always have /index.html?redirect=false
108+
*/
109+
const isBaseEquivalent = (currentUrlOrig, newUrlOrig) => {
110+
// Copy before mutating
111+
const [currentUrl, newUrl] = [new URL(currentUrlOrig), new URL(newUrlOrig)]
112+
newUrl.searchParams.sort()
113+
// If redirect is not already false in the search set that
114+
currentUrl.searchParams.set('redirect', 'false')
115+
currentUrl.searchParams.sort()
116+
// If pathname doesn't end in html, add that
117+
if (currentUrl.pathname.endsWith('/')) {
118+
currentUrl.pathname = currentUrl.pathname + 'index.html'
119+
}
120+
121+
const [newBase] = newUrl.href.split('#')
122+
const [currentBase] = currentUrl.href.split('#')
123+
124+
return newBase === currentBase
125+
}
126+
100127
const failedLoadErrorMessage =
101128
'The requested page is not accessible by the DHIS2 global shell, ' +
102129
'and the URL is therefore inaccessible to be printed here. ' +
@@ -179,10 +206,24 @@ export const PluginLoader = ({ appsInfoQuery }) => {
179206
return
180207
}
181208

209+
if (!iframeRef.current) {
210+
return
211+
}
212+
213+
const newUrl = new URL(pluginHref)
214+
const currentLocationUrl = new URL(
215+
iframeRef.current.contentWindow.location
216+
)
182217
// For further updates, replace iframe window location
183-
if (iframeRef.current) {
218+
if (!isBaseEquivalent(currentLocationUrl, newUrl)) {
219+
// If 'base' has changed, replace whole location
184220
iframeRef.current.contentWindow.location.replace(pluginHref)
221+
} else if (newUrl.hash !== currentLocationUrl.hash) {
222+
// If 'base' is functionally equivalent, update just hash,
223+
// if it has changed. Tested and preserves location state
224+
iframeRef.current.contentWindow.location.hash = newUrl.hash
185225
}
226+
// Otherwise, URLs are identical; don't need to update
186227
}, [pluginHref])
187228

188229
if (error) {

0 commit comments

Comments
 (0)