1import {LitElement, html} from 'https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js';
2
3class BumbleControls extends LitElement {
4    constructor() {
5        super();
6        this.bumbleLoaded = false;
7        this.connected = false;
8    }
9
10    render() {
11        return html`
12            <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
13            <dialog id="settings-dialog" @close=${this.onSettingsDialogClose} style="font-family:sans-serif">
14                <p>WebSocket URL for HCI transport</p>
15                <form>
16                    <input id="settings-hci-url-input" type="text" size="50"></input>
17                    <button value="cancel" formmethod="dialog">Cancel</button>
18                    <button @click=${this.saveSettings}>Save</button>
19                </form>
20            </dialog>
21            <button @click=${this.openSettingsDialog} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>settings</button>
22            <button @click=${this.connectBluetooth} ?disabled=${!this.canConnect()} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>bluetooth</button>
23            <button @click=${this.stop} ?disabled=${!this.connected} class="mdc-icon-button material-icons"><div class="mdc-icon-button__ripple"></div>stop</button>
24        `
25    }
26
27    get settingsHciUrlInput() {
28        return this.renderRoot.querySelector('#settings-hci-url-input');
29    }
30
31    get settingsDialog() {
32        return this.renderRoot.querySelector('#settings-dialog');
33    }
34
35    canConnect() {
36        return this.bumbleLoaded && !this.connected && this.getHciUrl();
37    }
38
39    getHciUrl() {
40        // Look for a URL parameter setting first.
41        const params = (new URL(document.location)).searchParams;
42        let hciWsUrl = params.get("hci");
43        if (hciWsUrl) {
44          return hciWsUrl;
45        }
46
47        // Try to load the setting from storage.
48        hciWsUrl = localStorage.getItem("hciWsUrl");
49        if (hciWsUrl) {
50          return hciWsUrl;
51        }
52
53        // Finally, default to nothing.
54        return null;
55    }
56
57    openSettingsDialog() {
58        const hciUrl = this.getHciUrl();
59        if (hciUrl) {
60            this.settingsHciUrlInput.value = hciUrl;
61        } else {
62          // Start with default, assuming port 7681.
63          this.settingsHciUrlInput.value = "ws://localhost:7681/v1/websocket/bt"
64        }
65        this.settingsDialog.showModal();
66    }
67
68    onSettingsDialogClose() {
69        if (this.settingsDialog.returnValue === "cancel") {
70            return;
71        }
72        if (this.settingsHciUrlInput.value) {
73            localStorage.setItem("hciWsUrl", this.settingsHciUrlInput.value);
74        } else {
75            localStorage.removeItem("hciWsUrl");
76        }
77
78        this.requestUpdate();
79    }
80
81    saveSettings(event) {
82        event.preventDefault();
83        this.settingsDialog.close(this.settingsHciUrlInput.value);
84    }
85
86    async connectBluetooth() {
87        this.connected = await this.connector(this.getHciUrl());
88        this.requestUpdate();
89    }
90
91    async stop() {
92        await this.stopper();
93        this.connected = false;
94        this.requestUpdate();
95    }
96
97    onBumbleLoaded() {
98        this.bumbleLoaded = true;
99        this.requestUpdate();
100    }
101}
102customElements.define('bumble-controls', BumbleControls);
103