@@ -27,7 +27,12 @@ import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
2727import AlertCircleIcon from ' vue-material-design-icons/AlertCircle.vue'
2828import NcLoadingIcon from ' @nextcloud/vue/dist/Components/NcLoadingIcon.js'
2929
30- import { APP_API_PROXY_URL_PREFIX , EX_APP_ID } from ' ../constants/AppAPI.js'
30+ import {
31+ APP_API_PROXY_URL_PREFIX ,
32+ APP_API_ROUTER_BASE ,
33+ EX_APP_ID ,
34+ EX_APP_MENU_ENTRY_NAME ,
35+ } from ' ../constants/AppAPI.js'
3136
3237import { getFilePickerBuilder } from ' @nextcloud/dialogs'
3338import ' @nextcloud/dialogs/style.css'
@@ -42,10 +47,13 @@ export default {
4247 data () {
4348 const baseUrl = generateUrl (` ${ APP_API_PROXY_URL_PREFIX } /${ EX_APP_ID } /` , {}, { noRewrite: true })
4449 const iframeSrcUrl = process .env .HARP_ENABLED ? baseUrl .replace (' /index.php' , ' ' ) : baseUrl
50+
4551 return {
4652 error: null ,
4753 loading: true ,
48- iframeSrc: iframeSrcUrl,
54+ iframeBaseUrl: baseUrl,
55+ pageBaseUrl: generateUrl (` ${ APP_API_ROUTER_BASE } /${ EX_APP_ID } /${ EX_APP_MENU_ENTRY_NAME } ` ),
56+ iframeSrc: this .loadIframeSrcUrlRoute (baseUrl, iframeSrcUrl),
4957 }
5058 },
5159 mounted () {
@@ -63,10 +71,14 @@ export default {
6371 this .error = true
6472 this .loading = false
6573 })
74+
6675 window .addEventListener (' message' , (event ) => {
6776 if (event .data .type === ' openNextcloudFilePicker' ) {
6877 this .showFilePicker (event )
6978 }
79+ if (event .data .type === ' routeChange' ) {
80+ this .handleIframeRouteChange (event .data .route )
81+ }
7082 })
7183 },
7284 methods: {
@@ -95,6 +107,51 @@ export default {
95107 })
96108 this .$refs .iframe .contentWindow .postMessage ({ files, inputParamName }, ' *' )
97109 },
110+ loadIframeSrcUrlRoute (iframeSrcUrl ) {
111+ const pageBaseUrl = generateUrl (` ${ APP_API_ROUTER_BASE } /${ EX_APP_ID } /${ EX_APP_MENU_ENTRY_NAME } ` )
112+ const pagePathRoute = window .location .pathname
113+ .replace (pageBaseUrl, ' ' )
114+ // fix duplicate slashes, remove starting slash
115+ const normalizedPath = pagePathRoute .replace (/ ^ \/ / , ' ' ).replace (/ \/\/ / g , ' /' )
116+
117+ if (iframeSrcUrl .endsWith (' /' )) {
118+ iframeSrcUrl = ` ${ iframeSrcUrl}${ normalizedPath} `
119+ } else {
120+ iframeSrcUrl = ` ${ iframeSrcUrl} /${ normalizedPath} `
121+ }
122+
123+ // always append ending slash if it is not present
124+ if (! iframeSrcUrl .endsWith (' /' )) {
125+ iframeSrcUrl += ' /'
126+ }
127+
128+ return iframeSrcUrl
129+ },
130+ handleIframeRouteChange (route ) {
131+ if (! route) {
132+ return
133+ }
134+
135+ const pageBaseUrl = generateUrl (` ${ APP_API_ROUTER_BASE } /${ EX_APP_ID } /${ EX_APP_MENU_ENTRY_NAME } ` )
136+ // Update window route part after the root path
137+ let normalizedPath = route
138+ if (route !== ' /' ) {
139+ normalizedPath = route .replace (/ ^ \/ / , ' ' ).replace (/ \/\/ / g , ' /' )
140+ if (this .pageBaseUrl .endsWith (' /' )) {
141+ this .pageBaseUrl = ` ${ pageBaseUrl}${ normalizedPath} `
142+ } else {
143+ this .pageBaseUrl = ` ${ pageBaseUrl} /${ normalizedPath} `
144+ }
145+ } else {
146+ this .pageBaseUrl = pageBaseUrl
147+ }
148+
149+ // replace potential duplicate slashes
150+ this .pageBaseUrl = this .pageBaseUrl .replace (/ \/\/ / g , ' /' )
151+
152+ // change the window path, without history
153+ window .history .replaceState ({}, ' ' , this .pageBaseUrl )
154+ },
98155 },
99156}
100157< / script>
0 commit comments