(devices: ButtplugClientDevice[])
| 30 | } |
| 31 | |
| 32 | function renderDevices(devices: ButtplugClientDevice[]) { |
| 33 | clearChildren(deviceListEl); |
| 34 | |
| 35 | if (devices.length === 0) { |
| 36 | const em = document.createElement("em"); |
| 37 | em.style.color = "#666"; |
| 38 | em.textContent = "None connected"; |
| 39 | deviceListEl.appendChild(em); |
| 40 | return; |
| 41 | } |
| 42 | |
| 43 | for (const device of devices) { |
| 44 | const row = document.createElement("div"); |
| 45 | row.className = "device-row"; |
| 46 | |
| 47 | const name = document.createElement("span"); |
| 48 | name.className = "device-name"; |
| 49 | name.textContent = device.name; |
| 50 | |
| 51 | const slider = document.createElement("input"); |
| 52 | slider.type = "range"; |
| 53 | slider.min = "0"; |
| 54 | slider.max = "100"; |
| 55 | slider.value = "50"; |
| 56 | slider.title = "Speed"; |
| 57 | |
| 58 | const btnVibrate = document.createElement("button"); |
| 59 | btnVibrate.textContent = "Vibrate"; |
| 60 | btnVibrate.addEventListener("click", async () => { |
| 61 | const speed = Number(slider.value) / 100; |
| 62 | try { |
| 63 | await device.vibrate(speed); |
| 64 | log(`${device.name}: vibrate @ ${speed.toFixed(2)}`); |
| 65 | } catch (e) { |
| 66 | log(`${device.name}: vibrate error — ${e}`); |
| 67 | } |
| 68 | }); |
| 69 | |
| 70 | const btnStop = document.createElement("button"); |
| 71 | btnStop.textContent = "Stop"; |
| 72 | btnStop.addEventListener("click", async () => { |
| 73 | try { |
| 74 | await device.stop(); |
| 75 | log(`${device.name}: stopped`); |
| 76 | } catch (e) { |
| 77 | log(`${device.name}: stop error — ${e}`); |
| 78 | } |
| 79 | }); |
| 80 | |
| 81 | row.append(name, slider, btnVibrate, btnStop); |
| 82 | deviceListEl.appendChild(row); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | function setConnectedState(connected: boolean) { |
| 87 | btnConnect.disabled = connected; |
no test coverage detected