summaryrefslogtreecommitdiffhomepage
path: root/main.mjs
diff options
context:
space:
mode:
authorLi Zhineng <[email protected]>2025-07-12 16:48:26 +0800
committerLi Zhineng <[email protected]>2025-07-12 16:48:26 +0800
commit9f80e84fa0c82cf8b7a683393051318b4923b372 (patch)
tree84e5e379ec1cd819f617e70c44792a503a411080 /main.mjs
parent3f07ce0826968c1461e7bf6c3e8072bc18862416 (diff)
downloadsetup-9f80e84fa0c82cf8b7a683393051318b4923b372.tar.gz
setup-9f80e84fa0c82cf8b7a683393051318b4923b372.zip
communicate progress
Diffstat (limited to 'main.mjs')
-rw-r--r--main.mjs111
1 files changed, 108 insertions, 3 deletions
diff --git a/main.mjs b/main.mjs
index 5c74731..9d0d025 100644
--- a/main.mjs
+++ b/main.mjs
@@ -563,6 +563,9 @@ class CommunicationForm extends Form {
/** @type {string} */
#descriptionText
+ /** @type {Progress} */
+ #progress
+
#handshakeCommand
#wifiCredentialsCommand
#identityCommand
@@ -590,6 +593,7 @@ class CommunicationForm extends Form {
this.#messages = new IncomingMessageHandler()
this.#messages.onMessage(this.handleMessage.bind(this))
this.#setupCounter()
+ this.#setupProgress()
this.#handshakeCommand = new HandshakeCommand()
this.#wifiCredentialsCommand = new ConfigureWifiCommand('', '')
this.#identityCommand = new RequestIdentityCommand()
@@ -611,25 +615,40 @@ class CommunicationForm extends Form {
this.#description = this.form.querySelector('.form__description')
this.#descriptionText = this.#description ? this.#description.textContent : ''
this.#countdown = new Countdown(this.#description, 10)
- this.#countdown.onComplete(this.transitToFailureResultForm.bind(this))
+ this.#countdown.onComplete(() => {
+ this.#progress.clear()
+ this.disconnectIfNeeded()
+ this.transitToFailureResultForm()
+ })
this.#countdown.onStop(() => {
this.#description.textContent = this.#descriptionText
})
}
+ #setupProgress() {
+ const el = this.form.querySelector('[data-slot="progress"]')
+ this.#progress = new Progress(el, [
+ { id: 'handshake', name: 'Say a hello to the machine' },
+ { id: 'wifi', name: 'Send Wi-Fi credentials' },
+ { id: 'identity', name: 'Receive the device\'s identity' }
+ ])
+ }
+
async startPairing() {
try {
await this.connect()
} catch {
this.showRetryOption()
- } finally {
- this.disconnectIfNeeded()
}
}
async connect() {
await this.#handler.connect()
+
this.#countdown.start()
+ this.#progress.render()
+
+ this.#progress.markAsCurrent('handshake')
await this.#handler.dispatch(this.#handshakeCommand)
}
@@ -661,6 +680,8 @@ class CommunicationForm extends Form {
* @param {CompleteMessage} message
*/
handleHandshakeMessage(message) {
+ this.#progress.markAsComplete('handshake')
+ this.#progress.markAsCurrent('wifi')
this.#handler.dispatch(this.#wifiCredentialsCommand)
}
@@ -668,6 +689,8 @@ class CommunicationForm extends Form {
* @param {CompleteMessage} message
*/
handleWifiCredentialsMessage(message) {
+ this.#progress.markAsComplete('wifi')
+ this.#progress.markAsCurrent('identity')
this.#handler.dispatch(this.#identityCommand)
}
@@ -676,6 +699,9 @@ class CommunicationForm extends Form {
*/
handleIdentityMessage(message) {
this.#countdown.stop()
+ this.#progress.markAsComplete('identity')
+ this.#progress.clear()
+ this.disconnectIfNeeded()
this.transitToSuccessResultForm()
}
@@ -733,6 +759,85 @@ class FailureForm extends ProgressibleForm {
}
}
+class Progress {
+ #el
+ #steps
+
+ /**
+ * @param {HTMLElement|null} el - The HTML element to display the progress.
+ * @param {{ id: string, name: string }[]} steps - The progress steps.
+ */
+ constructor(el, steps) {
+ this.#el = el
+ this.#steps = steps
+ if (this.#el === null) {
+ throw new Error('The HTML element could not be found to mount the progress.')
+ }
+ }
+
+ render() {
+ if (! this.#el.classList.contains('progress')) {
+ this.#el.classList.add('progress')
+ }
+
+ for (const step of this.#steps) {
+ const el = document.createElement('li')
+ el.innerText = step.name
+ el.classList.add('progress__item')
+ el.dataset.progress = step.id
+ this.#el.appendChild(el)
+ }
+ }
+
+ clear() {
+ this.#el.innerHTML = ''
+ }
+
+ /**
+ * @param {string} step - The step ID.
+ */
+ markAsCurrent(step) {
+ this.markAsDefault(step)
+
+ const el = this.#stepElement(step)
+ el.dataset.current = ''
+ }
+
+ /**
+ * @param {string} step - The step ID.
+ */
+ markAsComplete(step) {
+ this.markAsDefault(step)
+
+ const el = this.#stepElement(step)
+ el.dataset.complete = ''
+ }
+
+ /**
+ * @param {string} step - The step ID.
+ */
+ markAsDefault(step) {
+ const el = this.#stepElement(step)
+ if ('current' in el.dataset) {
+ delete el.dataset.current
+ }
+ if ('complete' in el.dataset) {
+ delete el.dataset.complete
+ }
+ }
+
+ /**
+ * @param {string} id - The step ID.
+ */
+ #stepElement(id) {
+ const el = this.#el.querySelector(`[data-progress="${id}"]`)
+ if (! el) {
+ throw new Error(`Progress step "${step}" does not exist.`)
+ }
+ return el
+ }
+}
+
class Application {
static supportBluetoothApi() {
return 'bluetooth' in navigator