Fix Bridge Navigation Event

* If there is no bind all, then keep navigation events as default
* More details (https://github.com/webui-dev/webui/issues/392)
This commit is contained in:
Hassan DRAGA 2024-06-11 16:58:33 -04:00
parent 20c350e3cd
commit 93d78bf7c8
2 changed files with 1563 additions and 1605 deletions

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ class WebuiBridge {
#hasEvents = false; #hasEvents = false;
#callPromiseID = new Uint16Array(1); #callPromiseID = new Uint16Array(1);
#callPromiseResolve: (((data: string) => unknown) | undefined)[] = []; #callPromiseResolve: (((data: string) => unknown) | undefined)[] = [];
#allowNavigation = false; #allowNavigation = true;
#sendQueue: Uint8Array[] = []; #sendQueue: Uint8Array[] = [];
#isSending = false; #isSending = false;
// WebUI Const // WebUI Const
@ -126,32 +126,27 @@ class WebuiBridge {
} }
// Connect to the backend application // Connect to the backend application
this.#start(); this.#start();
// Handle navigation server side // Navigation event listener
if ('navigation' in globalThis) { if ('navigation' in globalThis) {
globalThis.navigation.addEventListener('navigate', (event) => { globalThis.navigation.addEventListener('navigate', (event) => {
if (!this.#allowNavigation) { if (!this.#allowNavigation) {
event.preventDefault(); if (this.#hasEvents && this.#wsStatus) {
const url = new URL(event.destination.url); event.preventDefault();
if (this.#hasEvents) { const url = new URL(event.destination.url);
if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`); if (this.#log) console.log(`WebUI -> DOM -> Navigation Event [${url.href}]`);
this.#sendEventNavigation(url.href); this.#sendEventNavigation(url.href);
} else {
this.#close(this.#CMD_NAVIGATION, url.href);
} }
} }
}); });
} else { } else {
// Handle all link click to prevent natural navigation // Click navigation event listener
// Rebind listener if user inject new html
addRefreshableEventListener(document.body, 'a', 'click', (event) => { addRefreshableEventListener(document.body, 'a', 'click', (event) => {
if (!this.#allowNavigation) { if (!this.#allowNavigation) {
event.preventDefault(); if (this.#hasEvents && this.#wsStatus) {
const { href } = event.target as HTMLAnchorElement; event.preventDefault();
if (this.#hasEvents) { const { href } = event.target as HTMLAnchorElement;
if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`); if (this.#log) console.log(`WebUI -> DOM -> Navigation Click Event [${href}]`);
this.#sendEventNavigation(href); this.#sendEventNavigation(href);
} else {
this.#close(this.#CMD_NAVIGATION, href);
} }
} }
}); });
@ -251,6 +246,7 @@ class WebuiBridge {
this.#callPromiseID[0] = 0; this.#callPromiseID[0] = 0;
if (this.#bindList.includes(this.#winNum + '/')) { if (this.#bindList.includes(this.#winNum + '/')) {
this.#hasEvents = true; this.#hasEvents = true;
this.#allowNavigation = false;
} }
const host = window.location.hostname; const host = window.location.hostname;
const url = this.#secure ? ('wss://' + host) : ('ws://' + host); const url = this.#secure ? ('wss://' + host) : ('ws://' + host);
@ -385,7 +381,6 @@ class WebuiBridge {
} }
} }
break; break;
case this.#CMD_NAVIGATION: case this.#CMD_NAVIGATION:
// Protocol // Protocol
// 0: [SIGNATURE] // 0: [SIGNATURE]
@ -559,34 +554,28 @@ class WebuiBridge {
} }
#sendEventNavigation(url: string) { #sendEventNavigation(url: string) {
if (url !== '') { if (url !== '') {
if (this.#hasEvents) { if (this.#wsStatus) {
if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`); if (this.#log) console.log(`WebUI -> Send Navigation Event [${url}]`);
if (this.#wsStatus && this.#hasEvents) { const packet = Uint8Array.of(
const packet = Uint8Array.of( // Protocol
// Protocol // 0: [SIGNATURE]
// 0: [SIGNATURE] // 1: [TOKEN]
// 1: [TOKEN] // 2: [ID]
// 2: [ID] // 3: [CMD]
// 3: [CMD] // 4: [URL]
// 4: [URL] this.#WEBUI_SIGNATURE,
this.#WEBUI_SIGNATURE, 0,
0, 0,
0, 0,
0, 0, // Token (4 Bytes)
0, // Token (4 Bytes) 0,
0, 0, // ID (2 Bytes)
0, // ID (2 Bytes) this.#CMD_NAVIGATION,
this.#CMD_NAVIGATION, ...new TextEncoder().encode(url),
...new TextEncoder().encode(url), );
); this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN);
this.#addToken(packet, this.#token, this.#PROTOCOL_TOKEN); // this.#addID(packet, 0, this.#PROTOCOL_ID)
// this.#addID(packet, 0, this.#PROTOCOL_ID) this.#sendData(packet);
this.#sendData(packet);
}
} else {
if (this.#log) console.log(`WebUI -> Navigation To [${url}]`);
this.#allowNavigation = true;
globalThis.location.replace(url);
} }
} }
} }