diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5fd995c59..12c1a983f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -352,7 +352,7 @@ class extends HTMLElement { The class property `_states` can then be used in the JavaScript component code: ```javascript -this._state = this._states.FETCH_FROM_URL; +this._state = this._states.INITIALIZING; ``` We then use CSS rules based on the `state` attribute to control the component's appearance: @@ -388,6 +388,16 @@ This ensures that the elements in the `
` only appear when Prefer to change a web component's appearance based on attributes and CSS rules as opposed to JavaScript that manipulates the `.style` attributes of elements within the component. +We can then initialize the component when the dialog is opened by listening for the `overlay-shown` event: + +```javascript +connectedCallback() { + this.addEventListener("overlay-shown", () => { + this._state = this._states.INITIALIZING); + }; +} +``` + ### Disable closing a dialog For a component that is used within an overlay, there might be certain states that should prevent the user from closing the dialog. That’s typically the case when we are waiting for an action to complete (for example when loading something). diff --git a/app/static/js/app.js b/app/static/js/app.js index e8e54ef26..f9c3c6e30 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -230,8 +230,11 @@ document.onload = document.getElementById("app").focus(); document.addEventListener("keydown", onKeyDown); document.addEventListener("keyup", onKeyUp); -document.addEventListener("overlay-toggled", (evt) => { - overlayTracker.trackStatus(evt.target, evt.detail.isShown); +document.addEventListener("overlay-shown", (evt) => { + overlayTracker.trackStatus(evt.detail.overlay, /*isShown=*/ true); +}); +document.addEventListener("overlay-hidden", (evt) => { + overlayTracker.trackStatus(evt.detail.overlay, /*isShown=*/ false); }); document.addEventListener("video-streaming-mode-changed", (evt) => { document.getElementById("status-bar").videoStreamIndicator.mode = @@ -314,35 +317,21 @@ menuBar.addEventListener("update-dialog-requested", () => { document.getElementById("update-dialog").checkVersion(); }); menuBar.addEventListener("change-hostname-dialog-requested", () => { - // Note: we have to call `initialize()` after `show()`, to ensure that the - // dialog is able to focus the main input element. - // See https://github.com/tiny-pilot/tinypilot/issues/1770 document.getElementById("change-hostname-overlay").show(); - document.getElementById("change-hostname-dialog").initialize(); }); menuBar.addEventListener("wifi-dialog-requested", () => { - // Note: we have to call `initialize()` after `show()`, to ensure that the - // dialog is able to focus the main input element. - // See https://github.com/tiny-pilot/tinypilot/issues/1770 document.getElementById("wifi-overlay").show(); - document.getElementById("wifi-dialog").initialize(); }); menuBar.addEventListener("network-status-dialog-requested", () => { - // Note: we have to call `initialize()` after `show()`, to ensure that the - // dialog is able to focus the main input element. - // See https://github.com/tiny-pilot/tinypilot/issues/1770 document.getElementById("network-status-overlay").show(); - document.getElementById("network-status-dialog").initialize(); }); menuBar.addEventListener("fullscreen-requested", () => { document.getElementById("remote-screen").fullscreen = true; }); menuBar.addEventListener("debug-logs-dialog-requested", () => { - document.getElementById("debug-dialog").retrieveLogs(); document.getElementById("debug-overlay").show(); }); menuBar.addEventListener("about-dialog-requested", () => { - document.getElementById("about-dialog").initialize(); document.getElementById("about-overlay").show(); }); menuBar.addEventListener("mass-storage-dialog-requested", () => { @@ -355,15 +344,10 @@ menuBar.addEventListener("static-ip-dialog-requested", () => { document.getElementById("feature-pro-overlay").show(); }); menuBar.addEventListener("video-settings-dialog-requested", () => { - document.getElementById("video-settings-dialog").initialize(); document.getElementById("video-settings-overlay").show(); }); menuBar.addEventListener("paste-dialog-requested", () => { - // Note: we have to call `initialize()` after `show()`, to ensure that the - // dialog is able to focus the main input element. - // See https://github.com/tiny-pilot/tinypilot/issues/1770 document.getElementById("paste-overlay").show(); - document.getElementById("paste-dialog").initialize(); }); menuBar.addEventListener("ctrl-alt-del-requested", () => { // Even though only the final keystroke matters, send them one at a time to diff --git a/app/templates/custom-elements/about-dialog.html b/app/templates/custom-elements/about-dialog.html index d4d2a6cd6..7682c897e 100644 --- a/app/templates/custom-elements/about-dialog.html +++ b/app/templates/custom-elements/about-dialog.html @@ -82,6 +82,7 @@

About TinyPilot

this.attachShadow({ mode: "open" }).appendChild( template.content.cloneNode(true) ); + this.addEventListener("overlay-shown", () => this._initialize()); this.shadowRoot .querySelector(".close-btn") .addEventListener("click", () => @@ -89,7 +90,7 @@

About TinyPilot

); } - initialize() { + _initialize() { this._checkVersion(); this._populateCredits(); } diff --git a/app/templates/custom-elements/change-hostname-dialog.html b/app/templates/custom-elements/change-hostname-dialog.html index 6166f2469..5af1b237a 100644 --- a/app/templates/custom-elements/change-hostname-dialog.html +++ b/app/templates/custom-elements/change-hostname-dialog.html @@ -125,6 +125,7 @@

Changing Hostname

futureLocation: this.shadowRoot.getElementById("future-location"), }; + this.addEventListener("overlay-shown", () => this._initialize()); this._elements.hostnameInput.addEventListener("input", () => { this._onInputChanged(); }); @@ -162,7 +163,7 @@

Changing Hostname

this.setAttribute("initial-hostname", initialHostname); } - initialize() { + _initialize() { this._elements.inputError.hide(); this._state = this._states.INITIALIZING; determineHostname() diff --git a/app/templates/custom-elements/debug-dialog.html b/app/templates/custom-elements/debug-dialog.html index 24d2ff3a3..af6715a66 100644 --- a/app/templates/custom-elements/debug-dialog.html +++ b/app/templates/custom-elements/debug-dialog.html @@ -82,9 +82,6 @@

Debug Logs

constructor() { super(); this.attachShadow({ mode: "open" }); - // Ensure that these methods always refer to the correct "this", - // regardless of where they are called. - this.retrieveLogs = this.retrieveLogs.bind(this); } connectedCallback() { @@ -106,6 +103,8 @@

Debug Logs

shareLogsButton: this.shadowRoot.querySelector("#share-logs-button"), }; + + this.addEventListener("overlay-shown", () => this._initialize()); this._elements.includeSensitiveData.addEventListener( "input", (event) => { @@ -145,7 +144,7 @@

Debug Logs

return this.hasAttribute("include-sensitive-data"); } - retrieveLogs() { + _initialize() { this._state = this._states.LOGS_LOADING; getDebugLogs() .then((text) => { diff --git a/app/templates/custom-elements/network-status-dialog.html b/app/templates/custom-elements/network-status-dialog.html index 960476742..22f7516fa 100644 --- a/app/templates/custom-elements/network-status-dialog.html +++ b/app/templates/custom-elements/network-status-dialog.html @@ -66,21 +66,20 @@

Network Status

}; this._shouldAutoUpdate = false; this._updateTicker = null; + + this.addEventListener("overlay-shown", () => this._initialize()); + this.addEventListener("overlay-hidden", () => { + // Stop the update ticker when the dialog is closed, otherwise the + // status requests would continue to be fired even when the dialog + // is not visible anymore. + this._shouldAutoUpdate = false; + clearTimeout(this._updateTicker); + }); this.shadowRoot .querySelector("#close-button") .addEventListener("click", () => { this.dispatchEvent(new DialogClosedEvent()); }); - - // For all events that terminate the dialog, make sure to stop the - // update ticker, otherwise the status requests would continue to be - // fired even when the dialog is not visible anymore. - ["dialog-closed", "dialog-failed"].forEach((evtName) => { - this.addEventListener(evtName, () => { - this._shouldAutoUpdate = false; - clearTimeout(this._updateTicker); - }); - }); } get _state() { @@ -96,7 +95,7 @@

Network Status

); } - async initialize() { + async _initialize() { this._state = this._states.INITIALIZING; await this._update(); this._state = this._states.DISPLAY; diff --git a/app/templates/custom-elements/overlay-panel.html b/app/templates/custom-elements/overlay-panel.html index d6f6a3d69..23c85bf04 100644 --- a/app/templates/custom-elements/overlay-panel.html +++ b/app/templates/custom-elements/overlay-panel.html @@ -66,8 +66,6 @@