@homebridge-plugins/homebridge-eufy-security 4.6.0-beta.43 → 4.6.0-beta.44

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/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const LIB_VERSION = "4.6.0-beta.43";
1
+ export const LIB_VERSION = "4.6.0-beta.44";
2
2
  //# sourceMappingURL=version.js.map
@@ -37,33 +37,33 @@ const RecordingsView = {
37
37
  info.innerHTML = Helpers.iconHtml('info.svg') + ' <strong>Raw</strong> recordings capture the P2P feed directly from the camera (before FFmpeg). <strong>Processed</strong> recordings capture the re-encoded stream sent to HomeKit. Compare them to narrow down where an issue originates.';
38
38
  container.appendChild(info);
39
39
 
40
- // Loading spinner
41
- const spinner = document.createElement('div');
42
- spinner.id = 'recordings-spinner';
43
- spinner.className = 'd-flex justify-content-center my-3';
44
- spinner.innerHTML = '<div class="spinner-border spinner-border-sm text-primary" role="status"><span class="visually-hidden">Loading...</span></div>';
45
- container.appendChild(spinner);
40
+ // Toolbar row (Reload + Delete All)
41
+ const toolbar = document.createElement('div');
42
+ toolbar.className = 'd-flex justify-content-between align-items-center mb-3';
43
+ toolbar.id = 'recordings-toolbar';
46
44
 
47
- // Recordings list container
48
- const listContainer = document.createElement('div');
49
- listContainer.id = 'recordings-list';
50
- container.appendChild(listContainer);
51
-
52
- // Actions row
53
- const actionsRow = document.createElement('div');
54
- actionsRow.className = 'mt-3';
55
- actionsRow.id = 'recordings-actions';
56
- actionsRow.style.display = 'none';
45
+ const btnReload = document.createElement('button');
46
+ btnReload.className = 'btn btn-outline-primary btn-sm';
47
+ btnReload.appendChild(Helpers.icon('refresh.svg'));
48
+ btnReload.append(' Reload');
49
+ btnReload.addEventListener('click', () => this._loadRecordings(container));
57
50
 
58
51
  const btnDeleteAll = document.createElement('button');
59
52
  btnDeleteAll.className = 'btn btn-outline-danger btn-sm';
60
- btnDeleteAll.innerHTML = '';
53
+ btnDeleteAll.id = 'recordings-delete-all';
54
+ btnDeleteAll.style.display = 'none';
61
55
  btnDeleteAll.appendChild(Helpers.icon('delete.svg'));
62
- btnDeleteAll.append(' Delete All Recordings');
56
+ btnDeleteAll.append(' Delete All');
63
57
  btnDeleteAll.addEventListener('click', () => this._confirmDeleteAll(container));
64
58
 
65
- actionsRow.appendChild(btnDeleteAll);
66
- container.appendChild(actionsRow);
59
+ toolbar.appendChild(btnReload);
60
+ toolbar.appendChild(btnDeleteAll);
61
+ container.appendChild(toolbar);
62
+
63
+ // Recordings list container
64
+ const listContainer = document.createElement('div');
65
+ listContainer.id = 'recordings-list';
66
+ container.appendChild(listContainer);
67
67
 
68
68
  // Download progress area
69
69
  const progressArea = document.createElement('div');
@@ -75,17 +75,15 @@ const RecordingsView = {
75
75
  },
76
76
 
77
77
  async _loadRecordings(container) {
78
- const spinner = container.querySelector('#recordings-spinner');
79
78
  const listContainer = container.querySelector('#recordings-list');
80
- const actionsRow = container.querySelector('#recordings-actions');
79
+ const btnDeleteAll = container.querySelector('#recordings-delete-all');
81
80
 
82
81
  try {
83
82
  const result = await Api.listDebugRecordings();
84
83
  const recordings = result.recordings || [];
85
84
 
86
- if (spinner) spinner.style.display = 'none';
87
-
88
85
  if (recordings.length === 0) {
86
+ if (btnDeleteAll) btnDeleteAll.style.display = 'none';
89
87
  listContainer.innerHTML = `
90
88
  <div class="text-muted text-center py-4" style="font-size: 0.9rem;">
91
89
  No debug recordings found.<br>
@@ -95,7 +93,7 @@ const RecordingsView = {
95
93
  return;
96
94
  }
97
95
 
98
- if (actionsRow) actionsRow.style.display = '';
96
+ if (btnDeleteAll) btnDeleteAll.style.display = '';
99
97
 
100
98
  // Group by serial
101
99
  const grouped = {};
@@ -185,7 +183,6 @@ const RecordingsView = {
185
183
  listContainer.appendChild(section);
186
184
  }
187
185
  } catch (e) {
188
- if (spinner) spinner.style.display = 'none';
189
186
  listContainer.innerHTML = '<div class="alert alert-danger">Failed to load recordings: ' + Helpers.escHtml(e.message || String(e)) + '</div>';
190
187
  }
191
188
  },
@@ -246,15 +243,17 @@ const RecordingsView = {
246
243
  pos += chunk.length;
247
244
  }
248
245
 
249
- const blob = new Blob([combined], { type: 'video/mp4' });
250
- const url = URL.createObjectURL(blob);
246
+ let binary = '';
247
+ for (let i = 0; i < combined.length; i++) {
248
+ binary += String.fromCharCode(combined[i]);
249
+ }
250
+ const base64 = btoa(binary);
251
251
  const a = document.createElement('a');
252
- a.href = url;
252
+ a.href = 'data:application/octet-stream;base64,' + base64;
253
253
  a.download = filename;
254
254
  document.body.appendChild(a);
255
255
  a.click();
256
256
  document.body.removeChild(a);
257
- URL.revokeObjectURL(url);
258
257
 
259
258
  homebridge.toast.success('Downloaded: ' + filename);
260
259
  } catch (e) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "Homebridge Eufy Security",
3
3
  "name": "@homebridge-plugins/homebridge-eufy-security",
4
- "version": "4.6.0-beta.43",
4
+ "version": "4.6.0-beta.44",
5
5
  "description": "Control Eufy Security from homebridge.",
6
6
  "type": "module",
7
7
  "license": "Apache-2.0",