homebridge-intratone 0.5.0 → 0.5.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to `homebridge-intratone`. Versions follow [semver](https://semver.org/).
4
4
 
5
+ ## [0.5.1] - 2026-11-12
6
+
7
+ ### Fixed
8
+
9
+ - The **Regenerate device ID** button did nothing: the settings UI runs in a sandboxed iframe
10
+ without `allow-modals`, so the `window.confirm()` it used was blocked. It now confirms inline.
11
+ - The settings page left a large empty area and a prominent "Device identity" block. The device-ID
12
+ tools are now a compact, collapsed **Device ID (advanced)** section, and the page resizes to its
13
+ content so there is no empty space.
14
+
5
15
  ## [0.5.0] - 2026-11-12
6
16
 
7
17
  ### Added
@@ -165,6 +175,7 @@ two-way audio are out of scope.
165
175
  masked.
166
176
  - MIT license.
167
177
 
178
+ [0.5.1]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.5.1
168
179
  [0.5.0]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.5.0
169
180
  [0.4.2]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.4.2
170
181
  [0.4.1]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.4.1
@@ -1,13 +1,22 @@
1
1
  <!-- Custom settings page for homebridge-config-ui-x.
2
- Keeps the standard form (phone number, service, Advanced) and adds two user-facing helpers:
3
- a rename-your-doors list and a "Regenerate device ID" button. The technical connection values
4
- live in the Advanced fields (Device ID is pre-filled with the effective value). The form is
5
- shown via showSchemaForm() only once a config block exists (config-ui-x gates it on that). -->
6
- <div id="intratone-doors" class="mb-3"></div>
7
- <div id="intratone-device" class="mb-3"></div>
2
+ Adds a rename-your-doors list, and a collapsed "Device ID" advanced area with a Regenerate
3
+ button. The standard form (phone number, service, Advanced) is shown via showSchemaForm().
4
+ Note: the UI runs in a sandboxed iframe without allow-modals, so window.confirm/alert are
5
+ blocked — confirmation is done inline. -->
6
+ <div id="intratone-doors" class="mb-2"></div>
7
+ <div id="intratone-device"></div>
8
8
 
9
9
  <script>
10
10
  let started = false;
11
+ let block = { platform: 'Intratone', name: 'Intratone' };
12
+
13
+ function fit() {
14
+ try {
15
+ if (typeof homebridge.fixScrollHeight === 'function') {
16
+ homebridge.fixScrollHeight();
17
+ }
18
+ } catch (e) { /* ignore */ }
19
+ }
11
20
 
12
21
  async function init() {
13
22
  if (started) {
@@ -18,11 +27,9 @@
18
27
  const doors = document.getElementById('intratone-doors');
19
28
  const device = document.getElementById('intratone-device');
20
29
 
21
- let block;
22
30
  try {
23
31
  let configs = await homebridge.getPluginConfig();
24
32
  if (!configs.length) {
25
- // config-ui-x renders the schema form only once a config block exists.
26
33
  await homebridge.updatePluginConfig([{ platform: 'Intratone', name: 'Intratone' }]);
27
34
  configs = await homebridge.getPluginConfig();
28
35
  }
@@ -32,8 +39,8 @@
32
39
  return;
33
40
  }
34
41
 
35
- // Fill the Advanced "Device ID" field with the effective id so it is not blank. Needs the
36
- // phone number set (to resolve the account); harmless to skip before then.
42
+ // Fill the Advanced "Device ID" field with the effective id so it is not blank (needs the
43
+ // phone number set; harmless to skip before then).
37
44
  try {
38
45
  if (!block.device_id) {
39
46
  const info = await homebridge.request('/device', { config: block });
@@ -43,7 +50,7 @@
43
50
  }
44
51
  }
45
52
  } catch (error) {
46
- // No phone number yet, or not resolvable — leave Device ID blank for now.
53
+ // No phone number yet — leave Device ID blank for now.
47
54
  }
48
55
 
49
56
  try {
@@ -52,8 +59,6 @@
52
59
  console.error('showSchemaForm failed', error);
53
60
  }
54
61
 
55
- renderDeviceTools(device, block);
56
-
57
62
  let accesses;
58
63
  try {
59
64
  homebridge.showSpinner();
@@ -63,15 +68,17 @@
63
68
  } finally {
64
69
  homebridge.hideSpinner();
65
70
  }
66
- renderDoors(doors, block, accesses);
71
+ renderDoors(doors, accesses);
72
+ renderDeviceTools(device);
73
+ fit();
67
74
  }
68
75
 
69
76
  homebridge.addEventListener('ready', init);
70
77
  setTimeout(init, 1500);
71
78
 
72
- function note(parent, text) {
79
+ function note(parent, text, cls) {
73
80
  const p = document.createElement('p');
74
- p.className = 'help-block text-muted';
81
+ p.className = (cls || 'help-block text-muted') + ' mb-1';
75
82
  p.textContent = text;
76
83
  parent.appendChild(p);
77
84
  }
@@ -86,30 +93,53 @@
86
93
  }).toUpperCase();
87
94
  }
88
95
 
89
- function renderDeviceTools(container, block) {
96
+ function renderDeviceTools(container) {
90
97
  container.innerHTML = '';
91
- const title = document.createElement('h5');
92
- title.textContent = 'Device identity';
93
- container.appendChild(title);
94
- note(container, 'The device ID the plugin uses is shown in Advanced → Device ID. Regenerate it to log in as a brand-new device. A new device does NOT hold the 4G key until you claim it (which revokes the phone); put the old ID back to restore the current setup.');
95
-
96
- const button = document.createElement('button');
97
- button.type = 'button';
98
- button.className = 'btn btn-secondary btn-sm';
99
- button.textContent = 'Regenerate device ID';
100
- button.addEventListener('click', () => {
101
- if (!window.confirm('Generate a new device ID? The new device will not open the 4G doors until you claim the key (which revokes your phone), or until you set the ID back. Continue?')) {
102
- return;
103
- }
98
+ const details = document.createElement('details');
99
+ details.addEventListener('toggle', fit);
100
+
101
+ const summary = document.createElement('summary');
102
+ summary.textContent = 'Device ID (advanced)';
103
+ summary.style.cursor = 'pointer';
104
+ details.appendChild(summary);
105
+
106
+ note(details, 'Generate a new device identity. A new device will NOT open the 4G doors until you claim the key (which revokes the phone) or set the ID back. The ID in use is shown in Advanced → Device ID.');
107
+
108
+ const bar = document.createElement('div');
109
+ const regen = document.createElement('button');
110
+ regen.type = 'button';
111
+ regen.className = 'btn btn-secondary btn-sm';
112
+ regen.textContent = 'Regenerate device ID';
113
+ regen.addEventListener('click', () => {
104
114
  const id = newUuid();
105
- block.device_id = id;
106
- homebridge.updatePluginConfig([block]);
107
- homebridge.toast.success('New device ID: ' + id + '. Press Save, then restart the Intratone child bridge.', 'Device ID');
115
+ bar.innerHTML = '';
116
+ note(bar, 'Set new device ID ' + id + '?', 'text-danger');
117
+ const yes = document.createElement('button');
118
+ yes.type = 'button';
119
+ yes.className = 'btn btn-danger btn-sm mr-2';
120
+ yes.textContent = 'Confirm';
121
+ yes.addEventListener('click', () => {
122
+ block.device_id = id;
123
+ homebridge.updatePluginConfig([block]);
124
+ homebridge.toast.success('New device ID set. Press Save, then restart the Intratone child bridge.', 'Device ID');
125
+ renderDeviceTools(container);
126
+ fit();
127
+ });
128
+ const no = document.createElement('button');
129
+ no.type = 'button';
130
+ no.className = 'btn btn-link btn-sm';
131
+ no.textContent = 'Cancel';
132
+ no.addEventListener('click', () => { renderDeviceTools(container); fit(); });
133
+ bar.appendChild(yes);
134
+ bar.appendChild(no);
135
+ fit();
108
136
  });
109
- container.appendChild(button);
137
+ bar.appendChild(regen);
138
+ details.appendChild(bar);
139
+ container.appendChild(details);
110
140
  }
111
141
 
112
- function overridesFromConfig(block) {
142
+ function overridesFromConfig() {
113
143
  const map = {};
114
144
  for (const entry of (block.access_names || [])) {
115
145
  if (entry && entry.access_id) {
@@ -119,7 +149,7 @@
119
149
  return map;
120
150
  }
121
151
 
122
- function saveOverrides(block, map) {
152
+ function saveOverrides(map) {
123
153
  const list = Object.keys(map)
124
154
  .filter((id) => (map[id] || '').trim())
125
155
  .map((id) => ({ access_id: id, name: map[id].trim() }));
@@ -131,30 +161,32 @@
131
161
  homebridge.updatePluginConfig([block]);
132
162
  }
133
163
 
134
- function renderDoors(container, block, accesses) {
164
+ function renderDoors(container, accesses) {
135
165
  container.innerHTML = '';
136
166
  const title = document.createElement('h5');
137
167
  title.textContent = 'Your doors';
168
+ title.className = 'mb-1';
138
169
  container.appendChild(title);
139
170
 
140
171
  if (!accesses || accesses.error) {
141
172
  const reason = accesses && accesses.error ? accesses.error : 'unavailable';
142
- note(container, 'Could not list your doors (' + reason + '). Set the phone number below and Save first. You can also rename doors in Advanced via the config; unnamed doors keep their detected names in the Home app.');
173
+ note(container, 'Could not list your doors (' + reason + '). Set the phone number below and Save first; unnamed doors keep their detected names in the Home app.');
143
174
  return;
144
175
  }
145
176
 
146
177
  const list = accesses.openable || [];
147
- const map = overridesFromConfig(block);
178
+ const map = overridesFromConfig();
148
179
 
149
180
  note(container, list.length
150
- ? 'Type a name to show it in the Home app, then press Save. Renaming an existing door re-adds it in Home (it may briefly lose its room/automations). Leave blank to keep the detected name.'
151
- : 'No openable doors detected yet. Once they appear, you can rename them here.');
181
+ ? 'Type a name to show it in the Home app, then press Save. Renaming an existing door re-adds it (it may briefly lose its room/automations).'
182
+ : 'No openable doors detected yet.');
152
183
 
153
184
  for (const door of list) {
154
185
  const group = document.createElement('div');
155
- group.className = 'form-group';
186
+ group.className = 'form-group mb-2';
156
187
 
157
188
  const label = document.createElement('label');
189
+ label.className = 'mb-1';
158
190
  const where = door.residence ? door.residence + ' / ' : '';
159
191
  label.textContent = where + door.name + ' (id ' + door.id + ')';
160
192
  group.appendChild(label);
@@ -166,7 +198,7 @@
166
198
  input.value = map[door.id] || '';
167
199
  input.addEventListener('input', () => {
168
200
  map[door.id] = input.value;
169
- saveOverrides(block, map);
201
+ saveOverrides(map);
170
202
  });
171
203
  group.appendChild(input);
172
204
  container.appendChild(group);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-intratone",
3
3
  "displayName": "Intratone",
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
5
5
  "description": "Unofficial Homebridge plugin to open Intratone / Cogelec doors and gates from HomeKit and Matter (remote open, no doorbell).",
6
6
  "license": "MIT",
7
7
  "author": "jtoucas-DIMO",