homebridge-ratgdo 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,155 @@
1
+ /* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * webUi.mjs: Plugin webUI.
4
+ */
5
+ "use strict";
6
+
7
+ export class webUi {
8
+
9
+ // Feature options class instance.
10
+ #featureOptions;
11
+
12
+ // Homebridge class instance.
13
+ #homebridge;
14
+
15
+ // Plugin name.
16
+ #name;
17
+
18
+ constructor({ name, featureOptions, homebridge } = {}) {
19
+
20
+ this.homebridge = homebridge;
21
+ this.featureOptions = featureOptions;
22
+ this.name = name;
23
+
24
+ // Fire off our UI, catching errors along the way.
25
+ try {
26
+
27
+ this.#launchWebUI();
28
+ } catch(err) {
29
+
30
+ // If we had an error instantiating or updating the UI, notify the user.
31
+ this.homebridge.toast.error(err.message, "Error");
32
+ } finally {
33
+
34
+ // Always leave the UI in a usable place for the end user.
35
+ this.homebridge.hideSpinner();
36
+ }
37
+ }
38
+
39
+ // Show the first run user experience if we don't have valid login credentials.
40
+ async #showFirstRun() {
41
+
42
+ const buttonFirstRun = document.getElementById("firstRun");
43
+
44
+ // First run user experience.
45
+ buttonFirstRun.addEventListener("click", async () => {
46
+
47
+ // Show the beachball while we setup.
48
+ this.homebridge.showSpinner();
49
+
50
+ // Get the list of devices the plugin knows about.
51
+ const devices = await this.homebridge.getCachedAccessories();
52
+
53
+ // Sort it for posterity.
54
+ devices?.sort((a, b) => {
55
+
56
+ const aCase = (a.displayName ?? "").toLowerCase();
57
+ const bCase = (b.displayName ?? "").toLowerCase();
58
+
59
+ return aCase > bCase ? 1 : (bCase > aCase ? -1 : 0);
60
+ });
61
+
62
+ // Create our UI.
63
+ document.getElementById("pageFirstRun").style.display = "none";
64
+ document.getElementById("menuWrapper").style.display = "inline-flex";
65
+ this.featureOptions.showUI();
66
+
67
+ // All done. Let the user interact with us, although in practice, we shouldn't get here.
68
+ // this.homebridge.hideSpinner();
69
+ });
70
+
71
+ document.getElementById("pageFirstRun").style.display = "block";
72
+ }
73
+
74
+ // Show the main plugin configuration tab.
75
+ #showSettings() {
76
+
77
+ // Show the beachball while we setup.
78
+ this.homebridge.showSpinner();
79
+
80
+ // Create our UI.
81
+ document.getElementById("menuHome").classList.remove("btn-elegant");
82
+ document.getElementById("menuHome").classList.add("btn-primary");
83
+ document.getElementById("menuFeatureOptions").classList.remove("btn-elegant");
84
+ document.getElementById("menuFeatureOptions").classList.add("btn-primary");
85
+ document.getElementById("menuSettings").classList.add("btn-elegant");
86
+ document.getElementById("menuSettings").classList.remove("btn-primary");
87
+
88
+ document.getElementById("pageSupport").style.display = "none";
89
+ document.getElementById("pageFeatureOptions").style.display = "none";
90
+
91
+ this.homebridge.showSchemaForm();
92
+
93
+ // All done. Let the user interact with us.
94
+ this.homebridge.hideSpinner();
95
+ }
96
+
97
+ // Show the support tab.
98
+ #showSupport() {
99
+
100
+ // Show the beachball while we setup.
101
+ this.homebridge.showSpinner();
102
+ this.homebridge.hideSchemaForm();
103
+
104
+ // Create our UI.
105
+ document.getElementById("menuHome").classList.add("btn-elegant");
106
+ document.getElementById("menuHome").classList.remove("btn-primary");
107
+ document.getElementById("menuFeatureOptions").classList.remove("btn-elegant");
108
+ document.getElementById("menuFeatureOptions").classList.add("btn-primary");
109
+ document.getElementById("menuSettings").classList.remove("btn-elegant");
110
+ document.getElementById("menuSettings").classList.add("btn-primary");
111
+
112
+ document.getElementById("pageSupport").style.display = "block";
113
+ document.getElementById("pageFeatureOptions").style.display = "none";
114
+
115
+ // All done. Let the user interact with us.
116
+ this.homebridge.hideSpinner();
117
+ }
118
+
119
+ // Launch our webUI.
120
+ async #launchWebUI() {
121
+
122
+ // Retrieve the current plugin configuration.
123
+ this.featureOptions.currentConfig = await this.homebridge.getPluginConfig();
124
+
125
+ // Add our event listeners to animate the UI.
126
+ document.getElementById("menuHome").addEventListener("click", () => this.#showSupport());
127
+ document.getElementById("menuFeatureOptions").addEventListener("click", () => this.featureOptions.showUI());
128
+ document.getElementById("menuSettings").addEventListener("click", () => this.#showSettings());
129
+
130
+ // Get the list of devices the plugin knows about.
131
+ const devices = await this.homebridge.getCachedAccessories();
132
+
133
+ // If we've got devices detected, we launch our feature option UI. Otherwise, we launch our first run UI.
134
+ if(this.featureOptions.currentConfig.length && devices?.length) {
135
+
136
+ document.getElementById("menuWrapper").style.display = "inline-flex";
137
+ this.featureOptions.showUI();
138
+ return;
139
+ }
140
+
141
+ // If we have no configuration, let's create one.
142
+ if(!this.featureOptions.currentConfig.length) {
143
+
144
+ this.featureOptions.currentConfig.push({ name: this.name });
145
+ } else if(!("name" in this.featureOptions.currentConfig[0])) {
146
+
147
+ // If we haven't set the name, let's do so now.
148
+ this.featureOptions.currentConfig[0].name = this.name;
149
+ }
150
+
151
+ // Update the plugin configuration and launch the first run UI.
152
+ await this.homebridge.updatePluginConfig(this.featureOptions.currentConfig);
153
+ this.#showFirstRun();
154
+ }
155
+ }