aboutsummaryrefslogtreecommitdiff
path: root/web/ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/ui.js')
-rw-r--r--web/ui.js102
1 files changed, 102 insertions, 0 deletions
diff --git a/web/ui.js b/web/ui.js
new file mode 100644
index 0000000..6e8d877
--- /dev/null
+++ b/web/ui.js
@@ -0,0 +1,102 @@
+import {LitElement, html} from 'https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js';
+
+class BumbleControls extends LitElement {
+ constructor() {
+ super();
+ this.bumbleLoaded = false;
+ this.connected = false;
+ }
+
+ render() {
+ return html`
+ <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
+ <dialog id="settings-dialog" @close=${this.onSettingsDialogClose} style="font-family:sans-serif">
+ <p>WebSocket URL for HCI transport</p>
+ <form>
+ <input id="settings-hci-url-input" type="text" size="50"></input>
+ <button value="cancel" formmethod="dialog">Cancel</button>
+ <button @click=${this.saveSettings}>Save</button>
+ </form>
+ </dialog>
+ <button @click=${this.openSettingsDialog} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>settings</button>
+ <button @click=${this.connectBluetooth} ?disabled=${!this.canConnect()} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>bluetooth</button>
+ <button @click=${this.stop} ?disabled=${!this.connected} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>stop</button>
+ `
+ }
+
+ get settingsHciUrlInput() {
+ return this.renderRoot.querySelector('#settings-hci-url-input');
+ }
+
+ get settingsDialog() {
+ return this.renderRoot.querySelector('#settings-dialog');
+ }
+
+ canConnect() {
+ return this.bumbleLoaded && !this.connected && this.getHciUrl();
+ }
+
+ getHciUrl() {
+ // Look for a URL parameter setting first.
+ const params = (new URL(document.location)).searchParams;
+ let hciWsUrl = params.get("hci");
+ if (hciWsUrl) {
+ return hciWsUrl;
+ }
+
+ // Try to load the setting from storage.
+ hciWsUrl = localStorage.getItem("hciWsUrl");
+ if (hciWsUrl) {
+ return hciWsUrl;
+ }
+
+ // Finally, default to nothing.
+ return null;
+ }
+
+ openSettingsDialog() {
+ const hciUrl = this.getHciUrl();
+ if (hciUrl) {
+ this.settingsHciUrlInput.value = hciUrl;
+ } else {
+ // Start with default, assuming port 7681.
+ this.settingsHciUrlInput.value = "ws://localhost:7681/v1/websocket/bt"
+ }
+ this.settingsDialog.showModal();
+ }
+
+ onSettingsDialogClose() {
+ if (this.settingsDialog.returnValue === "cancel") {
+ return;
+ }
+ if (this.settingsHciUrlInput.value) {
+ localStorage.setItem("hciWsUrl", this.settingsHciUrlInput.value);
+ } else {
+ localStorage.removeItem("hciWsUrl");
+ }
+
+ this.requestUpdate();
+ }
+
+ saveSettings(event) {
+ event.preventDefault();
+ this.settingsDialog.close(this.settingsHciUrlInput.value);
+ }
+
+ async connectBluetooth() {
+ this.connected = await this.connector(this.getHciUrl());
+ this.requestUpdate();
+ }
+
+ async stop() {
+ await this.stopper();
+ this.connected = false;
+ this.requestUpdate();
+ }
+
+ onBumbleLoaded() {
+ this.bumbleLoaded = true;
+ this.requestUpdate();
+ }
+}
+customElements.define('bumble-controls', BumbleControls);