@homebridge-plugins/homebridge-eufy-security 4.7.2 → 5.0.0-beta.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.
Files changed (471) hide show
  1. package/AUTHORS +4 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +77 -0
  4. package/README.md +152 -49
  5. package/SECURITY.md +30 -0
  6. package/config.schema.json +92 -3
  7. package/dist/account/ownership.js +290 -0
  8. package/dist/account/ownership.js.map +1 -0
  9. package/dist/account/persistence.js +274 -0
  10. package/dist/account/persistence.js.map +1 -0
  11. package/dist/account/temporary-authentication.js +348 -0
  12. package/dist/account/temporary-authentication.js.map +1 -0
  13. package/dist/configuration.js +167 -0
  14. package/dist/configuration.js.map +1 -0
  15. package/dist/device/member-evidence.js +66 -0
  16. package/dist/device/member-evidence.js.map +1 -0
  17. package/dist/device/member-trust.js +114 -0
  18. package/dist/device/member-trust.js.map +1 -0
  19. package/dist/device/snapshot.js +190 -0
  20. package/dist/device/snapshot.js.map +1 -0
  21. package/dist/diagnostics.js +2218 -0
  22. package/dist/diagnostics.js.map +1 -0
  23. package/dist/homekit/adapter.js +2 -0
  24. package/dist/homekit/adapter.js.map +1 -0
  25. package/dist/homekit/adapters/battery.js +208 -0
  26. package/dist/homekit/adapters/battery.js.map +1 -0
  27. package/dist/homekit/adapters/camera-controls.js +527 -0
  28. package/dist/homekit/adapters/camera-controls.js.map +1 -0
  29. package/dist/homekit/adapters/camera-streaming.js +1515 -0
  30. package/dist/homekit/adapters/camera-streaming.js.map +1 -0
  31. package/dist/homekit/adapters/contact.js +138 -0
  32. package/dist/homekit/adapters/contact.js.map +1 -0
  33. package/dist/homekit/adapters/doorbell.js +57 -0
  34. package/dist/homekit/adapters/doorbell.js.map +1 -0
  35. package/dist/homekit/adapters/information.js +55 -0
  36. package/dist/homekit/adapters/information.js.map +1 -0
  37. package/dist/homekit/adapters/lock.js +489 -0
  38. package/dist/homekit/adapters/lock.js.map +1 -0
  39. package/dist/homekit/adapters/motion.js +100 -0
  40. package/dist/homekit/adapters/motion.js.map +1 -0
  41. package/dist/homekit/adapters/registry.js +26 -0
  42. package/dist/homekit/adapters/registry.js.map +1 -0
  43. package/dist/homekit/adapters/security-system.js +425 -0
  44. package/dist/homekit/adapters/security-system.js.map +1 -0
  45. package/dist/homekit/adapters/siren.js +136 -0
  46. package/dist/homekit/adapters/siren.js.map +1 -0
  47. package/dist/homekit/adapters/smart-light.js +662 -0
  48. package/dist/homekit/adapters/smart-light.js.map +1 -0
  49. package/dist/homekit/coverage-matrix.js +119 -0
  50. package/dist/homekit/coverage-matrix.js.map +1 -0
  51. package/dist/homekit/device-control.js +175 -0
  52. package/dist/homekit/device-control.js.map +1 -0
  53. package/dist/homekit/reconciler.js +319 -0
  54. package/dist/homekit/reconciler.js.map +1 -0
  55. package/dist/homekit/representation.js +23 -0
  56. package/dist/homekit/representation.js.map +1 -0
  57. package/dist/index.js +4 -9
  58. package/dist/index.js.map +1 -1
  59. package/dist/media/contracts.js +2 -0
  60. package/dist/media/contracts.js.map +1 -0
  61. package/dist/media/last-successful-image.js +208 -0
  62. package/dist/media/last-successful-image.js.map +1 -0
  63. package/dist/media/live-stream.js +1003 -0
  64. package/dist/media/live-stream.js.map +1 -0
  65. package/dist/media/recording.js +560 -0
  66. package/dist/media/recording.js.map +1 -0
  67. package/dist/media/session-budget.js +39 -0
  68. package/dist/media/session-budget.js.map +1 -0
  69. package/dist/media/snapshot.js +406 -0
  70. package/dist/media/snapshot.js.map +1 -0
  71. package/dist/media/station-live-sessions.js +101 -0
  72. package/dist/media/station-live-sessions.js.map +1 -0
  73. package/dist/platform.js +97 -809
  74. package/dist/platform.js.map +1 -1
  75. package/dist/runtime/channel.js +375 -0
  76. package/dist/runtime/channel.js.map +1 -0
  77. package/dist/runtime/owner.js +682 -0
  78. package/dist/runtime/owner.js.map +1 -0
  79. package/dist/runtime/sdk-client.js +211 -0
  80. package/dist/runtime/sdk-client.js.map +1 -0
  81. package/dist/runtime/tracker.js +211 -0
  82. package/dist/runtime/tracker.js.map +1 -0
  83. package/dist/settings.js +1 -43
  84. package/dist/settings.js.map +1 -1
  85. package/dist/storage.js +59 -0
  86. package/dist/storage.js.map +1 -0
  87. package/dist/ui/dashboard.js +181 -0
  88. package/dist/ui/dashboard.js.map +1 -0
  89. package/dist/ui/device-image.js +22 -0
  90. package/dist/ui/device-image.js.map +1 -0
  91. package/dist/ui/runtime-channel-client.js +305 -0
  92. package/dist/ui/runtime-channel-client.js.map +1 -0
  93. package/dist/ui/server.js +259 -0
  94. package/dist/ui/server.js.map +1 -0
  95. package/homebridge-ui/public/app.css +1902 -0
  96. package/homebridge-ui/public/assets/devices/clean/clean-T1250.webp +0 -0
  97. package/homebridge-ui/public/assets/devices/clean/clean-T2070.webp +0 -0
  98. package/homebridge-ui/public/assets/devices/clean/clean-T2080.webp +0 -0
  99. package/homebridge-ui/public/assets/devices/clean/clean-T2081.webp +0 -0
  100. package/homebridge-ui/public/assets/devices/clean/clean-T2103.webp +0 -0
  101. package/homebridge-ui/public/assets/devices/clean/clean-T2117.webp +0 -0
  102. package/homebridge-ui/public/assets/devices/clean/clean-T2118.webp +0 -0
  103. package/homebridge-ui/public/assets/devices/clean/clean-T2119.webp +0 -0
  104. package/homebridge-ui/public/assets/devices/clean/clean-T211A.webp +0 -0
  105. package/homebridge-ui/public/assets/devices/clean/clean-T2120.webp +0 -0
  106. package/homebridge-ui/public/assets/devices/clean/clean-T2123.webp +0 -0
  107. package/homebridge-ui/public/assets/devices/clean/clean-T2128.webp +0 -0
  108. package/homebridge-ui/public/assets/devices/clean/clean-T2130.webp +0 -0
  109. package/homebridge-ui/public/assets/devices/clean/clean-T2132.webp +0 -0
  110. package/homebridge-ui/public/assets/devices/clean/clean-T2150.webp +0 -0
  111. package/homebridge-ui/public/assets/devices/clean/clean-T2181.webp +0 -0
  112. package/homebridge-ui/public/assets/devices/clean/clean-T2182.webp +0 -0
  113. package/homebridge-ui/public/assets/devices/clean/clean-T2190.webp +0 -0
  114. package/homebridge-ui/public/assets/devices/clean/clean-T2192.webp +0 -0
  115. package/homebridge-ui/public/assets/devices/clean/clean-T2193.webp +0 -0
  116. package/homebridge-ui/public/assets/devices/clean/clean-T2194.webp +0 -0
  117. package/homebridge-ui/public/assets/devices/clean/clean-T2210.webp +0 -0
  118. package/homebridge-ui/public/assets/devices/clean/clean-T2250.webp +0 -0
  119. package/homebridge-ui/public/assets/devices/clean/clean-T2251.webp +0 -0
  120. package/homebridge-ui/public/assets/devices/clean/clean-T2252.webp +0 -0
  121. package/homebridge-ui/public/assets/devices/clean/clean-T2253.webp +0 -0
  122. package/homebridge-ui/public/assets/devices/clean/clean-T2254.webp +0 -0
  123. package/homebridge-ui/public/assets/devices/clean/clean-T2255.webp +0 -0
  124. package/homebridge-ui/public/assets/devices/clean/clean-T2256.webp +0 -0
  125. package/homebridge-ui/public/assets/devices/clean/clean-T2257.webp +0 -0
  126. package/homebridge-ui/public/assets/devices/clean/clean-T2258.webp +0 -0
  127. package/homebridge-ui/public/assets/devices/clean/clean-T2259.webp +0 -0
  128. package/homebridge-ui/public/assets/devices/clean/clean-T2261.webp +0 -0
  129. package/homebridge-ui/public/assets/devices/clean/clean-T2262.webp +0 -0
  130. package/homebridge-ui/public/assets/devices/clean/clean-T2266.webp +0 -0
  131. package/homebridge-ui/public/assets/devices/clean/clean-T2267.webp +0 -0
  132. package/homebridge-ui/public/assets/devices/clean/clean-T2268.webp +0 -0
  133. package/homebridge-ui/public/assets/devices/clean/clean-T2270.webp +0 -0
  134. package/homebridge-ui/public/assets/devices/clean/clean-T2272.webp +0 -0
  135. package/homebridge-ui/public/assets/devices/clean/clean-T2273.webp +0 -0
  136. package/homebridge-ui/public/assets/devices/clean/clean-T2276.webp +0 -0
  137. package/homebridge-ui/public/assets/devices/clean/clean-T2277.webp +0 -0
  138. package/homebridge-ui/public/assets/devices/clean/clean-T2278.webp +0 -0
  139. package/homebridge-ui/public/assets/devices/clean/clean-T2280.webp +0 -0
  140. package/homebridge-ui/public/assets/devices/clean/clean-T2292.webp +0 -0
  141. package/homebridge-ui/public/assets/devices/clean/clean-T2320.webp +0 -0
  142. package/homebridge-ui/public/assets/devices/clean/clean-T2351.webp +0 -0
  143. package/homebridge-ui/public/assets/devices/clean/clean-T2352.webp +0 -0
  144. package/homebridge-ui/public/assets/devices/clean/clean-T2353.webp +0 -0
  145. package/homebridge-ui/public/assets/devices/life/life-T8L00.webp +0 -0
  146. package/homebridge-ui/public/assets/devices/life/life-T8L01.webp +0 -0
  147. package/homebridge-ui/public/assets/devices/life/life-T8L02.webp +0 -0
  148. package/homebridge-ui/public/assets/devices/life/life-T8L04.webp +0 -0
  149. package/homebridge-ui/public/assets/devices/life/life-T8L10.webp +0 -0
  150. package/homebridge-ui/public/assets/devices/life/life-T8L20.webp +0 -0
  151. package/homebridge-ui/public/assets/devices/life/life-T8L30.webp +0 -0
  152. package/homebridge-ui/public/assets/devices/life/life-T8L40.webp +0 -0
  153. package/homebridge-ui/public/assets/devices/mower/mower-T2801.webp +0 -0
  154. package/homebridge-ui/public/assets/devices/mower/mower-T280B.webp +0 -0
  155. package/homebridge-ui/public/assets/devices/mower/mower-T2880.webp +0 -0
  156. package/homebridge-ui/public/assets/devices/security/security-T7400.webp +0 -0
  157. package/homebridge-ui/public/assets/devices/security/security-T7401.webp +0 -0
  158. package/homebridge-ui/public/assets/devices/security/security-T8001.webp +0 -0
  159. package/homebridge-ui/public/assets/devices/security/security-T8002.webp +0 -0
  160. package/homebridge-ui/public/assets/devices/security/security-T8010.webp +0 -0
  161. package/homebridge-ui/public/assets/devices/security/security-T8021.webp +0 -0
  162. package/homebridge-ui/public/assets/devices/security/security-T8023.webp +0 -0
  163. package/homebridge-ui/public/assets/devices/security/security-T8025.webp +0 -0
  164. package/homebridge-ui/public/assets/devices/security/security-T8030.webp +0 -0
  165. package/homebridge-ui/public/assets/devices/security/security-T8110.webp +0 -0
  166. package/homebridge-ui/public/assets/devices/security/security-T8111.webp +0 -0
  167. package/homebridge-ui/public/assets/devices/security/security-T8112.webp +0 -0
  168. package/homebridge-ui/public/assets/devices/security/security-T8113.webp +0 -0
  169. package/homebridge-ui/public/assets/devices/security/security-T8114.webp +0 -0
  170. package/homebridge-ui/public/assets/devices/security/security-T8122.webp +0 -0
  171. package/homebridge-ui/public/assets/devices/security/security-T8123.webp +0 -0
  172. package/homebridge-ui/public/assets/devices/security/security-T8124.webp +0 -0
  173. package/homebridge-ui/public/assets/devices/security/security-T8130.webp +0 -0
  174. package/homebridge-ui/public/assets/devices/security/security-T8131.webp +0 -0
  175. package/homebridge-ui/public/assets/devices/security/security-T8134.webp +0 -0
  176. package/homebridge-ui/public/assets/devices/security/security-T8140.webp +0 -0
  177. package/homebridge-ui/public/assets/devices/security/security-T8141.webp +0 -0
  178. package/homebridge-ui/public/assets/devices/security/security-T8150.webp +0 -0
  179. package/homebridge-ui/public/assets/devices/security/security-T8151.webp +0 -0
  180. package/homebridge-ui/public/assets/devices/security/security-T8152.webp +0 -0
  181. package/homebridge-ui/public/assets/devices/security/security-T8153.webp +0 -0
  182. package/homebridge-ui/public/assets/devices/security/security-T8160.webp +0 -0
  183. package/homebridge-ui/public/assets/devices/security/security-T8161.webp +0 -0
  184. package/homebridge-ui/public/assets/devices/security/security-T8162.webp +0 -0
  185. package/homebridge-ui/public/assets/devices/security/security-T8170.webp +0 -0
  186. package/homebridge-ui/public/assets/devices/security/security-T8171.webp +0 -0
  187. package/homebridge-ui/public/assets/devices/security/security-T8172.webp +0 -0
  188. package/homebridge-ui/public/assets/devices/security/security-T8173.webp +0 -0
  189. package/homebridge-ui/public/assets/devices/security/security-T8200.webp +0 -0
  190. package/homebridge-ui/public/assets/devices/security/security-T8200X.webp +0 -0
  191. package/homebridge-ui/public/assets/devices/security/security-T8201.webp +0 -0
  192. package/homebridge-ui/public/assets/devices/security/security-T8203.webp +0 -0
  193. package/homebridge-ui/public/assets/devices/security/security-T8210.webp +0 -0
  194. package/homebridge-ui/public/assets/devices/security/security-T8213.webp +0 -0
  195. package/homebridge-ui/public/assets/devices/security/security-T8214.webp +0 -0
  196. package/homebridge-ui/public/assets/devices/security/security-T8222.webp +0 -0
  197. package/homebridge-ui/public/assets/devices/security/security-T8400.webp +0 -0
  198. package/homebridge-ui/public/assets/devices/security/security-T8401.webp +0 -0
  199. package/homebridge-ui/public/assets/devices/security/security-T8410.webp +0 -0
  200. package/homebridge-ui/public/assets/devices/security/security-T8411.webp +0 -0
  201. package/homebridge-ui/public/assets/devices/security/security-T8414.webp +0 -0
  202. package/homebridge-ui/public/assets/devices/security/security-T8416.webp +0 -0
  203. package/homebridge-ui/public/assets/devices/security/security-T8417.webp +0 -0
  204. package/homebridge-ui/public/assets/devices/security/security-T8419.webp +0 -0
  205. package/homebridge-ui/public/assets/devices/security/security-T8419N.webp +0 -0
  206. package/homebridge-ui/public/assets/devices/security/security-T8420.webp +0 -0
  207. package/homebridge-ui/public/assets/devices/security/security-T8420X.webp +0 -0
  208. package/homebridge-ui/public/assets/devices/security/security-T8422.webp +0 -0
  209. package/homebridge-ui/public/assets/devices/security/security-T8423.webp +0 -0
  210. package/homebridge-ui/public/assets/devices/security/security-T8424.webp +0 -0
  211. package/homebridge-ui/public/assets/devices/security/security-T8425.webp +0 -0
  212. package/homebridge-ui/public/assets/devices/security/security-T8441.webp +0 -0
  213. package/homebridge-ui/public/assets/devices/security/security-T8442.webp +0 -0
  214. package/homebridge-ui/public/assets/devices/security/security-T8452.webp +0 -0
  215. package/homebridge-ui/public/assets/devices/security/security-T84A0.webp +0 -0
  216. package/homebridge-ui/public/assets/devices/security/security-T84A1.webp +0 -0
  217. package/homebridge-ui/public/assets/devices/security/security-T8500.webp +0 -0
  218. package/homebridge-ui/public/assets/devices/security/security-T8502.webp +0 -0
  219. package/homebridge-ui/public/assets/devices/security/security-T8503.webp +0 -0
  220. package/homebridge-ui/public/assets/devices/security/security-T8504.webp +0 -0
  221. package/homebridge-ui/public/assets/devices/security/security-T8506.webp +0 -0
  222. package/homebridge-ui/public/assets/devices/security/security-T8510.webp +0 -0
  223. package/homebridge-ui/public/assets/devices/security/security-T8510P.webp +0 -0
  224. package/homebridge-ui/public/assets/devices/security/security-T8520.webp +0 -0
  225. package/homebridge-ui/public/assets/devices/security/security-T8520P.webp +0 -0
  226. package/homebridge-ui/public/assets/devices/security/security-T8530.webp +0 -0
  227. package/homebridge-ui/public/assets/devices/security/security-T8531.webp +0 -0
  228. package/homebridge-ui/public/assets/devices/security/security-T85D0.webp +0 -0
  229. package/homebridge-ui/public/assets/devices/security/security-T85L0.webp +0 -0
  230. package/homebridge-ui/public/assets/devices/security/security-T85P0.webp +0 -0
  231. package/homebridge-ui/public/assets/devices/security/security-T85V0.webp +0 -0
  232. package/homebridge-ui/public/assets/devices/security/security-T8600.webp +0 -0
  233. package/homebridge-ui/public/assets/devices/security/security-T86P2.webp +0 -0
  234. package/homebridge-ui/public/assets/devices/security/security-T8790.webp +0 -0
  235. package/homebridge-ui/public/assets/devices/security/security-T87B0.webp +0 -0
  236. package/homebridge-ui/public/assets/devices/security/security-T87B2.webp +0 -0
  237. package/homebridge-ui/public/assets/devices/security/security-T8900.webp +0 -0
  238. package/homebridge-ui/public/assets/devices/security/security-T8910.webp +0 -0
  239. package/homebridge-ui/public/assets/devices/security/security-T8920.webp +0 -0
  240. package/homebridge-ui/public/assets/devices/security/security-T8960.webp +0 -0
  241. package/homebridge-ui/public/assets/devices/security/security-T8B0.webp +0 -0
  242. package/homebridge-ui/public/assets/devices/security/security-T8E00.webp +0 -0
  243. package/homebridge-ui/public/assets/devices/security/security-T8N00.webp +0 -0
  244. package/homebridge-ui/public/assets/devices/security/security-T8W11C.webp +0 -0
  245. package/homebridge-ui/public/assets/devices/security/security-T90F0.webp +0 -0
  246. package/homebridge-ui/public/assets/devices/security/security-T90M0.webp +0 -0
  247. package/homebridge-ui/public/assets/devices/security/security-T90R0.webp +0 -0
  248. package/homebridge-ui/public/assets/devices/security/security-T90S0.webp +0 -0
  249. package/homebridge-ui/public/assets/icons/inventory.svg +1 -1
  250. package/homebridge-ui/public/assets/icons/troubleshoot.svg +1 -0
  251. package/homebridge-ui/public/assets/icons/warning.svg +1 -1
  252. package/homebridge-ui/public/assets/logo-dark.svg +10 -0
  253. package/homebridge-ui/public/assets/logo.svg +10 -0
  254. package/homebridge-ui/public/i18n/en.json +218 -0
  255. package/homebridge-ui/public/i18n/fr.json +218 -0
  256. package/homebridge-ui/public/index.html +377 -28
  257. package/homebridge-ui/public/js/app.js +1065 -0
  258. package/homebridge-ui/public/js/dashboard.js +385 -0
  259. package/homebridge-ui/public/js/legacy-settings.js +37 -0
  260. package/homebridge-ui/public/js/profile-wizard.js +68 -0
  261. package/homebridge-ui/server.js +2 -1393
  262. package/i18n/runtime/en.json +100 -0
  263. package/media/Snapshot-Unavailable.jpg +0 -0
  264. package/media/Snapshot-black.jpg +0 -0
  265. package/media/camera-disabled.jpg +0 -0
  266. package/media/camera-offline.jpg +0 -0
  267. package/package.json +29 -24
  268. package/.claude/CLAUDE.md +0 -175
  269. package/.claude/PRD.md +0 -241
  270. package/.claude/docs/debug-recording-lessons.md +0 -91
  271. package/.claude/docs/hksv-recording-fix.md +0 -160
  272. package/.claude/skills/architect/SKILL.md +0 -76
  273. package/.claude/skills/developer/SKILL.md +0 -59
  274. package/.claude/skills/new-device-support/SKILL.md +0 -212
  275. package/.claude/skills/new-device-support/check-device.mjs +0 -363
  276. package/.claude/skills/new-device-support/map-properties.mjs +0 -450
  277. package/.claude/skills/new-device-support/verify-device.mjs +0 -272
  278. package/.claude/skills/planner/SKILL.md +0 -100
  279. package/.claude/skills/qa/SKILL.md +0 -79
  280. package/.claude/skills/support/SKILL.md +0 -175
  281. package/.prettierignore +0 -7
  282. package/.prettierrc.json +0 -7
  283. package/FUNDING.yml +0 -1
  284. package/dist/accessories/AutoSyncStationAccessory.js +0 -157
  285. package/dist/accessories/AutoSyncStationAccessory.js.map +0 -1
  286. package/dist/accessories/BaseAccessory.js +0 -261
  287. package/dist/accessories/BaseAccessory.js.map +0 -1
  288. package/dist/accessories/CameraAccessory.js +0 -459
  289. package/dist/accessories/CameraAccessory.js.map +0 -1
  290. package/dist/accessories/Device.js +0 -65
  291. package/dist/accessories/Device.js.map +0 -1
  292. package/dist/accessories/EntrySensorAccessory.js +0 -48
  293. package/dist/accessories/EntrySensorAccessory.js.map +0 -1
  294. package/dist/accessories/GarageDoorAccessory.js +0 -160
  295. package/dist/accessories/GarageDoorAccessory.js.map +0 -1
  296. package/dist/accessories/LockAccessory.js +0 -142
  297. package/dist/accessories/LockAccessory.js.map +0 -1
  298. package/dist/accessories/MotionSensorAccessory.js +0 -48
  299. package/dist/accessories/MotionSensorAccessory.js.map +0 -1
  300. package/dist/accessories/SmartDropAccessory.js +0 -141
  301. package/dist/accessories/SmartDropAccessory.js.map +0 -1
  302. package/dist/accessories/StationAccessory.js +0 -373
  303. package/dist/accessories/StationAccessory.js.map +0 -1
  304. package/dist/config.js +0 -26
  305. package/dist/config.js.map +0 -1
  306. package/dist/controller/DebugRecordingManager.js +0 -402
  307. package/dist/controller/DebugRecordingManager.js.map +0 -1
  308. package/dist/controller/LocalLivestreamManager.js +0 -371
  309. package/dist/controller/LocalLivestreamManager.js.map +0 -1
  310. package/dist/controller/recordingDelegate.js +0 -252
  311. package/dist/controller/recordingDelegate.js.map +0 -1
  312. package/dist/controller/snapshotDelegate.js +0 -348
  313. package/dist/controller/snapshotDelegate.js.map +0 -1
  314. package/dist/controller/streamingDelegate.js +0 -389
  315. package/dist/controller/streamingDelegate.js.map +0 -1
  316. package/dist/interfaces.js +0 -2
  317. package/dist/interfaces.js.map +0 -1
  318. package/dist/media/Snapshot-Unavailable.png +0 -0
  319. package/dist/media/Snapshot-Unavailable.xcf +0 -0
  320. package/dist/media/Snapshot-black.png +0 -0
  321. package/dist/media/camera-disabled.png +0 -0
  322. package/dist/media/camera-offline.png +0 -0
  323. package/dist/media/media/Snapshot-Unavailable.png +0 -0
  324. package/dist/media/media/Snapshot-Unavailable.xcf +0 -0
  325. package/dist/media/media/Snapshot-black.png +0 -0
  326. package/dist/media/media/camera-disabled.png +0 -0
  327. package/dist/media/media/camera-offline.png +0 -0
  328. package/dist/utils/Talkback.js +0 -162
  329. package/dist/utils/Talkback.js.map +0 -1
  330. package/dist/utils/accessoriesStore.js +0 -210
  331. package/dist/utils/accessoriesStore.js.map +0 -1
  332. package/dist/utils/configTypes.js +0 -38
  333. package/dist/utils/configTypes.js.map +0 -1
  334. package/dist/utils/ffmpeg.js +0 -1111
  335. package/dist/utils/ffmpeg.js.map +0 -1
  336. package/dist/utils/interfaces.js +0 -8
  337. package/dist/utils/interfaces.js.map +0 -1
  338. package/dist/utils/utils.js +0 -224
  339. package/dist/utils/utils.js.map +0 -1
  340. package/dist/version.js +0 -2
  341. package/dist/version.js.map +0 -1
  342. package/homebridge-eufy-security.png +0 -0
  343. package/homebridge-ui/diagnosticsCrypto.js +0 -112
  344. package/homebridge-ui/public/app.js +0 -237
  345. package/homebridge-ui/public/assets/devices/4g_lte_cam_s330_large.png +0 -0
  346. package/homebridge-ui/public/assets/devices/4g_lte_starlight_large.jpg +0 -0
  347. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C30.png +0 -0
  348. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C31.png +0 -0
  349. package/homebridge-ui/public/assets/devices/batterydoorbell1080p_large.jpg +0 -0
  350. package/homebridge-ui/public/assets/devices/batterydoorbell2k_large.png +0 -0
  351. package/homebridge-ui/public/assets/devices/batterydoorbell2kdual_large.jpg +0 -0
  352. package/homebridge-ui/public/assets/devices/batterydoorbell_e340_large.png +0 -0
  353. package/homebridge-ui/public/assets/devices/eufy-security-client.png +0 -0
  354. package/homebridge-ui/public/assets/devices/eufyCamS4_large.png +0 -0
  355. package/homebridge-ui/public/assets/devices/eufycam2_large.png +0 -0
  356. package/homebridge-ui/public/assets/devices/eufycam2c_large.jpg +0 -0
  357. package/homebridge-ui/public/assets/devices/eufycam2cpro_large.jpg +0 -0
  358. package/homebridge-ui/public/assets/devices/eufycam2pro_large.jpg +0 -0
  359. package/homebridge-ui/public/assets/devices/eufycam3_large.jpg +0 -0
  360. package/homebridge-ui/public/assets/devices/eufycam3c_large.jpg +0 -0
  361. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  362. package/homebridge-ui/public/assets/devices/eufycam_large.jpg +0 -0
  363. package/homebridge-ui/public/assets/devices/eufycame330_large.jpg +0 -0
  364. package/homebridge-ui/public/assets/devices/flood_freeze_sensor_e20_t90F0_large.png +0 -0
  365. package/homebridge-ui/public/assets/devices/floodlight2_large.jpg +0 -0
  366. package/homebridge-ui/public/assets/devices/floodlight2pro_large.jpg +0 -0
  367. package/homebridge-ui/public/assets/devices/floodlight_large.jpg +0 -0
  368. package/homebridge-ui/public/assets/devices/floodlightcame340_large.jpg +0 -0
  369. package/homebridge-ui/public/assets/devices/garage_camera_t8452_large.png +0 -0
  370. package/homebridge-ui/public/assets/devices/homebase2_large.png +0 -0
  371. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  372. package/homebridge-ui/public/assets/devices/homebase_large.jpg +0 -0
  373. package/homebridge-ui/public/assets/devices/homebasemini_large.png +0 -0
  374. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  375. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  376. package/homebridge-ui/public/assets/devices/indoorcamC220_t8419N_large.png +0 -0
  377. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  378. package/homebridge-ui/public/assets/devices/indoorcamc120_large.png +0 -0
  379. package/homebridge-ui/public/assets/devices/indoorcammini_large.jpg +0 -0
  380. package/homebridge-ui/public/assets/devices/indoorcamp24_large.png +0 -0
  381. package/homebridge-ui/public/assets/devices/indoorcams350_large.png +0 -0
  382. package/homebridge-ui/public/assets/devices/keypad_large.png +0 -0
  383. package/homebridge-ui/public/assets/devices/minibase_chime_T8023_large.jpg +0 -0
  384. package/homebridge-ui/public/assets/devices/motionsensor_large.png +0 -0
  385. package/homebridge-ui/public/assets/devices/nvr_s4_max_T8N00_large.png +0 -0
  386. package/homebridge-ui/public/assets/devices/pir_sensor_e20_large.png +0 -0
  387. package/homebridge-ui/public/assets/devices/poe_bullet_ptz_cam_s4_T8E00_large.png +0 -0
  388. package/homebridge-ui/public/assets/devices/sensor_large.png +0 -0
  389. package/homebridge-ui/public/assets/devices/siren_sensor_e20_large.png +0 -0
  390. package/homebridge-ui/public/assets/devices/smartdrop_t8790_large.png +0 -0
  391. package/homebridge-ui/public/assets/devices/smartlock_t8500_large.png +0 -0
  392. package/homebridge-ui/public/assets/devices/smartlock_t8500_wifibridge_large.jpg +0 -0
  393. package/homebridge-ui/public/assets/devices/smartlock_t8503_large.png +0 -0
  394. package/homebridge-ui/public/assets/devices/smartlock_t8504_large.jpg +0 -0
  395. package/homebridge-ui/public/assets/devices/smartlock_t8510P_t8520P_large.png +0 -0
  396. package/homebridge-ui/public/assets/devices/smartlock_t85D0_large.png +0 -0
  397. package/homebridge-ui/public/assets/devices/smartlock_t85L0_large.png +0 -0
  398. package/homebridge-ui/public/assets/devices/smartlock_t85P0_large.png +0 -0
  399. package/homebridge-ui/public/assets/devices/smartlock_t85V0_large.png +0 -0
  400. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8502_large.png +0 -0
  401. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8506_large.png +0 -0
  402. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8520_large.png +0 -0
  403. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_large.png +0 -0
  404. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_wifibridge_large.jpg +0 -0
  405. package/homebridge-ui/public/assets/devices/smartlock_video_t8530_large.png +0 -0
  406. package/homebridge-ui/public/assets/devices/smartlock_video_t8531_large.png +0 -0
  407. package/homebridge-ui/public/assets/devices/smartlockwifibridge_t8021_large.jpg +0 -0
  408. package/homebridge-ui/public/assets/devices/smartsafe_s10_t7400_large.png +0 -0
  409. package/homebridge-ui/public/assets/devices/smartsafe_s12_t7401_large.png +0 -0
  410. package/homebridge-ui/public/assets/devices/smarttrack_card_t87B2_large.png +0 -0
  411. package/homebridge-ui/public/assets/devices/smarttrack_link_t87B0_large.png +0 -0
  412. package/homebridge-ui/public/assets/devices/smoke_alarm_e10_t90S0_large.png +0 -0
  413. package/homebridge-ui/public/assets/devices/solocamc210_large.jpg +0 -0
  414. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  415. package/homebridge-ui/public/assets/devices/solocame20_large.jpg +0 -0
  416. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  417. package/homebridge-ui/public/assets/devices/solocame40_large.jpg +0 -0
  418. package/homebridge-ui/public/assets/devices/solocame42_large.png +0 -0
  419. package/homebridge-ui/public/assets/devices/solocaml20_large.jpg +0 -0
  420. package/homebridge-ui/public/assets/devices/solocams220_large.jpg +0 -0
  421. package/homebridge-ui/public/assets/devices/solocams340_large.png +0 -0
  422. package/homebridge-ui/public/assets/devices/solocams40_large.jpg +0 -0
  423. package/homebridge-ui/public/assets/devices/soloindoorcamc24_large.jpg +0 -0
  424. package/homebridge-ui/public/assets/devices/solooutdoorcamc22_large.png +0 -0
  425. package/homebridge-ui/public/assets/devices/solooutdoorcamc24_large.jpg +0 -0
  426. package/homebridge-ui/public/assets/devices/unknown.png +0 -0
  427. package/homebridge-ui/public/assets/devices/walllight_s100_large.png +0 -0
  428. package/homebridge-ui/public/assets/devices/walllight_s120_large.png +0 -0
  429. package/homebridge-ui/public/assets/devices/water_freeze_sensor_t8920_large.png +0 -0
  430. package/homebridge-ui/public/assets/devices/wireddoorbell1080p_large.jpg +0 -0
  431. package/homebridge-ui/public/assets/devices/wireddoorbell2k_large.png +0 -0
  432. package/homebridge-ui/public/assets/devices/wireddoorbelldual_large.jpg +0 -0
  433. package/homebridge-ui/public/assets/icons/attach.svg +0 -1
  434. package/homebridge-ui/public/assets/icons/battery_0.svg +0 -1
  435. package/homebridge-ui/public/assets/icons/battery_1.svg +0 -1
  436. package/homebridge-ui/public/assets/icons/battery_2.svg +0 -1
  437. package/homebridge-ui/public/assets/icons/battery_3.svg +0 -1
  438. package/homebridge-ui/public/assets/icons/battery_4.svg +0 -1
  439. package/homebridge-ui/public/assets/icons/battery_5.svg +0 -1
  440. package/homebridge-ui/public/assets/icons/battery_6.svg +0 -1
  441. package/homebridge-ui/public/assets/icons/copy.svg +0 -1
  442. package/homebridge-ui/public/assets/icons/delete.svg +0 -1
  443. package/homebridge-ui/public/assets/icons/download.svg +0 -1
  444. package/homebridge-ui/public/assets/icons/info.svg +0 -1
  445. package/homebridge-ui/public/assets/icons/refresh.svg +0 -1
  446. package/homebridge-ui/public/assets/icons/satellite_alt.svg +0 -1
  447. package/homebridge-ui/public/assets/icons/solar_power.svg +0 -1
  448. package/homebridge-ui/public/components/device-card.js +0 -174
  449. package/homebridge-ui/public/components/guard-modes.js +0 -88
  450. package/homebridge-ui/public/components/number-input.js +0 -121
  451. package/homebridge-ui/public/components/select.js +0 -73
  452. package/homebridge-ui/public/components/toggle.js +0 -68
  453. package/homebridge-ui/public/services/api.js +0 -250
  454. package/homebridge-ui/public/services/config.js +0 -144
  455. package/homebridge-ui/public/style.css +0 -818
  456. package/homebridge-ui/public/utils/countries.js +0 -73
  457. package/homebridge-ui/public/utils/device-images.js +0 -102
  458. package/homebridge-ui/public/utils/helpers.js +0 -115
  459. package/homebridge-ui/public/views/dashboard.js +0 -226
  460. package/homebridge-ui/public/views/device-detail.js +0 -654
  461. package/homebridge-ui/public/views/diagnostics.js +0 -402
  462. package/homebridge-ui/public/views/login.js +0 -650
  463. package/homebridge-ui/public/views/recordings.js +0 -319
  464. package/homebridge-ui/public/views/settings.js +0 -197
  465. package/homebridge-ui/public/views/unsupported-detail.js +0 -296
  466. package/media/Snapshot-Unavailable.png +0 -0
  467. package/media/Snapshot-Unavailable.xcf +0 -0
  468. package/media/Snapshot-black.png +0 -0
  469. package/media/camera-disabled.png +0 -0
  470. package/media/camera-offline.png +0 -0
  471. package/scripts/decrypt-diagnostics.mjs +0 -257
@@ -1,174 +0,0 @@
1
- /**
2
- * DeviceCard component — renders a single device/station card for the dashboard grid.
3
- *
4
- * Usage:
5
- * DeviceCard.render(container, {
6
- * device: { uniqueId, displayName, type, typename, ... },
7
- * isStation: false,
8
- * enabled: true,
9
- * onClick: (device) => { ... },
10
- * onToggle: (device, enabled) => { ... }
11
- * });
12
- */
13
- // eslint-disable-next-line no-unused-vars
14
- const DeviceCard = {
15
-
16
- /**
17
- * @param {HTMLElement} container
18
- * @param {object} opts
19
- * @param {object} opts.device - L_Device or L_Station data
20
- * @param {boolean} [opts.isStation]
21
- * @param {boolean} opts.enabled - whether device is enabled (not ignored)
22
- * @param {function} opts.onClick - callback(device)
23
- * @param {function} opts.onToggle - callback(device, enabled)
24
- * @returns {HTMLElement}
25
- */
26
- render(container, opts) {
27
- const d = opts.device;
28
- const isUnsupported = d.unsupported === true;
29
- const isIgnored = d.ignored === true;
30
- const isKeypad = d.isKeypad === true;
31
-
32
- const col = document.createElement('div');
33
- col.className = 'col-6 col-md-4 col-lg-3 mb-3';
34
-
35
- const card = document.createElement('div');
36
- card.className = 'device-card';
37
- if (isUnsupported) card.classList.add('device-card--unsupported');
38
- if (isIgnored) card.classList.add('device-card--ignored');
39
-
40
- // Image (skip for unsupported)
41
- if (!isUnsupported) {
42
- const imgWrap = document.createElement('div');
43
- imgWrap.className = 'device-card__image-wrap';
44
- const img = document.createElement('img');
45
- img.src = DeviceImages.getPath(d.type);
46
- img.alt = d.displayName;
47
- img.loading = 'lazy';
48
- imgWrap.appendChild(img);
49
- card.appendChild(imgWrap);
50
- }
51
-
52
- // Body
53
- const body = document.createElement('div');
54
- body.className = 'device-card__body';
55
-
56
- const name = document.createElement('div');
57
- name.className = 'device-card__name';
58
- name.textContent = d.displayName;
59
- name.title = d.displayName;
60
-
61
- // Meta row: left side = battery/charging info, right side = toggle
62
- const metaRow = document.createElement('div');
63
- metaRow.className = 'device-card__meta-row';
64
-
65
- const meta = document.createElement('div');
66
- meta.className = 'device-card__meta';
67
-
68
- // Build meta line with DOM nodes so we can mix text and SVG icons
69
- const metaFragments = [];
70
- if (isUnsupported) {
71
- metaFragments.push('Type ' + d.type);
72
- }
73
-
74
- // Power info (pre-computed by server)
75
- const pw = d.power || {};
76
- if (pw.battery !== undefined) {
77
- metaFragments.push({ icon: Helpers.batteryIcon(pw.battery), text: pw.battery + '%' });
78
- } else if (pw.batteryLow === true) {
79
- metaFragments.push({ icon: Helpers.batteryIcon(0), text: 'Low' });
80
- } else if (pw.batteryLow === false) {
81
- metaFragments.push({ icon: Helpers.batteryIcon(100), text: 'OK' });
82
- }
83
- if (pw.icon && pw.label) {
84
- metaFragments.push({ icon: pw.icon, text: pw.label });
85
- }
86
- metaFragments.forEach((frag, i) => {
87
- if (i > 0) meta.append(' · ');
88
- if (typeof frag === 'string') {
89
- meta.append(frag);
90
- } else {
91
- meta.appendChild(Helpers.icon(frag.icon, 14, frag.text));
92
- meta.append(' ' + frag.text);
93
- }
94
- });
95
-
96
- metaRow.appendChild(meta);
97
-
98
- // Toggle — inline with meta, only for non-unsupported, non-keypad devices
99
- if (!isUnsupported && !isKeypad) {
100
- const switchWrap = document.createElement('div');
101
- switchWrap.className = 'form-check form-switch mb-0';
102
- switchWrap.addEventListener('click', (e) => e.stopPropagation());
103
-
104
- const toggle = document.createElement('input');
105
- toggle.type = 'checkbox';
106
- toggle.className = 'form-check-input';
107
- toggle.checked = opts.enabled;
108
- toggle.role = 'switch';
109
- toggle.title = opts.enabled ? 'Enabled in HomeKit' : 'Disabled in HomeKit';
110
-
111
- toggle.addEventListener('change', (e) => {
112
- e.stopPropagation();
113
- if (opts.onToggle) opts.onToggle(d, toggle.checked);
114
- });
115
-
116
- switchWrap.appendChild(toggle);
117
- metaRow.appendChild(switchWrap);
118
- }
119
-
120
- body.appendChild(name);
121
- body.appendChild(metaRow);
122
-
123
- // Footer with badges (unsupported / disabled)
124
- const footer = document.createElement('div');
125
- footer.className = 'device-card__footer';
126
-
127
- const badgeArea = document.createElement('div');
128
- let hasBadge = false;
129
-
130
- if (isKeypad) {
131
- const badge = document.createElement('span');
132
- badge.className = 'badge bg-secondary';
133
- badge.textContent = 'Not available for HomeKit';
134
- badgeArea.appendChild(badge);
135
- hasBadge = true;
136
- } else if (isUnsupported) {
137
- const badge = document.createElement('span');
138
- badge.className = 'badge badge-unsupported';
139
- badge.textContent = 'Not Supported';
140
- badgeArea.appendChild(badge);
141
-
142
- const hint = document.createElement('div');
143
- hint.className = 'device-card__hint';
144
- hint.textContent = 'Click to help us add support';
145
- badgeArea.appendChild(hint);
146
- hasBadge = true;
147
- } else if (isIgnored) {
148
- const badge = document.createElement('span');
149
- badge.className = 'badge bg-secondary';
150
- badge.textContent = 'Disabled';
151
- badgeArea.appendChild(badge);
152
- hasBadge = true;
153
- }
154
-
155
- footer.appendChild(badgeArea);
156
-
157
- card.appendChild(body);
158
- if (hasBadge) card.appendChild(footer);
159
-
160
- // Click handler — navigate to detail (disabled for keypads)
161
- if (isKeypad) {
162
- card.style.cursor = 'default';
163
- card.title = 'Keypads have no configurable HomeKit settings. The keypad works alongside your station but cannot be exposed to HomeKit.';
164
- } else {
165
- card.addEventListener('click', () => {
166
- if (opts.onClick) opts.onClick(d);
167
- });
168
- }
169
-
170
- col.appendChild(card);
171
- if (container) container.appendChild(col);
172
- return col;
173
- },
174
- };
@@ -1,88 +0,0 @@
1
- /**
2
- * Guard Modes mapping component.
3
- * Maps HomeKit modes (Home, Away, Night, Off) to Eufy guard mode numbers.
4
- *
5
- * Usage:
6
- * GuardModes.render(container, {
7
- * hkHome: 1, hkAway: 0, hkNight: 1, hkOff: 63,
8
- * onChange: (modes) => { ... } // { hkHome, hkAway, hkNight, hkOff }
9
- * });
10
- */
11
- // eslint-disable-next-line no-unused-vars
12
- const GuardModes = {
13
- EUFY_MODES: [
14
- { value: '0', label: 'Away' },
15
- { value: '1', label: 'Home' },
16
- { value: '2', label: 'Schedule' },
17
- { value: '3', label: 'Custom 1' },
18
- { value: '4', label: 'Custom 2' },
19
- { value: '5', label: 'Custom 3' },
20
- { value: '6', label: 'Off' },
21
- { value: '47', label: 'Geofencing' },
22
- { value: '63', label: 'Disarmed' },
23
- ],
24
-
25
- /**
26
- * @param {HTMLElement} container
27
- * @param {object} opts
28
- * @param {number} [opts.hkHome]
29
- * @param {number} [opts.hkAway]
30
- * @param {number} [opts.hkNight]
31
- * @param {number} [opts.hkOff]
32
- * @param {boolean} [opts.disabled]
33
- * @param {function} opts.onChange - callback({ hkHome, hkAway, hkNight, hkOff })
34
- * @returns {HTMLElement}
35
- */
36
- render(container, opts) {
37
- const wrap = document.createElement('div');
38
- wrap.className = 'guard-mode-grid';
39
-
40
- const modes = {
41
- hkHome: { label: 'HomeKit Home', value: opts.hkHome ?? 1 },
42
- hkAway: { label: 'HomeKit Away', value: opts.hkAway ?? 0 },
43
- hkNight: { label: 'HomeKit Night', value: opts.hkNight ?? 1 },
44
- hkOff: { label: 'HomeKit Off', value: opts.hkOff ?? 63 },
45
- };
46
-
47
- const currentValues = {
48
- hkHome: modes.hkHome.value,
49
- hkAway: modes.hkAway.value,
50
- hkNight: modes.hkNight.value,
51
- hkOff: modes.hkOff.value,
52
- };
53
-
54
- Object.entries(modes).forEach(([key, mode]) => {
55
- const group = document.createElement('div');
56
- group.className = 'form-group';
57
-
58
- const label = document.createElement('label');
59
- label.textContent = mode.label;
60
- label.setAttribute('for', 'guard-' + key);
61
-
62
- const select = document.createElement('select');
63
- select.className = 'form-select form-select-sm';
64
- select.id = 'guard-' + key;
65
- select.disabled = !!opts.disabled;
66
-
67
- this.EUFY_MODES.forEach((em) => {
68
- const option = document.createElement('option');
69
- option.value = em.value;
70
- option.textContent = em.label;
71
- if (String(em.value) === String(mode.value)) option.selected = true;
72
- select.appendChild(option);
73
- });
74
-
75
- select.addEventListener('change', () => {
76
- currentValues[key] = parseInt(select.value);
77
- if (opts.onChange) opts.onChange({ ...currentValues });
78
- });
79
-
80
- group.appendChild(label);
81
- group.appendChild(select);
82
- wrap.appendChild(group);
83
- });
84
-
85
- if (container) container.appendChild(wrap);
86
- return wrap;
87
- },
88
- };
@@ -1,121 +0,0 @@
1
- /**
2
- * NumberInput component — renders a number input with +/- buttons, label, and optional help tooltip.
3
- *
4
- * Usage:
5
- * NumberInput.render(container, {
6
- * id: 'polling-interval',
7
- * label: 'Polling Interval',
8
- * help: 'Minutes between cloud polls',
9
- * value: 10,
10
- * min: 1,
11
- * max: 120,
12
- * step: 1,
13
- * suffix: 'min',
14
- * onChange: (value) => { ... }
15
- * });
16
- */
17
- // eslint-disable-next-line no-unused-vars
18
- const NumberInput = {
19
- /**
20
- * @param {HTMLElement} container
21
- * @param {object} opts
22
- * @param {string} opts.id
23
- * @param {string} opts.label
24
- * @param {string} [opts.help]
25
- * @param {number} opts.value
26
- * @param {number} [opts.min]
27
- * @param {number} [opts.max]
28
- * @param {number} [opts.step]
29
- * @param {string} [opts.suffix] - text after the input (e.g., 'min', 'sec')
30
- * @param {boolean} [opts.disabled]
31
- * @param {function} opts.onChange - callback(value: number)
32
- * @returns {HTMLElement}
33
- */
34
- render(container, opts) {
35
- const row = document.createElement('div');
36
- row.className = 'eufy-toggle';
37
-
38
- const labelWrap = document.createElement('div');
39
- labelWrap.className = 'eufy-toggle__label';
40
-
41
- const labelEl = document.createElement('label');
42
- labelEl.setAttribute('for', opts.id);
43
- labelEl.textContent = opts.label;
44
- labelWrap.appendChild(labelEl);
45
-
46
- if (opts.help) {
47
- const helpEl = document.createElement('span');
48
- helpEl.className = 'eufy-toggle__help';
49
- helpEl.textContent = '?';
50
- helpEl.title = opts.help;
51
- labelWrap.appendChild(helpEl);
52
- }
53
-
54
- const inputGroup = document.createElement('div');
55
- inputGroup.className = 'number-input-group';
56
-
57
- const step = opts.step || 1;
58
- const min = opts.min !== undefined ? opts.min : 0;
59
- const max = opts.max !== undefined ? opts.max : 99999;
60
-
61
- const btnMinus = document.createElement('button');
62
- btnMinus.type = 'button';
63
- btnMinus.className = 'btn btn-outline-secondary btn-sm';
64
- btnMinus.textContent = '−';
65
-
66
- const input = document.createElement('input');
67
- input.type = 'number';
68
- input.className = 'form-control form-control-sm';
69
- input.id = opts.id;
70
- input.value = opts.value;
71
- input.min = min;
72
- input.max = max;
73
- input.step = step;
74
- input.disabled = !!opts.disabled;
75
-
76
- const btnPlus = document.createElement('button');
77
- btnPlus.type = 'button';
78
- btnPlus.className = 'btn btn-outline-secondary btn-sm';
79
- btnPlus.textContent = '+';
80
-
81
- const fireChange = () => {
82
- let val = parseFloat(input.value);
83
- if (isNaN(val)) val = min;
84
- val = Math.max(min, Math.min(max, val));
85
- input.value = val;
86
- if (opts.onChange) opts.onChange(val);
87
- };
88
-
89
- btnMinus.addEventListener('click', () => {
90
- let val = parseFloat(input.value) - step;
91
- input.value = Math.max(min, val);
92
- fireChange();
93
- });
94
-
95
- btnPlus.addEventListener('click', () => {
96
- let val = parseFloat(input.value) + step;
97
- input.value = Math.min(max, val);
98
- fireChange();
99
- });
100
-
101
- input.addEventListener('change', fireChange);
102
-
103
- inputGroup.appendChild(btnMinus);
104
- inputGroup.appendChild(input);
105
- inputGroup.appendChild(btnPlus);
106
-
107
- if (opts.suffix) {
108
- const suffixEl = document.createElement('span');
109
- suffixEl.className = 'text-muted ms-1';
110
- suffixEl.style.fontSize = '0.8rem';
111
- suffixEl.textContent = opts.suffix;
112
- inputGroup.appendChild(suffixEl);
113
- }
114
-
115
- row.appendChild(labelWrap);
116
- row.appendChild(inputGroup);
117
-
118
- if (container) container.appendChild(row);
119
- return row;
120
- },
121
- };
@@ -1,73 +0,0 @@
1
- /**
2
- * Select component — renders a dropdown with label and optional help tooltip.
3
- *
4
- * Usage:
5
- * Select.render(container, {
6
- * id: 'snapshot-method',
7
- * label: 'Snapshot Method',
8
- * help: 'How snapshots are captured',
9
- * options: [{ value: '0', label: 'Auto' }, { value: '1', label: 'From Stream' }],
10
- * value: '0',
11
- * onChange: (value) => { ... }
12
- * });
13
- */
14
- // eslint-disable-next-line no-unused-vars
15
- const Select = {
16
- /**
17
- * @param {HTMLElement} container
18
- * @param {object} opts
19
- * @param {string} opts.id
20
- * @param {string} opts.label
21
- * @param {string} [opts.help]
22
- * @param {Array<{value: string, label: string}>} opts.options
23
- * @param {string} opts.value - initial selected value
24
- * @param {boolean} [opts.disabled]
25
- * @param {function} opts.onChange - callback(value: string)
26
- * @returns {HTMLElement}
27
- */
28
- render(container, opts) {
29
- const row = document.createElement('div');
30
- row.className = 'eufy-toggle';
31
-
32
- const labelWrap = document.createElement('div');
33
- labelWrap.className = 'eufy-toggle__label';
34
-
35
- const labelEl = document.createElement('label');
36
- labelEl.setAttribute('for', opts.id);
37
- labelEl.textContent = opts.label;
38
- labelWrap.appendChild(labelEl);
39
-
40
- if (opts.help) {
41
- const helpEl = document.createElement('span');
42
- helpEl.className = 'eufy-toggle__help';
43
- helpEl.textContent = '?';
44
- helpEl.title = opts.help;
45
- labelWrap.appendChild(helpEl);
46
- }
47
-
48
- const selectEl = document.createElement('select');
49
- selectEl.className = 'form-select form-select-sm';
50
- selectEl.id = opts.id;
51
- selectEl.style.width = 'auto';
52
- selectEl.style.maxWidth = '200px';
53
- selectEl.disabled = !!opts.disabled;
54
-
55
- (opts.options || []).forEach((opt) => {
56
- const option = document.createElement('option');
57
- option.value = opt.value;
58
- option.textContent = opt.label;
59
- if (String(opt.value) === String(opts.value)) option.selected = true;
60
- selectEl.appendChild(option);
61
- });
62
-
63
- selectEl.addEventListener('change', () => {
64
- if (opts.onChange) opts.onChange(selectEl.value);
65
- });
66
-
67
- row.appendChild(labelWrap);
68
- row.appendChild(selectEl);
69
-
70
- if (container) container.appendChild(row);
71
- return row;
72
- },
73
- };
@@ -1,68 +0,0 @@
1
- /**
2
- * Toggle component — renders an on/off switch with label and optional help tooltip.
3
- *
4
- * Usage:
5
- * Toggle.render(container, {
6
- * id: 'enable-camera',
7
- * label: 'Enable Camera',
8
- * help: 'Show this camera in HomeKit',
9
- * checked: true,
10
- * onChange: (checked) => { ... }
11
- * });
12
- */
13
- // eslint-disable-next-line no-unused-vars
14
- const Toggle = {
15
- /**
16
- * @param {HTMLElement} container - parent element to append into
17
- * @param {object} opts
18
- * @param {string} opts.id - unique id for the input
19
- * @param {string} opts.label - display label
20
- * @param {string} [opts.help] - tooltip text
21
- * @param {boolean} opts.checked - initial state
22
- * @param {boolean} [opts.disabled] - disabled state
23
- * @param {function} opts.onChange - callback(checked: boolean)
24
- * @returns {HTMLElement}
25
- */
26
- render(container, opts) {
27
- const row = document.createElement('div');
28
- row.className = 'eufy-toggle';
29
-
30
- const labelWrap = document.createElement('div');
31
- labelWrap.className = 'eufy-toggle__label';
32
-
33
- const labelEl = document.createElement('label');
34
- labelEl.setAttribute('for', opts.id);
35
- labelEl.textContent = opts.label;
36
- labelWrap.appendChild(labelEl);
37
-
38
- if (opts.help) {
39
- const helpEl = document.createElement('span');
40
- helpEl.className = 'eufy-toggle__help';
41
- helpEl.textContent = '?';
42
- helpEl.title = opts.help;
43
- labelWrap.appendChild(helpEl);
44
- }
45
-
46
- const switchWrap = document.createElement('div');
47
- switchWrap.className = 'form-check form-switch mb-0';
48
-
49
- const input = document.createElement('input');
50
- input.type = 'checkbox';
51
- input.className = 'form-check-input';
52
- input.id = opts.id;
53
- input.checked = !!opts.checked;
54
- input.disabled = !!opts.disabled;
55
- input.role = 'switch';
56
-
57
- input.addEventListener('change', () => {
58
- if (opts.onChange) opts.onChange(input.checked);
59
- });
60
-
61
- switchWrap.appendChild(input);
62
- row.appendChild(labelWrap);
63
- row.appendChild(switchWrap);
64
-
65
- if (container) container.appendChild(row);
66
- return row;
67
- },
68
- };