From 782d69bcb9f09e55681b6a34caa78c9dc2bbbbbf Mon Sep 17 00:00:00 2001 From: Suthep Yonphimai Date: Sun, 1 Jun 2025 02:31:53 +0700 Subject: [PATCH 01/40] updates to the `th.json` language file (#2443) --- ui/src/i18n/th.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index f739f59ed..7e16666b9 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -13,9 +13,9 @@ "accessories.button_remove": "ลบออกจากแคช", "accessories.control.auto": "อัตโนมัติ", "accessories.control.away": "ห่างออกไป", - "accessories.control.battery_charged": "Charged", + "accessories.control.battery_charged": "ชาร์จแล้ว", "accessories.control.battery_charging": "กำลังชาร์จ", - "accessories.control.battery_low": "Battery Low", + "accessories.control.battery_low": "แบตเตอรี่ใกล้หมด", "accessories.control.battery_notchargeable": "ไม่สามารถชาร์จได้", "accessories.control.battery_notcharging": "ไม่ชาร์จ", "accessories.control.brightness": "ความสว่าง", @@ -24,14 +24,14 @@ "accessories.control.color_temperature": "อุณหภูมิสี", "accessories.control.cool": "ความเย็น", "accessories.control.default_room": "ห้องเริ่มต้น", - "accessories.control.dehumidify": "Dehumidify", + "accessories.control.dehumidify": "ลดความชื้น", "accessories.control.detected": "ตรวจพบ", "accessories.control.drag_here": "ลากมาที่นี่", "accessories.control.heat": "ความร้อน", "accessories.control.home": "บ้าน", - "accessories.control.humidify": "Humidify", + "accessories.control.humidify": "เพิ่มความชื้น", "accessories.control.jammed": "ติดขัดอยู่", - "accessories.control.lock_auto": "Auto Lock Timer", + "accessories.control.lock_auto": "ตั้งเวลาในการล็อกอัตโนมัติ", "accessories.control.locked": "ล็อกแล้ว", "accessories.control.mute": "ปิดเสียง", "accessories.control.night": "กลางคืน", @@ -50,7 +50,7 @@ "accessories.control.speaker_volume": "ระดับเสียง", "accessories.control.stopped": "หยุดแล้ว", "accessories.control.target": "เป้าหมาย", - "accessories.control.target_auto": "Auto Target", + "accessories.control.target_auto": "เป้าหมายอัตโนมัติ", "accessories.control.triggered": "ทริกเกอร์แล้ว", "accessories.control.unknown": "ไม่ทราบ", "accessories.control.unlocked": "ปลดล๊อคแล้ว", @@ -175,7 +175,7 @@ "logs.title_truncate_log_file": "ตัดทอนไฟล์บันทึก", "logs.truncate.error": "ไม่สามารถตัดทอนไฟล์ log ได้", "logs.truncate_log_warning": "การดำเนินการนี้จะลบบันทึก Homebridge ที่มีอยู่ของคุณอย่างไม่สามารถย้อนกลับได้ แน่ใจไหมว่าต้องการดำเนินการต่อ", - "menu.config_json_editor": "JSON Config", + "menu.config_json_editor": "คอนฟิก JSON", "menu.docker.restart_container": "รีสตาร์ทคอนเทนเนอร์", "menu.docker.startup_script": "สคริปต์เริ่มต้น", "menu.docker.terminal": "เทอร์มินอล", From d6a128d5903c019083ef81d1bc49fc4a3ecbf683 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 31 May 2025 21:23:04 +0100 Subject: [PATCH 02/40] improvements to various accessory tiles and modals --- CHANGELOG.md | 17 ++- package-lock.json | 75 ++++++------ package.json | 4 +- src/modules/backup/backup.service.ts | 6 +- ui/package-lock.json | 100 ++++++++-------- ui/package.json | 2 +- .../airpurifier.manage.component.html | 39 +++++- .../airpurifier.manage.component.ts | 40 +++++-- .../types/battery/battery.component.html | 11 +- .../types/battery/battery.component.scss | 11 +- .../types/door/door.component.html | 5 +- .../types/door/door.manage.component.html | 42 +++++-- .../types/door/door.manage.component.ts | 17 ++- .../types/fan/fan.manage.component.html | 29 +++-- .../types/fan/fan.manage.component.ts | 12 +- .../types/fanv2/fanv2.manage.component.html | 29 +++-- .../types/fanv2/fanv2.manage.component.ts | 14 ++- .../heatercooler.manage.component.html | 12 +- .../heatercooler.manage.component.ts | 5 +- ...midifierdehumidifier.manage.component.html | 13 +- ...humidifierdehumidifier.manage.component.ts | 5 +- .../types/lightbulb/lightbulb.component.html | 8 +- .../types/lightbulb/lightbulb.component.ts | 57 ++++++++- .../lightbulb/lightbulb.manage.component.html | 44 ++++++- .../lightbulb/lightbulb.manage.component.ts | 111 ++++++++++++++---- .../lockmechanism.manage.component.html | 1 - .../securitysystem.manage.component.html | 2 - .../speaker/speaker.manage.component.html | 1 - .../types/speaker/speaker.manage.component.ts | 10 +- .../television/television.component.html | 9 +- .../types/television/television.component.ts | 22 +++- .../television.manage.component.html | 69 +++++++++++ .../television/television.manage.component.ts | 52 ++++++++ .../thermostat/thermostat.component.scss | 32 +++++ .../thermostat.manage.component.html | 54 ++++++++- .../thermostat/thermostat.manage.component.ts | 43 ++++++- .../types/valve/valve.manage.component.html | 1 - .../types/window/window.component.html | 5 +- .../types/window/window.manage.component.html | 42 +++++-- .../types/window/window.manage.component.ts | 17 ++- .../windowcovering.component.html | 5 +- .../windowcovering.manage.component.html | 42 +++++-- .../windowcovering.manage.component.ts | 17 ++- ui/src/i18n/bg.json | 8 ++ ui/src/i18n/ca.json | 8 ++ ui/src/i18n/cs.json | 8 ++ ui/src/i18n/de.json | 8 ++ ui/src/i18n/en.json | 8 ++ ui/src/i18n/es.json | 8 ++ ui/src/i18n/fi.json | 8 ++ ui/src/i18n/fr.json | 8 ++ ui/src/i18n/he.json | 8 ++ ui/src/i18n/hu.json | 8 ++ ui/src/i18n/id.json | 8 ++ ui/src/i18n/it.json | 8 ++ ui/src/i18n/ja.json | 8 ++ ui/src/i18n/ko.json | 8 ++ ui/src/i18n/mk.json | 8 ++ ui/src/i18n/nl.json | 8 ++ ui/src/i18n/no.json | 8 ++ ui/src/i18n/pl.json | 8 ++ ui/src/i18n/pt-BR.json | 8 ++ ui/src/i18n/pt.json | 8 ++ ui/src/i18n/ru.json | 8 ++ ui/src/i18n/sl.json | 8 ++ ui/src/i18n/sv.json | 8 ++ ui/src/i18n/th.json | 8 ++ ui/src/i18n/tr.json | 8 ++ ui/src/i18n/uk.json | 8 ++ ui/src/i18n/zh-CN.json | 8 ++ ui/src/i18n/zh-TW.json | 8 ++ ui/src/scss/base/buttons.scss | 21 ++++ ui/src/scss/base/form.scss | 6 +- ui/src/scss/base/layout.scss | 8 ++ ui/src/scss/themes/themes-dark.scss | 6 + 75 files changed, 1135 insertions(+), 262 deletions(-) create mode 100644 ui/src/app/core/accessories/types/television/television.manage.component.html create mode 100644 ui/src/app/core/accessories/types/television/television.manage.component.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c3160ebb..be6fc8a60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.75.0 (2025-05-25) +## v4.76.0 (Unreleased) ### ⚠️ Upcoming Deprecations: @@ -12,7 +12,20 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - Drop support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) - Drop support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware - Drop support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) -- Note that these are not requirements for UI `v4.75.0` +- Note that these are not requirements for UI `v4.76.0` + +### UI Changes + +- updates to the `th.json` language file (#2443) (@tomzt) +- improvements to various accessory tiles and modals + +### Homebridge Dependencies + +- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` +- `@homebridge/plugin-ui-utils` @ `v2.0.2` + +## v4.75.0 (2025-05-25) ### UI Changes diff --git a/package-lock.json b/package-lock.json index c5a0c19ee..2b21b74c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.1.0", + "@homebridge/hap-client": "2.2.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", "@nestjs/common": "10.4.17", @@ -53,7 +53,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.0", + "systeminformation": "5.27.1", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", @@ -1330,29 +1330,18 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.1.0.tgz", - "integrity": "sha512-8OpTYaC9McLAWoY6vv8CmYMZ+RnJbsOh8Tc9rGgeuHE3x+Tx+T0hh2B726WAZ5VEgoUNKY8oP+7Zfo/2qQ7SHw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", + "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", "license": "MIT", "dependencies": { - "axios": "1.8.4", + "axios": "1.9.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", "source-map-support": "0.5.21" } }, - "node_modules/@homebridge/hap-client/node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/@homebridge/node-pty-prebuilt-multiarch": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@homebridge/node-pty-prebuilt-multiarch/-/node-pty-prebuilt-multiarch-0.11.14.tgz", @@ -5425,16 +5414,28 @@ } }, "node_modules/eslint-import-context": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.3.tgz", - "integrity": "sha512-dmdfEU9i8EgxV7jR9IAeiC6mp22wNfclhs33D8zctPYiclQhq61idm/Q4VJv00SPvqLWTokvN5lDyNkuQZYzUg==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.5.tgz", + "integrity": "sha512-jalO1mLiEvTv0io0koz1AE4LwkHQxDBFLaSXWweWtJR0y/NC1yyxvU61Z54bghIFNeM1M4TvwRwVRhLunQJ3gw==", "dev": true, "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash": "^0.0.5" + }, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } } }, "node_modules/eslint-import-resolver-node": { @@ -5591,23 +5592,23 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.13.0.tgz", - "integrity": "sha512-YtbaFHEQYGvR9zPuI525UhwPKEK0sXAvPyHKBUZYadJeIhD6UIuQE60Fje4q5nP17fkhzxjECrFV20nSdLrQtg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.13.1.tgz", + "integrity": "sha512-Ua4HZBmG5TNr18q3Is+nT6mKCzNNpycqtv/+TkIK7E3w4LBlPlZI6vLwmDjXdIZtJPP2Z1Oh5+wksWwlcCjMpA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.31.0", + "@typescript-eslint/utils": "^8.32.1", "comment-parser": "^1.4.1", - "debug": "^4.4.0", - "eslint-import-context": "^0.1.3", + "debug": "^4.4.1", + "eslint-import-context": "^0.1.4", "eslint-import-resolver-node": "^0.3.9", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", - "semver": "^7.7.1", + "semver": "^7.7.2", "stable-hash": "^0.0.5", "tslib": "^2.8.1", - "unrs-resolver": "^1.7.0" + "unrs-resolver": "^1.7.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6758,9 +6759,9 @@ "peer": true }, "node_modules/globals": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", - "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", + "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", "dev": true, "license": "MIT", "engines": { @@ -10885,9 +10886,9 @@ } }, "node_modules/systeminformation": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.0.tgz", - "integrity": "sha512-zGORCUwHh9XoDK92HO/2jZT2Kj1sEU1t62iRpk3RDXVs4Af7QE/ot4cZ3I3XO0q6SmOIiZjCGHZM0zzqbUHGcA==", + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.1.tgz", + "integrity": "sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==", "license": "MIT", "os": [ "darwin", @@ -11130,9 +11131,9 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 3ab8a2310..3af3c5833 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.1.0", + "@homebridge/hap-client": "2.2.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", "@nestjs/common": "10.4.17", @@ -113,7 +113,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.0", + "systeminformation": "5.27.1", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", diff --git a/src/modules/backup/backup.service.ts b/src/modules/backup/backup.service.ts index 70f92aa5b..d2f6fa4c6 100644 --- a/src/modules/backup/backup.service.ts +++ b/src/modules/backup/backup.service.ts @@ -322,7 +322,7 @@ export class BackupService { // Ensure the backupPath is within the instanceBackupPath if (!backupPath.startsWith(this.configService.instanceBackupPath)) { - throw new BadRequestException('Invalid backup path') + throw new BadRequestException(`Invalid backup path: ${backupPath} does not start with ${this.configService.instanceBackupPath}`) } return new StreamableFile(createReadStream(backupPath)) @@ -346,7 +346,7 @@ export class BackupService { // Ensure the backupPath is within the instanceBackupPath if (!backupPath.startsWith(this.configService.instanceBackupPath)) { - throw new BadRequestException('Invalid backup path') + throw new BadRequestException(`Invalid backup path: ${backupPath} does not start with ${this.configService.instanceBackupPath}`) } try { @@ -376,7 +376,7 @@ export class BackupService { // Ensure the backupPath is within the instanceBackupPath if (!backupPath.startsWith(this.configService.instanceBackupPath)) { - throw new BadRequestException('Invalid backup path') + throw new BadRequestException(`Invalid backup path: ${backupPath} does not start with ${this.configService.instanceBackupPath}`) } // Clear restore directory diff --git a/ui/package-lock.json b/ui/package-lock.json index 50c70ff44..edf622fc4 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -20,7 +20,7 @@ "@angular/platform-browser-dynamic": "19.2.13", "@angular/router": "19.2.13", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.1.0", + "@homebridge/hap-client": "2.2.0", "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", @@ -1391,12 +1391,12 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.1.0.tgz", - "integrity": "sha512-8OpTYaC9McLAWoY6vv8CmYMZ+RnJbsOh8Tc9rGgeuHE3x+Tx+T0hh2B726WAZ5VEgoUNKY8oP+7Zfo/2qQ7SHw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", + "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", "license": "MIT", "dependencies": { - "axios": "1.8.4", + "axios": "1.9.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", @@ -1411,13 +1411,13 @@ "license": "MIT" }, "node_modules/@inquirer/checkbox": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.7.tgz", - "integrity": "sha512-VEr2vnI4TSM2Q50fAck98mzWJGAoxbF0rb48tcSEjkJ2kn3mM6c/YsJwnyu45PlXd6aNWObMGWmQVleL2BJy6w==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.8.tgz", + "integrity": "sha512-d/QAsnwuHX2OPolxvYcgSj7A9DO9H6gVOy2DvBTx+P2LH2iRTo/RSGV3iwCzW024nP9hw98KIuDmdyhZQj1UQg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/figures": "^1.0.12", "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", @@ -1458,9 +1458,9 @@ } }, "node_modules/@inquirer/core": { - "version": "10.1.12", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.12.tgz", - "integrity": "sha512-uoaDadeJCYSVKYCMPwJi3AjCF9w+l9aWbHYA4iskKX84cVW/A2M6bJlWBoy3k81GpFp6EX3IElV1Z5xKw0g1QQ==", + "version": "10.1.13", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.13.tgz", + "integrity": "sha512-1viSxebkYN2nJULlzCxES6G9/stgHSepZ9LqqfdIGPHj5OHhiBUXVS0a6R0bEC2A+VL4D9w6QB66ebCr6HGllA==", "dev": true, "license": "MIT", "dependencies": { @@ -1486,13 +1486,13 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.12.tgz", - "integrity": "sha512-YNOCY79iqI/ksWohdudGtnO02N/a2j82b6akK/+hy1/C6xoU07dsKFUBfQ36nLCxE98ICS74Uyandq7nBS31Mw==", + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.13.tgz", + "integrity": "sha512-WbicD9SUQt/K8O5Vyk9iC2ojq5RHoCLK6itpp2fHsWe44VxxcA9z3GTWlvjSTGmMQpZr+lbVmrxdHcumJoLbMA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7", "external-editor": "^3.1.0" }, @@ -1509,13 +1509,13 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.14.tgz", - "integrity": "sha512-aon4yACMp4Qwc/2f6xafcC6jzAJ5vXBwL5+z4bS2y4YIOGF+QOe+Jzd5hLz1hOo+bhzVS7q07dNXTeBjaFAqRA==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.15.tgz", + "integrity": "sha512-4Y+pbr/U9Qcvf+N/goHzPEXiHH8680lM3Dr3Y9h9FFw4gHS+zVpbj8LfbKWIb/jayIB4aSO4pWiBTrBYWkvi5A==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7", "yoctocolors-cjs": "^2.1.2" }, @@ -1542,13 +1542,13 @@ } }, "node_modules/@inquirer/input": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.11.tgz", - "integrity": "sha512-gzcBWLWMiBaY507HFg4B1NJ18InnHhLjj4DTLfyoz9Rv7dSPpJ9JSj7Of8ea5QE2D+ms3ESTl/4MdzrC1//B0Q==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.12.tgz", + "integrity": "sha512-xJ6PFZpDjC+tC1P8ImGprgcsrzQRsUh9aH3IZixm1lAZFK49UGHxM3ltFfuInN2kPYNfyoPRh+tU4ftsjPLKqQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7" }, "engines": { @@ -1564,13 +1564,13 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.14.tgz", - "integrity": "sha512-8B4jX8ArK9zvb8/tB04jGLja4XoFfjvrTLJ5YeLlFnJh3jPa9VTQt2kxJZubGKc8YHX68e1XQxv4Nu/WZUnXIw==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.15.tgz", + "integrity": "sha512-xWg+iYfqdhRiM55MvqiTCleHzszpoigUpN5+t1OMcRkJrUrw7va3AzXaxvS+Ak7Gny0j2mFSTv2JJj8sMtbV2g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7" }, "engines": { @@ -1586,13 +1586,13 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.14.tgz", - "integrity": "sha512-/N/5PeI+QWE23dTn2D4erD9Y3yYeh0bUDkO9tt2d11mAVuCswiOKzoHrV9KYGQhoD6ae+Nff1G8TPqbfUUh8Ag==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.15.tgz", + "integrity": "sha512-75CT2p43DGEnfGTaqFpbDC2p2EEMrq0S+IRrf9iJvYreMy5mAWj087+mdKyLHapUEPLjN10mNvABpGbk8Wdraw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2" }, @@ -1639,13 +1639,13 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.2.tgz", - "integrity": "sha512-VDuhV58w3FuKNl24GR9ygdbu3NkGfuaK7D2gyMWeY79Lr4GVbj7ySxw1isAnelSzU1ecZC/TwICa5rCy0za2OA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.3.tgz", + "integrity": "sha512-7XrV//6kwYumNDSsvJIPeAqa8+p7GJh7H5kRuxirct2cgOcSWwwNGoXDRgpNFbY/MG2vQ4ccIWCi8+IXXyFMZA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/type": "^3.0.7", "yoctocolors-cjs": "^2.1.2" }, @@ -1662,13 +1662,13 @@ } }, "node_modules/@inquirer/search": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.14.tgz", - "integrity": "sha512-+VdtRD5nVR50K5fEMq/qbtHGH08vfqm69NJtojavlMXj6fsYymQZrNqjxEISPs2PDvtsemTJVFGs0uI6Zti6Dw==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.15.tgz", + "integrity": "sha512-YBMwPxYBrADqyvP4nNItpwkBnGGglAvCLVW8u4pRmmvOsHUtCAUIMbUrLX5B3tFL1/WsLGdQ2HNzkqswMs5Uaw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/figures": "^1.0.12", "@inquirer/type": "^3.0.7", "yoctocolors-cjs": "^2.1.2" @@ -1686,13 +1686,13 @@ } }, "node_modules/@inquirer/select": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.2.tgz", - "integrity": "sha512-3X8AAPE1WPUwY3IawT19BapD0kKpAUP7SVUu5mxmRjnl/f4q0MQz8CU8ToCC6Im0SzyOTWmSauE3GBgyOv1rBw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.3.tgz", + "integrity": "sha512-OAGhXU0Cvh0PhLz9xTF/kx6g6x+sP+PcyTiLvCrewI99P3BBeexD+VbuwkNDvqGkk3y2h5ZiWLeRP7BFlhkUDg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.12", + "@inquirer/core": "^10.1.13", "@inquirer/figures": "^1.0.12", "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", @@ -3740,9 +3740,9 @@ "peer": true }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -8464,9 +8464,9 @@ "peer": true }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/ui/package.json b/ui/package.json index 4a5f10841..1b7a6d3eb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -22,7 +22,7 @@ "@angular/platform-browser-dynamic": "19.2.13", "@angular/router": "19.2.13", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.1.0", + "@homebridge/hap-client": "2.2.0", "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", diff --git a/ui/src/app/core/accessories/types/airpurifier/airpurifier.manage.component.html b/ui/src/app/core/accessories/types/airpurifier/airpurifier.manage.component.html index cf219e570..308835b1d 100644 --- a/ui/src/app/core/accessories/types/airpurifier/airpurifier.manage.component.html +++ b/ui/src/app/core/accessories/types/airpurifier/airpurifier.manage.component.html @@ -10,12 +10,40 @@ [ngClass]="{ 'fa-check-circle': targetMode === 0, 'fa-blank': targetMode !== 0 }" > - {{ 'accessories.control.off' | translate }} + {{ 'accessories.control.manual' | translate }}
+ } @if (targetModeValidValues.includes(1)) { + } - - @if (targetRotationSpeed) { + } @if (targetRotationSpeed) {
{{ 'accessories.control.rotation_speed' | translate }}: {{ targetRotationSpeed.value }}%
= new Subject() @@ -38,26 +41,26 @@ export class AirpurifierManageComponent implements OnInit { .subscribe(() => { this.service.getCharacteristic('RotationSpeed').setValue(this.targetRotationSpeed.value) - // Turn bulb on or off when brightness is adjusted + // Turn the air purifier on or off when rotation speed is adjusted if (this.targetRotationSpeed.value && !this.service.values.Active) { - this.targetMode = 1 + this.targetState = 1 this.service.getCharacteristic('Active').setValue(this.targetMode) } else if (!this.targetRotationSpeed.value && this.service.values.Active) { - this.targetMode = 0 + this.targetState = 0 this.service.getCharacteristic('Active').setValue(this.targetMode) } }) } ngOnInit() { - this.targetMode = this.service.values.Active - + this.targetState = this.service.values.Active + this.targetMode = this.service.values.TargetAirPurifierState + this.targetModeValidValues = this.service.getCharacteristic('TargetAirPurifierState').validValues as number[] this.loadRotationSpeed() } loadRotationSpeed() { const RotationSpeed = this.service.getCharacteristic('RotationSpeed') - if (RotationSpeed) { this.targetRotationSpeed = { value: RotationSpeed.value, @@ -65,19 +68,30 @@ export class AirpurifierManageComponent implements OnInit { max: RotationSpeed.maxValue, step: RotationSpeed.minStep, } + setTimeout(() => { + const sliderElements = document.querySelectorAll('.noUi-target') + sliderElements.forEach((sliderElement: HTMLElement) => { + sliderElement.style.background = 'linear-gradient(to right, #add8e6, #416bdf)' + }) + }, 10) } } - setTargetMode(value: number) { - this.targetMode = value - this.service.getCharacteristic('Active').setValue(this.targetMode) + setTargetState(value: number) { + this.targetState = value + this.service.getCharacteristic('Active').setValue(this.targetState) - // Set the rotation speed to 100% if on 0% when turned on - if (this.targetMode && this.targetRotationSpeed && !this.targetRotationSpeed.value) { - this.targetRotationSpeed.value = 100 + // Set the rotation speed to max if on 0% when turned on + if (this.targetState && this.targetRotationSpeed && !this.targetRotationSpeed.value) { + this.targetRotationSpeed.value = this.service.getCharacteristic('RotationSpeed').maxValue } } + setTargetMode(value: number) { + this.targetMode = value + this.service.getCharacteristic('TargetAirPurifierState').setValue(this.targetMode) + } + onTargetRotationSpeedChange() { this.targetRotationSpeedChanged.next(this.targetRotationSpeed.value) } diff --git a/ui/src/app/core/accessories/types/battery/battery.component.html b/ui/src/app/core/accessories/types/battery/battery.component.html index 1dc410558..8b9a77a9a 100644 --- a/ui/src/app/core/accessories/types/battery/battery.component.html +++ b/ui/src/app/core/accessories/types/battery/battery.component.html @@ -7,14 +7,21 @@ }" >
- {{ (service.values.BatteryLevel || 0 | number:'1.0-0') + '%' }} + {{ (service.values.BatteryLevel || 0 | number:'1.0-0') + '%' }}
{{ service.customName || service.serviceName }}
@if (service.values.ChargingState === 0) { {{ 'accessories.control.battery_notcharging' | translate }} } @else if (service.values.ChargingState === 1) { {{ 'accessories.control.battery_charging' | translate }} } @else if (service.values.ChargingState === 2) { {{ 'accessories.control.battery_notchargeable' | translate }} } @else if - (service.values.StatusLowBattery === 1) { + (service.values.StatusLowBattery === 1 || service.values.BatteryLevel === 0) { {{ 'accessories.control.battery_low' | translate }} } @else { {{ 'accessories.control.battery_charged' | translate }} }
diff --git a/ui/src/app/core/accessories/types/battery/battery.component.scss b/ui/src/app/core/accessories/types/battery/battery.component.scss index 00c9001bc..dce21432e 100644 --- a/ui/src/app/core/accessories/types/battery/battery.component.scss +++ b/ui/src/app/core/accessories/types/battery/battery.component.scss @@ -28,7 +28,7 @@ top: 0; left: 0; height: 100%; - background-color: #42d672; + background-color: #808080; z-index: 1; transition: width 0.3s ease-in-out; } @@ -36,7 +36,14 @@ .battery-text { position: relative; z-index: 2; - color: white; + } + + .battery-over { + color: #ffffff; + } + + .battery-under { + color: #808080; } @media (max-width: 575px) { diff --git a/ui/src/app/core/accessories/types/door/door.component.html b/ui/src/app/core/accessories/types/door/door.component.html index 89326fafd..36d3a0805 100644 --- a/ui/src/app/core/accessories/types/door/door.component.html +++ b/ui/src/app/core/accessories/types/door/door.component.html @@ -16,8 +16,9 @@ @if (service.values.PositionState === 2) {
@if (service.values.CurrentPosition === 0) { {{ 'accessories.control.closed' | translate }} } @if - (service.values.CurrentPosition > 0 && service.values.CurrentPosition < 100) { {{ service.values.CurrentPosition - }}% } @if (service.values.CurrentPosition === 100) { {{ 'accessories.control.open' | translate }} } + (service.values.CurrentPosition > 0 && service.values.CurrentPosition < 100) { {{ 'accessories.control.open' | + translate }} {{ service.values.CurrentPosition }}% } @if (service.values.CurrentPosition === 100) { {{ + 'accessories.control.open' | translate }} }
} @if (service.values.PositionState === 1) {
{{ 'accessories.control.opening' | translate }}...
diff --git a/ui/src/app/core/accessories/types/door/door.manage.component.html b/ui/src/app/core/accessories/types/door/door.manage.component.html index 5664b046b..2b4539a3d 100644 --- a/ui/src/app/core/accessories/types/door/door.manage.component.html +++ b/ui/src/app/core/accessories/types/door/door.manage.component.html @@ -10,25 +10,45 @@ }
  • {{ 'users.label_admin_user' | translate }} -
    +
    Date: Sat, 7 Jun 2025 10:17:56 +0100 Subject: [PATCH 12/40] v4.76.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 577b0106f..412cb369e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.76.0 (Unreleased) +## v4.76.0 (2025-06-07) ### ⚠️ Upcoming Deprecations: diff --git a/package-lock.json b/package-lock.json index 61023bde7..cc31816d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-config-ui-x", - "version": "4.75.0", + "version": "4.76.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebridge-config-ui-x", - "version": "4.75.0", + "version": "4.76.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 9de736b30..626f9b241 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "homebridge-config-ui-x", "displayName": "Homebridge UI", - "version": "4.75.0", + "version": "4.76.0", "description": "A web based management, configuration and control platform for Homebridge.", "author": "oznu ", "license": "MIT", From 443f01bbecedd6fa5ad038d2fba1f3b1838feae5 Mon Sep 17 00:00:00 2001 From: Suthep Yonphimai Date: Sun, 29 Jun 2025 11:40:43 +0700 Subject: [PATCH 13/40] updates to the `th.json` language file (#2472) --- ui/src/i18n/th.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 63d43faa2..07199303a 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -11,8 +11,8 @@ "accessories.button_hidden_hide": "ซ่อน ที่ซ่อน", "accessories.button_hidden_show": "แสดง ที่ซ่อน", "accessories.button_remove": "ลบออกจากแคช", - "accessories.control.adaptive_lighting": "Adaptive Lighting", - "accessories.control.adaptive_lighting_note": "Some plugins may automatically re-enable Adaptive Lighting when changing this.", + "accessories.control.adaptive_lighting": "การจัดแสงแบบปรับได้", + "accessories.control.adaptive_lighting_note": "ปลั๊กอินบางตัวอาจเปิดใช้งาน Adaptive Lighting อีกครั้งโดยอัตโนมัติเมื่อมีการเปลี่ยนแปลงนี้", "accessories.control.auto": "อัตโนมัติ", "accessories.control.away": "ห่างออกไป", "accessories.control.battery_charged": "ชาร์จแล้ว", @@ -25,7 +25,7 @@ "accessories.control.closing": "กำลังปิด", "accessories.control.color_temperature": "อุณหภูมิสี", "accessories.control.cool": "ความเย็น", - "accessories.control.current": "Current", + "accessories.control.current": "ปัจจุบัน", "accessories.control.default_room": "ห้องเริ่มต้น", "accessories.control.dehumidify": "ลดความชื้น", "accessories.control.detected": "ตรวจพบ", @@ -34,12 +34,12 @@ "accessories.control.home": "บ้าน", "accessories.control.hue": "Hue", "accessories.control.humidify": "เพิ่มความชื้น", - "accessories.control.input": "Input List", + "accessories.control.input": "รายการอินพุต", "accessories.control.jammed": "ติดขัดอยู่", "accessories.control.lock_auto": "ตั้งเวลาในการล็อกอัตโนมัติ", "accessories.control.locked": "ล็อกแล้ว", - "accessories.control.manual": "Manual", - "accessories.control.mode": "Mode", + "accessories.control.manual": "ปรับเอง", + "accessories.control.mode": "โหมด", "accessories.control.mute": "ปิดเสียง", "accessories.control.night": "กลางคืน", "accessories.control.not_detected": "ตรวจไม่พบ", @@ -58,7 +58,7 @@ "accessories.control.stopped": "หยุดแล้ว", "accessories.control.target": "เป้าหมาย", "accessories.control.target_auto": "เป้าหมายอัตโนมัติ", - "accessories.control.threshold_auto": "Auto Threshold", + "accessories.control.threshold_auto": "เกณฑ์อัตโนมัติ", "accessories.control.triggered": "ทริกเกอร์แล้ว", "accessories.control.unknown": "ไม่ทราบ", "accessories.control.unlocked": "ปลดล๊อคแล้ว", @@ -76,7 +76,7 @@ "accessories.support.list_1": "ห้องที่คุณสร้างที่นี่จะไม่ปรากฏใน HomeKit แต่มีไว้สำหรับการจัดระเบียบอุปกรณ์เสริมใน Homebridge UI เท่านั้น", "accessories.support.list_2": "หากต้องการเปลี่ยนชื่อห้องที่มีอยู่ ให้สร้างห้องใหม่โดยใช้ชื่อที่ต้องการ และย้ายอุปกรณ์เสริมไปยังห้องใหม่", "accessories.support.list_3": "หากต้องการลบห้องที่มีอยู่ ให้ย้ายอุปกรณ์เสริมทั้งหมดไปยังห้องอื่นและรีเฟรชหน้า", - "accessories.support.list_4": "Aอุปกรณ์เสริมอาจใช้เวลาสองสามนาทีจึงจะปรากฏบนหน้าจอนี้หลังจากรีสตาร์ท Homebridge หรือหลังจากเพิ่มเข้าไปแล้ว หากอุปกรณ์เสริมหายไปอย่างต่อเนื่อง ให้ลองเปลี่ยน mDNS AdvertiserS ในการตั้งค่า", + "accessories.support.list_4": "อุปกรณ์เสริมอาจใช้เวลาสองสามนาทีจึงจะปรากฏบนหน้าจอนี้หลังจากรีสตาร์ท Homebridge หรือหลังจากเพิ่มเข้าไปแล้ว หากอุปกรณ์เสริมหายไปอย่างต่อเนื่อง ให้ลองเปลี่ยน mDNS AdvertiserS ในการตั้งค่า", "accessories.title_accessories": "อุปกรณ์เสริม", "backup.backup_delete_failed": "การลบข้อมูลสำรองล้มเหลว ดูรายละเอียดใน Logs", "backup.backup_download_failed": "การดาวน์โหลดข้อมูลสำรองล้มเหลว", @@ -100,9 +100,9 @@ "backup.restore_warning": "การกู้คืนจากข้อมูลสำรองจะเขียนทับการกำหนดค่า Homebridge ปัจจุบันอย่างไม่สามารถย้อนกลับได้", "backup.scheduled_backup_disabled": "การสำรองข้อมูลตามกำหนดเวลาถูกปิดการใช้งานผ่านการกำหนดค่า", "backup.scheduled_backup_time": "การสำรองข้อมูลทั้งหมดของอินสแตนซ์ Homebridge จะถูกสร้างขึ้นโดยอัตโนมัติทุกวันที่ {{ backupTime }} และเก็บไว้สำหรับ {{ dayCount }} วัน", - "backup.settings_enable": "Enable Scheduled Backups", - "backup.settings_path": "Scheduled Backup Path", - "backup.settings_title": "Scheduled Backup Settings", + "backup.settings_enable": "เปิดใช้งานการสำรองข้อมูลตามกำหนดเวลา", + "backup.settings_path": "เส้นทางการสำรองข้อมูลตามกำหนดเวลา", + "backup.settings_title": "การตั้งค่าการสำรองข้อมูลตามกำหนดเวลา", "backup.title_backup": "การสำรองข้อมูลและกู้คืน", "child_bridge.about": "Homebridge ช่วยให้คุณสามารถเรียกใช้แพลตฟอร์มปลั๊กอินหรืออุปกรณ์เสริมแยกจากบริดจ์ย่อยสิ่งนี้สามารถปรับปรุงการตอบสนองทั่วไปและความน่าเชื่อถือของ Homebridge {{ link }}", "child_bridge.bridge_connect": "เชื่อมต่อไปที่ HomeKit", @@ -151,7 +151,7 @@ "config.restore.title_restore_homebridge_backup": "คืนค่าการสำรองข้อมูลการกำหนดค่า Homebridge", "config.restore.toast_backups_deleted": "ลบข้อมูลสำรองทั้งหมดแล้ว", "config.title_backup_loaded": "โหลดข้อมูลสำรองแล้ว", - "form.auto_save": "Changes are automatically saved.", + "form.auto_save": "การเปลี่ยนแปลงจะได้รับการบันทึกโดยอัตโนมัติ", "form.button_back": "ย้่อนกลับ", "form.button_cancel": "ยกเลิก", "form.button_close": "ปิด", @@ -176,9 +176,9 @@ "form.label_invalid_strict": "การตรวจสอบการกำหนดค่าล้มเหลว - โปรดตรวจสอบแบบฟอร์มก่อนบันทึก", "form.label_valid": "ผ่านการตรวจสอบการกำหนดค่าแล้ว", "form.select.auto": "อัตโนมัติ (ใช้การตั้งค่าเบราว์เซอร์)", - "login.invalid_code": "The code entered is incorrect or has expired", + "login.invalid_code": "รหัสที่ป้อนไม่ถูกต้องหรือหมดอายุแล้ว", "login.invalid_credentials": "ชื่อผู้ใช้และรหัสผ่านไม่ถูกต้อง", - "login.invalid_credentials_2": "To reset your credentials or 2fa code, delete the auth.json file in your Homebridge storage directory, restart Homebridge, then login with admin / admin.", + "login.invalid_credentials_2": "หากต้องการรีเซ็ตข้อมูลประจำตัวหรือรหัส 2fa ของคุณ ให้ลบไฟล์ auth.json ในไดเร็กทอรีที่เก็บข้อมูล Homebridge ของคุณ รีสตาร์ท Homebridge จากนั้นเข้าสู่ระบบด้วย admin / admin", "login.invalid_password": "รหัสผ่านไม่ถูกต้อง", "login.label_2fa_code": "รหัสรับรองความถูกต้องสองปัจจัย", "logs.download.error": "ไม่สามารถดาวน์โหลดไฟล์ log ได้", @@ -410,11 +410,11 @@ "settings.display.temp_units.c": "เซลเซียส (°C)", "settings.display.temp_units.f": "ฟาเรนไฮต์ (°F)", "settings.display.theme": "ธีม", - "settings.display.wallpaper": "Wallpaper", - "settings.display.wallpaper_intro": "Upload a wallpaper for your Homebridge UI. This is currently shown on the login screen.", - "settings.display.wallpaper_rule": "You can choose an image file which is up to {{ maxFileSizeText }}.", - "settings.display.wallpaper_rule2": "You will need to click Save to upload the wallpaper to your Homebridge storage directory.", - "settings.display.wallpaper_success": "Wallpaper was successfully updated.", + "settings.display.wallpaper": "วอลล์เปเปอร์", + "settings.display.wallpaper_intro": "อัปโหลดวอลเปเปอร์สำหรับ Homebridge UI ของคุณ ซึ่งขณะนี้แสดงอยู่ที่หน้าจอเข้าสู่ระบบ", + "settings.display.wallpaper_rule": "คุณสามารถเลือกไฟล์รูปภาพขนาดสูงสุด {{ maxFileSizeText }} ได้", + "settings.display.wallpaper_rule2": "คุณจะต้องคลิกบันทึกเพื่ออัปโหลดวอลเปเปอร์ไปยังไดเร็กทอรีที่จัดเก็บข้อมูล Homebridge ของคุณ", + "settings.display.wallpaper_success": "อัปเดตวอลเปเปอร์สำเร็จแล้ว", "settings.general.title_display": "การแดงผล", "settings.general.title_general": "ทั่วไป", "settings.mdns_advertiser": "mDNS Advertiser", @@ -464,9 +464,9 @@ "status.network.received_per_second": "ได้รับแล้ว", "status.network.sent_per_second": "ส่ง", "status.network.title_network": "กิจกรรมเครือข่าย", - "status.readiness.node_no": "Your version of Node.js is not compatible with {{ app }}.", - "status.readiness.node_yes": "Your version of Node.js is compatible with {{ app }}.", - "status.readiness.title": "{{ app }} Readiness", + "status.readiness.node_no": "เวอร์ชัน Node.js ของคุณไม่เข้ากันได้กับ {{ app }}", + "status.readiness.node_yes": "เวอร์ชัน Node.js ของคุณเข้ากันได้กับ {{ app }}", + "status.readiness.title": "{{ แอป }} ความพร้อม", "status.services.label_not_running": "ไม่ทำงาน", "status.services.label_running": "กำลังทำงาน", "status.services.updates": "อัปเดตข้อมูล", From 564bbe4f5763a51f842f637d9bc652fa740fafc3 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 7 Jun 2025 13:13:41 +0100 Subject: [PATCH 14/40] auto restart after version change of hb or ui --- CHANGELOG.md | 17 ++++++- .../restart-homebridge.component.ts | 30 ++---------- .../manage-plugin.component.html | 12 +++-- .../manage-plugin/manage-plugin.component.ts | 47 +++++++++++-------- .../manage-version.component.html | 4 ++ .../manage-version.component.ts | 3 +- ui/src/i18n/bg.json | 1 + ui/src/i18n/ca.json | 1 + ui/src/i18n/cs.json | 1 + ui/src/i18n/de.json | 1 + ui/src/i18n/en.json | 1 + ui/src/i18n/es.json | 1 + ui/src/i18n/fi.json | 1 + ui/src/i18n/fr.json | 1 + ui/src/i18n/he.json | 1 + ui/src/i18n/hu.json | 1 + ui/src/i18n/id.json | 1 + ui/src/i18n/it.json | 1 + ui/src/i18n/ja.json | 1 + ui/src/i18n/ko.json | 1 + ui/src/i18n/mk.json | 1 + ui/src/i18n/nl.json | 1 + ui/src/i18n/no.json | 1 + ui/src/i18n/pl.json | 1 + ui/src/i18n/pt-BR.json | 1 + ui/src/i18n/pt.json | 1 + ui/src/i18n/ru.json | 1 + ui/src/i18n/sl.json | 1 + ui/src/i18n/sv.json | 1 + ui/src/i18n/th.json | 1 + ui/src/i18n/tr.json | 1 + ui/src/i18n/uk.json | 1 + ui/src/i18n/zh-CN.json | 1 + ui/src/i18n/zh-TW.json | 1 + 34 files changed, 88 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 412cb369e..b0c0fbd89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.76.0 (2025-06-07) +## v4.77.0 (Unreleased) ### ⚠️ Upcoming Deprecations: @@ -12,7 +12,20 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - Drop support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) - Drop support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware - Drop support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) -- Note that these are not requirements for UI `v4.76.0` +- Note that these are not requirements for UI `v4.77.0` + +### UI Changes + +- updates to the `th.json` language file (#2472) (@tomzt) +- auto restart after version change of hb or ui + +### Homebridge Dependencies + +- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` +- `@homebridge/plugin-ui-utils` @ `v2.1.0` + +## v4.76.0 (2025-06-07) ### UI Changes diff --git a/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts b/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts index 01d99ff4e..3b03cc019 100644 --- a/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts +++ b/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts @@ -1,10 +1,7 @@ -import { Component, inject, Input } from '@angular/core' +import { Component, inject } from '@angular/core' import { Router } from '@angular/router' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { TranslatePipe, TranslateService } from '@ngx-translate/core' -import { ToastrService } from 'ngx-toastr' - -import { ApiService } from '@/app/core/api.service' +import { TranslatePipe } from '@ngx-translate/core' @Component({ templateUrl: './restart-homebridge.component.html', @@ -13,31 +10,12 @@ import { ApiService } from '@/app/core/api.service' }) export class RestartHomebridgeComponent { $activeModal = inject(NgbActiveModal) - private $api = inject(ApiService) private $router = inject(Router) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - @Input() fullRestart = false constructor() {} public onRestartHomebridgeClick() { - if (!this.fullRestart) { - this.$router.navigate(['/restart']) - this.$activeModal.close() - return - } - - this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ - next: () => { - this.$router.navigate(['/restart']) - this.$activeModal.close() - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) + this.$router.navigate(['/restart']) + this.$activeModal.close() } } diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html index ddfb95341..a571de6da 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html @@ -24,9 +24,9 @@
    class="mb-3 text-center grey-text" [innerHTML]="'plugins.manage.github_support' | translate:{ iconStar, iconThumbsUp }" >

    - @if (['homebridge', 'homebridge-config-ui-x'].includes(pluginName) || childBridges.length === 0) { + @if (childBridges.length === 0) {

    {{ 'plugins.settings.restart_required' | translate }}

    - } @if (!['homebridge', 'homebridge-config-ui-x'].includes(pluginName) && childBridges.length > 0) { + } @if (childBridges.length > 0) {

    {{ 'restart.child_bridges' | translate }}

    } } @if (changeLog) {
    @@ -82,7 +82,11 @@
    v{{ installedVersion }} → } @if (release.name) { {{ release.name }} } @if (!release.name) { v{{ latestVersion }} }
    - } + @if (['homebridge', 'homebridge-config-ui-x'].includes(pluginName)) { + +

    {{ 'plugins.manage.hb_restart' | translate }}

    +
    + } }
    @@ -124,7 +128,7 @@
    diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts index fb4d32ef8..24649bd89 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts @@ -1,7 +1,7 @@ import { NgClass } from '@angular/common' import { Component, inject, Input, OnDestroy, OnInit } from '@angular/core' import { Router } from '@angular/router' -import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { NgbActiveModal, NgbAlert, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { saveAs } from 'file-saver' import { NgxMdModule } from 'ngx-md' @@ -27,6 +27,7 @@ import { HbV2ModalComponent } from '@/app/modules/status/widgets/update-info-wid PluginsMarkdownDirective, TranslatePipe, NgClass, + NgbAlert, ], }) @@ -197,6 +198,20 @@ export class ManagePluginComponent implements OnInit, OnDestroy { termRows: this.term.rows, }).subscribe({ next: async () => { + // Updating the UI needs a restart straight away + if (this.pluginName === 'homebridge-config-ui-x') { + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => { + window.location.href = '/restart' + }, + error: (error) => { + console.error(error) + window.location.href = '/restart' + }, + }) + return + } + try { await Promise.all([this.getChangeLog(), this.getChildBridges()]) } catch (error) { @@ -204,7 +219,7 @@ export class ManagePluginComponent implements OnInit, OnDestroy { } this.actionComplete = true this.justUpdatedPlugin = true - this.$router.navigate([this.pluginName === 'homebridge-config-ui-x' ? '/' : '/plugins']) + this.$router.navigate(['/plugins']) }, error: (error) => { this.actionFailed = true @@ -240,11 +255,15 @@ export class ManagePluginComponent implements OnInit, OnDestroy { }).subscribe({ next: () => { this.$activeModal.close() - const ref = this.$modal.open(RestartHomebridgeComponent, { - size: 'lg', - backdrop: 'static', + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => { + this.$router.navigate(['/restart']) + }, + error: (error) => { + console.error(error) + this.$router.navigate(['/restart']) + }, }) - ref.componentInstance.fullRestart = true }, error: (error) => { this.actionFailed = true @@ -291,20 +310,8 @@ export class ManagePluginComponent implements OnInit, OnDestroy { } public onRestartHomebridgeClick() { - if (this.pluginName === 'homebridge-config-ui-x') { - this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ - next: () => { - window.location.href = '/restart' - }, - error: (error) => { - console.error(error) - window.location.href = '/restart' - }, - }) - } else { - this.$router.navigate(['/restart']) - this.$activeModal.close() - } + this.$router.navigate(['/restart']) + this.$activeModal.close() } public async onRestartChildBridgeClick() { diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html index f0e669d01..dcead1d7d 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html @@ -25,6 +25,10 @@
    {{ 'plugins.manage.select_version' | translate }}
    } @else {
    {{ 'plugins.manage.select_version' | translate }}
    + } @if (['homebridge', 'homebridge-config-ui-x'].includes(plugin.name)) { + +

    {{ 'plugins.manage.hb_restart' | translate }}

    +
    }
      @for (version of versionsWithTags; track version) { diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts index be9d6cf14..f6026f840 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts @@ -1,6 +1,6 @@ import { Component, inject, Input, OnInit } from '@angular/core' import { FormsModule } from '@angular/forms' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { NgbActiveModal, NgbAlert } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { rcompare } from 'semver' @@ -21,6 +21,7 @@ interface VersionData { imports: [ FormsModule, TranslatePipe, + NgbAlert, ], }) export class ManageVersionComponent implements OnInit { diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index ed5951c19..24c99f7e2 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирай", "plugins.manage.installed": "Инсталиран", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index c120f0c58..2d6127aad 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Desactivar", "plugins.manage.enable": "Activar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Informació del plugin", "plugins.manage.install": "Instal·lar", "plugins.manage.installed": "Instal·lat", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 82d0f3ddf..76704e648 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Zakázat", "plugins.manage.enable": "Povolit", "plugins.manage.github_support": "Můžete vyjádřit svou podporu tomuto pluginu tím, že mu na GitHubu dáte {{ iconStar }} (nebo této verzi {{ iconThumbsUp }})!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Informace o pluginu", "plugins.manage.install": "Instalovat", "plugins.manage.installed": "Instalováno", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index bf87969a7..1c3da8f4c 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Deaktivieren", "plugins.manage.enable": "Aktivieren", "plugins.manage.github_support": "Sie können Ihre Unterstützung zeigen, indem Sie dieses Plugin mit einem {{ iconStar }} (oder dem Release ein {{ iconThumbsUp }}) auf GitHub geben!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installieren", "plugins.manage.installed": "Installiert", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index c39195a11..7cf76e5ad 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Install", "plugins.manage.installed": "Installed", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index ae9de2700..4a16a09b3 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Deshabilitar", "plugins.manage.enable": "Habilitar", "plugins.manage.github_support": "Puedes mostrar tu apoyo dando a este plugin una {{ iconStar }} (o a la versión una {{ iconThumbsUp }}) en GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Información del Plugin", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 5342ccb71..fb3622b79 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Poista käytöstä", "plugins.manage.enable": "Ota käyttöön", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Tietoja laajennuksesta", "plugins.manage.install": "Asenna", "plugins.manage.installed": "Asennettu", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 6e5983485..6c6eb0e95 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Désactiver", "plugins.manage.enable": "Activer", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Informations sur le plugin", "plugins.manage.install": "Installer", "plugins.manage.installed": "Installé", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 0620469c5..9835be71a 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "לא פעיל", "plugins.manage.enable": "מאופשר", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "התקן", "plugins.manage.installed": "הותקן", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index ffed62e1c..75023d5df 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Telepítés", "plugins.manage.installed": "Telepítve", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 6bcd6d1f4..81f6f3afb 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Nonaktifkan", "plugins.manage.enable": "Aktifkan", "plugins.manage.github_support": "Anda dapat menunjukkan dukungan Anda dengan memberikan plugin ini {{ iconStar }} (atau rilis A {{ iconThumbsUp }}) di github!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Informasi Plugin", "plugins.manage.install": "Pasang", "plugins.manage.installed": "Terpasang", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index edfda8718..3801e4cea 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disattiva", "plugins.manage.enable": "Attiva", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installa", "plugins.manage.installed": "Installato", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 839d80c03..4129e882d 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "無効化", "plugins.manage.enable": "有効化", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "プラグイン情報", "plugins.manage.install": "インストール", "plugins.manage.installed": "インストール済", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 605d3f752..4649229e3 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "비활성화", "plugins.manage.enable": "활성화", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "플러그인 정보", "plugins.manage.install": "설치", "plugins.manage.installed": "설치됨", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 3d8612e0d..b6abd9e21 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирај", "plugins.manage.installed": "Инсталирано", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index ccaa0f940..339b00c78 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Deactiveren", "plugins.manage.enable": "Activeren", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installeer", "plugins.manage.installed": "Geïnstalleerd", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 1fa7439c9..fb89f2ed5 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installere", "plugins.manage.installed": "Installert", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index d89353d56..541d3f69e 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Wyłącz", "plugins.manage.enable": "Włącz", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Informacje wtyczki", "plugins.manage.install": "Instaluj", "plugins.manage.installed": "Zainstalowane", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 86172b374..a8c2bf364 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Desativar", "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 897e46472..d02c1b9f8 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Desativar", "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 6928137de..aae991770 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Отключить", "plugins.manage.enable": "Включить", "plugins.manage.github_support": "Вы можете поддержать проект, поставив {{ iconStar }} плагину (или {{ iconThumbsUp }} релизу) на GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Информация о плагине", "plugins.manage.install": "Установить", "plugins.manage.installed": "Установлен", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index efb086de3..2e5c98437 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Onemogoči", "plugins.manage.enable": "Omogoči", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Namestite", "plugins.manage.installed": "Nameščeno", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index e07a78f68..e2171398c 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Inaktivera", "plugins.manage.enable": "Aktivera", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin-information", "plugins.manage.install": "Installera", "plugins.manage.installed": "Installerad", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 07199303a..96b87e876 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "ปิดการใช้งาน", "plugins.manage.enable": "เปิดการใช้งาน", "plugins.manage.github_support": "คุณสามารถแสดงการสนับสนุนของคุณโดยมอบ {{ iconStar }} ให้กับปลั๊กอินนี้ (หรือเผยแพร่ {{ iconThumbsUp }}) บน GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "ข้อมูลปลั๊กอิน", "plugins.manage.install": "ติดตั้ง", "plugins.manage.installed": "ติดตั้งแล้ว", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index fe4204c8c..b6f098262 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Devre Dışı Bırak", "plugins.manage.enable": "Etkinleştir", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Yükle", "plugins.manage.installed": "Yüklü", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 8752ac060..728160d55 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Вимкнути", "plugins.manage.enable": "Увімкнути", "plugins.manage.github_support": "Ви можете продемонструвати свою підтримку, поставивши цьому плагіну {{ iconStar }} (або випуску {{ iconThumbsUp }}) на GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Інформація про плагін", "plugins.manage.install": "Встановлення", "plugins.manage.installed": "Плагін встановлено", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 7aeb7286a..c2d14ce60 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "Disable", "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安装", "plugins.manage.installed": "已安装", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index 971397b4d..a80b77ed4 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -266,6 +266,7 @@ "plugins.manage.disable": "關閉", "plugins.manage.enable": "開啟", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", + "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安裝", "plugins.manage.installed": "已安裝", From 1d5d3aac4c5d66b4bdf8f87ee5cfda291fe960ee Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 8 Jun 2025 21:05:29 +0100 Subject: [PATCH 15/40] redesigned setup wizard page --- CHANGELOG.md | 1 + src/core/config/config.service.ts | 4 +- ui/src/app/core/settings.service.ts | 4 +- ui/src/app/modules/login/login.component.html | 2 +- ui/src/app/modules/login/login.component.scss | 5 - ui/src/app/modules/login/login.component.ts | 6 +- .../setup-wizard/setup-wizard.component.html | 162 ++++++------ .../setup-wizard/setup-wizard.component.scss | 95 +++---- .../setup-wizard/setup-wizard.component.ts | 246 +++++++++++------- ui/src/i18n/bg.json | 15 +- ui/src/i18n/ca.json | 15 +- ui/src/i18n/cs.json | 15 +- ui/src/i18n/de.json | 15 +- ui/src/i18n/en.json | 15 +- ui/src/i18n/es.json | 15 +- ui/src/i18n/fi.json | 15 +- ui/src/i18n/fr.json | 15 +- ui/src/i18n/he.json | 15 +- ui/src/i18n/hu.json | 15 +- ui/src/i18n/id.json | 15 +- ui/src/i18n/it.json | 15 +- ui/src/i18n/ja.json | 15 +- ui/src/i18n/ko.json | 15 +- ui/src/i18n/mk.json | 15 +- ui/src/i18n/nl.json | 15 +- ui/src/i18n/no.json | 15 +- ui/src/i18n/pl.json | 15 +- ui/src/i18n/pt-BR.json | 15 +- ui/src/i18n/pt.json | 15 +- ui/src/i18n/ru.json | 15 +- ui/src/i18n/sl.json | 15 +- ui/src/i18n/sv.json | 15 +- ui/src/i18n/th.json | 15 +- ui/src/i18n/tr.json | 15 +- ui/src/i18n/uk.json | 15 +- ui/src/i18n/zh-CN.json | 15 +- ui/src/i18n/zh-TW.json | 15 +- ui/src/scss/base/layout.scss | 5 + ui/src/scss/themes/themes-dark.scss | 3 +- ui/src/scss/themes/themes-light.scss | 5 + 40 files changed, 548 insertions(+), 410 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0c0fbd89..f2fe8b917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - updates to the `th.json` language file (#2472) (@tomzt) - auto restart after version change of hb or ui +- redesigned setup wizard page ### Homebridge Dependencies diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index 875693fd0..e157cbf37 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -211,7 +211,7 @@ export class ConfigService { formAuth: Boolean(this.ui.auth !== 'none'), lightingMode: this.ui.lightingMode || 'auto', serverTimestamp: new Date().toISOString(), - theme: this.ui.theme || 'orange', + theme: this.ui.theme || 'deep-purple', menuMode: this.ui.menuMode || 'default', } @@ -293,7 +293,7 @@ export class ConfigService { if (!this.ui.port && process.env.HOMEBRIDGE_CONFIG_UI_PORT) { this.ui.port = Number.parseInt(process.env.HOMEBRIDGE_CONFIG_UI_PORT, 10) } - this.ui.theme = this.ui.theme || process.env.HOMEBRIDGE_CONFIG_UI_THEME || 'orange' + this.ui.theme = this.ui.theme || process.env.HOMEBRIDGE_CONFIG_UI_THEME || 'deep-purple' this.ui.auth = this.ui.auth || process.env.HOMEBRIDGE_CONFIG_UI_AUTH as 'form' | 'none' || 'form' this.ui.wallpaper = this.ui.wallpaper || process.env.HOMEBRIDGE_CONFIG_UI_LOGIN_WALLPAPER || undefined } diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts index 30ea6a51f..74d4887f5 100644 --- a/ui/src/app/core/settings.service.ts +++ b/ui/src/app/core/settings.service.ts @@ -69,7 +69,7 @@ export class SettingsService { public menuMode: 'default' | 'freeze' public wallpaper: string public serverTimeOffset = 0 - private readonly defaultTheme = 'orange' + private readonly defaultTheme = 'deep-purple' public readonly themeList = [ 'orange', 'red', @@ -134,7 +134,7 @@ export class SettingsService { } setTheme(theme: string) { - // Default theme is orange + // Default theme is deep-purple if (!theme || !this.themeList.includes(theme)) { theme = this.defaultTheme diff --git a/ui/src/app/modules/login/login.component.html b/ui/src/app/modules/login/login.component.html index e3fa92d06..910c1ac68 100644 --- a/ui/src/app/modules/login/login.component.html +++ b/ui/src/app/modules/login/login.component.html @@ -91,7 +91,7 @@

      {{ 'setup.welcome_to_homebridge' | translate }}

      }
      -
      diff --git a/ui/src/app/modules/login/login.component.scss b/ui/src/app/modules/login/login.component.scss index 9b258d1a7..cf2628ff4 100644 --- a/ui/src/app/modules/login/login.component.scss +++ b/ui/src/app/modules/login/login.component.scss @@ -56,8 +56,3 @@ .homebridge-logo { margin-bottom: 10px; } - -.btn-primary { - background-color: #4a266c !important; - border-color: #4a266c !important; -} diff --git a/ui/src/app/modules/login/login.component.ts b/ui/src/app/modules/login/login.component.ts index ccda38270..260d92e59 100644 --- a/ui/src/app/modules/login/login.component.ts +++ b/ui/src/app/modules/login/login.component.ts @@ -75,10 +75,8 @@ export class LoginComponent implements OnInit, AfterViewChecked { } if (this.$settings.env.customWallpaperHash) { - if (this.$settings.env.customWallpaperHash) { - const backgroundImageUrl = `${environment.api.base}/auth/wallpaper/${this.$settings.env.customWallpaperHash}` - this.backgroundStyle = `url('${backgroundImageUrl}') center/cover` - } + const backgroundImageUrl = `${environment.api.base}/auth/wallpaper/${this.$settings.env.customWallpaperHash}` + this.backgroundStyle = `url('${backgroundImageUrl}') center/cover` } } diff --git a/ui/src/app/modules/setup-wizard/setup-wizard.component.html b/ui/src/app/modules/setup-wizard/setup-wizard.component.html index 3e41ceab5..09572b9d8 100644 --- a/ui/src/app/modules/setup-wizard/setup-wizard.component.html +++ b/ui/src/app/modules/setup-wizard/setup-wizard.component.html @@ -1,31 +1,47 @@ -
      -
      +
      +
      + +
      +
      +
      @if (step === 'welcome') { -
      - -

      {{ 'setup.welcome_to_homebridge' | translate }}

      - - - {{ 'setup_wizard_message_restore' | translate }} - + {{ 'setup_wizard_restore' | translate }}
      - } @if (step === 'create-account') { -
      - -

      {{ 'setup.create_account' | translate }}

      + } @else if (step === 'create-account') { +
      +

      {{ 'setup.create_account' | translate }}

      +
      {{ 'setup_wizard_create_info' | translate }}
      -

      {{ 'setup.create_account_reason' | translate }}

      -
      - +
      + {{ 'setup.create_account' | translate }}
    autocomplete="username" autocapitalize="none" tabindex="1" - class="form-control py-2" - [placeholder]="'users.label_username' | translate" + class="form-control custom-input" [readonly]="loading" [ngClass]="{ 'is-valid': (createUserForm.controls.username.dirty) && createUserForm.controls.username.valid, 'is-invalid': (createUserForm.controls.username.dirty) && createUserForm.controls.username.invalid }" + [placeholder]="'users.label_username' | translate" + required />
    -
    - +
    +
    -
    - +
    +
    -
    +
    +
    - } @if (step === 'restore-backup') { -
    - -

    {{ 'form.button_restore' | translate }}

    -

    {{ 'backup.restore_help_one' | translate }}

    + } @else if (step === 'restore-backup') { +
    +

    {{ 'setup_wizard_restore' | translate }}

    +
    {{ 'backup.restore_help_one' | translate }}
    {{ 'form.button_restore' | translate }} [disabled]="restoreUploading" (click)="onClickCancelRestore()" > - {{ 'form.button_cancel' | translate }} + {{ 'form.button_back' | translate }}
    - } @if (step === 'restarting') { -
    - -

    {{ 'restart.title_restart' | translate }}

    -

    - -

    + } @else if (['restoring', 'restarting', 'restore-complete'].includes(step)) { +
    +

    + @if (step === 'restoring') { {{ 'setup_wizard_restoring' | translate }} } @else if (step === 'restarting') { {{ + 'setup_wizard_starting' | translate }} } @else if (step === 'restore-complete') { {{ 'setup_wizard_complete' | + translate }} } +

    +
    + @if (step === 'restore-complete') { + {{ 'form.label_continue' | translate }} + }
    - } @if (step === 'setup-complete') { -
    - -

    {{ 'setup_wizard_message_complete_title' | translate }}

    -

    {{ 'setup_wizard_message_complete_message' | translate }}

    - {{ 'setup.open_dashboard' | translate }} + } @else if (step === 'setup-complete') { +
    +

    {{ 'setup_wizard_complete_title' | translate }}

    +
    {{ 'setup_wizard_completed' | translate }}
    + {{ 'form.label_continue' | translate }}
    }
    diff --git a/ui/src/app/modules/setup-wizard/setup-wizard.component.scss b/ui/src/app/modules/setup-wizard/setup-wizard.component.scss index 8ac420536..d0d4a4ddf 100644 --- a/ui/src/app/modules/setup-wizard/setup-wizard.component.scss +++ b/ui/src/app/modules/setup-wizard/setup-wizard.component.scss @@ -1,77 +1,68 @@ +::ng-deep body { + overflow: scroll !important; +} + +::ng-deep body.dark-mode { + .setup-card { + background-color: #2b2b2b; + color: #ffffff; + } +} + .setup-container { - background-size: cover; z-index: -1; - padding-top: 1em; - padding-bottom: 1em; + padding-top: 2em; + padding-bottom: 2em; + min-height: 100%; + background-size: 300% 300%; +} + +.anim { + -webkit-animation: gradient 20s ease infinite; + -moz-animation: gradient 20s ease infinite; + -o-animation: gradient 20s ease infinite; + animation: gradient 20s ease infinite; +} - @media screen and (min-height: 500px) and (min-width: 600px) { - padding-top: 4em; +@keyframes gradient { + 0% { + background-position: 0 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0 50%; } } .setup-card { - max-width: 600px; - border-radius: 15px; - background-color: #ffffff; + max-width: 550px; + border-radius: 1rem; padding-right: 25px; padding-left: 25px; + background-color: rgba(255, 255, 255, 0.9); .form-control:focus { background-color: inherit !important; } - @media screen and (max-width: 600px) { + @media screen and (max-width: 575px) { margin-left: 1em; margin-right: 1em; } } -::ng-deep body.dark-mode { - .setup-card { - background-color: #2b2b2b; - color: #fff; - } -} - .homebridge-logo { - margin-right: 10px; - height: 200px; - - @media screen and (max-height: 500px) { - height: 100px; - } - - @media screen and (max-width: 600px) { - height: 100px; - } + margin-bottom: 10px; } -.homebridge-logo-small { - height: 50px; +.progress { + background-color: #dddddd; } -.button-loading { - position: relative; - color: rgba(0, 0, 0, 0); - - .button-loading-overlay { - display: block; - color: #fff; - } -} - -.button-loading-overlay { - display: none; - position: absolute; - top: 9px; - left: 0; - right: 0; -} - -small { - a { - &:hover { - text-decoration: underline; - } - } +#output { + height: 200px; + overflow-y: scroll; + white-space: pre-wrap; } diff --git a/ui/src/app/modules/setup-wizard/setup-wizard.component.ts b/ui/src/app/modules/setup-wizard/setup-wizard.component.ts index 43b50479e..8ad191c90 100644 --- a/ui/src/app/modules/setup-wizard/setup-wizard.component.ts +++ b/ui/src/app/modules/setup-wizard/setup-wizard.component.ts @@ -1,9 +1,7 @@ -import { NgClass } from '@angular/common' -import { Component, inject, OnDestroy, OnInit } from '@angular/core' +import { NgClass, NgOptimizedImage, NgStyle } from '@angular/common' +import { Component } from '@angular/core' import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms' import { Title } from '@angular/platform-browser' -import { RouterLink } from '@angular/router' -import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' @@ -11,49 +9,63 @@ import { firstValueFrom } from 'rxjs' import { ApiService } from '@/app/core/api.service' import { AuthService } from '@/app/core/auth/auth.service' import { SettingsService } from '@/app/core/settings.service' -import { RestoreComponent } from '@/app/modules/settings/backup/restore/restore.component' +import { IoNamespace, WsService } from '@/app/core/ws.service' import { environment } from '@/environments/environment' @Component({ templateUrl: './setup-wizard.component.html', styleUrls: ['./setup-wizard.component.scss'], - standalone: true, imports: [ - FormsModule, - ReactiveFormsModule, NgClass, - RouterLink, TranslatePipe, + NgOptimizedImage, + FormsModule, + ReactiveFormsModule, + NgStyle, ], }) -export class SetupWizardComponent implements OnInit, OnDestroy { - private $api = inject(ApiService) - private $auth = inject(AuthService) - private $modal = inject(NgbModal) - private $settings = inject(SettingsService) - private $title = inject(Title) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - public previousTitle: string - public step: 'welcome' | 'create-account' | 'setup-complete' | 'restore-backup' | 'restarting' = 'welcome' - +export class SetupWizardComponent { + private io: IoNamespace + + public step: 'welcome' | 'create-account' | 'setup-complete' | 'restore-backup' | 'restoring' | 'restarting' | 'restore-complete' = 'welcome' + public backgroundStyle: string + public progress = 1 + public restoreInProgress = false + public restoreStarted = false + public restoreFailed = false + public loading = false + public selectedFile: File + public restoreUploading = false public createUserForm = new FormGroup({ username: new FormControl('', [Validators.required]), password: new FormControl('', [Validators.compose([Validators.required, Validators.minLength(4)])]), passwordConfirm: new FormControl('', [Validators.required]), }, this.matchPassword) - public loading = false - - public selectedFile: File - public restoreUploading = false + constructor( + private $api: ApiService, + private $auth: AuthService, + private $settings: SettingsService, + private $title: Title, + private $toastr: ToastrService, + private $translate: TranslateService, + private $ws: WsService, + ) {} + + async ngOnInit(): Promise { + this.$title.setTitle(this.$translate.instant('setup_wizard_page_title')) + await this.setBackground() + } - constructor() {} + async setBackground() { + if (!this.$settings.settingsLoaded) { + await firstValueFrom(this.$settings.onSettingsLoaded) + } - ngOnInit(): void { - this.previousTitle = this.$title.getTitle() - this.$title.setTitle('Setup Homebridge') + if (this.$settings.env.customWallpaperHash) { + const backgroundImageUrl = `${environment.api.base}/auth/wallpaper/${this.$settings.env.customWallpaperHash}` + this.backgroundStyle = `url('${backgroundImageUrl}') center/cover` + } } matchPassword(AC: AbstractControl) { @@ -66,113 +78,153 @@ export class SetupWizardComponent implements OnInit, OnDestroy { } } - ngOnDestroy() { - this.$title.setTitle(this.previousTitle) - } - onClickGettingStarted() { this.step = 'create-account' + this.progress = 50 } onClickRestoreBackup() { this.step = 'restore-backup' + this.progress = 20 } onClickCancelRestore() { this.selectedFile = null this.step = 'welcome' + this.progress = 1 } - createFirstUser() { + async createFirstUser() { this.loading = true + this.progress = 75 const payload = this.createUserForm.getRawValue() as Record payload.name = payload.username - this.$api.post('/setup-wizard/create-first-user', payload).subscribe({ - next: async () => { - this.$settings.env.setupWizardComplete = true - await this.$auth.login({ - username: payload.username, - password: payload.password, - }) - this.step = 'setup-complete' - }, - error: (error) => { - this.loading = false - console.error(error) - this.$toastr.error(error.error.message || this.$translate.instant('users.toast_failed_to_add_user'), this.$translate.instant('toast.title_error')) - }, - }) + try { + await firstValueFrom(this.$api.post('/setup-wizard/create-first-user', payload)) + this.$settings.env.setupWizardComplete = true + this.progress = 100 + this.loading = false + await this.$auth.login({ + username: payload.username, + password: payload.password, + }) + this.step = 'setup-complete' + } catch (error) { + this.loading = false + this.progress = 50 + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } } handleRestoreFileInput(files: FileList) { if (files.length) { this.selectedFile = files[0] + this.progress = 40 } else { delete this.selectedFile + this.progress = 20 } } - onRestoreBackupClick() { + async onRestoreBackupClick() { this.restoreUploading = true - this.uploadHomebridgeArchive() - } - - async uploadHomebridgeArchive() { + this.step = 'restoring' + this.progress = 60 try { - // Get and set a temporary access token + // get and set a temporary access token const authorization = await firstValueFrom(this.$api.get('/setup-wizard/get-setup-wizard-token')) window.localStorage.setItem(environment.jwt.tokenKey, authorization.access_token) this.$auth.token = authorization.access_token + this.progress = 65 - // Upload archive + // upload archive const formData: FormData = new FormData() formData.append('restoreArchive', this.selectedFile, this.selectedFile.name) await firstValueFrom(this.$api.post('/backup/restore', formData)) - - // Open restore modal - this.openRestoreModal() - this.restoreUploading = false + this.progress = 70 + + // start restore + this.io = this.$ws.connectToNamespace('backup') + const outputBox = document.getElementById('output') + this.io.socket.on('stdout', (data) => { + const lines = data.split('\n\r') + lines.forEach((line: string) => { + if (line && !/^[⠇⠏⠋⠙⠹⠸]+$/.test(line)) { // Ignore lines with invalid characters + const lineElement = document.createElement('div') + const regex = /\x1B\[(\d{1,2}(;\d{1,2})?)?[mGK]/g // eslint-disable-line no-control-regex + lineElement.innerHTML = line.replace(regex, '') + if (line.includes('[0;31m')) { + lineElement.classList.add('red-text') + } else if (line.includes('[0;32m')) { + lineElement.classList.add('green-text') + } else if (line.includes('[0;33m')) { + lineElement.classList.add('orange-text') + } else if (line.includes('[0;36m')) { + lineElement.classList.add('cyan-text') + } + outputBox.appendChild(lineElement) + outputBox.scrollTop = outputBox.scrollHeight + } + }) + }) + this.restoreStarted = true + this.restoreInProgress = true + this.progress = 75 + await firstValueFrom(this.io.request('do-restore')) + this.progress = 80 + this.restoreInProgress = false + await firstValueFrom(this.$api.put('/backup/restart', {})) + this.step = 'restarting' + this.progress = 85 + + // remove tokens + window.localStorage.removeItem(environment.jwt.tokenKey) + this.$auth.token = null + + // show final message in the terminal box + const restoreMessage = document.createElement('div') + restoreMessage.classList.add('orange-text') + restoreMessage.innerHTML = 'Starting Homebridge, please wait...' + outputBox.appendChild(restoreMessage) + outputBox.scrollTop = outputBox.scrollHeight + + // wait at least 15 seconds + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 88 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 91 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 94 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 97 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 99 + + const checkHomebridgeInterval = setInterval(async () => { + try { + await firstValueFrom(this.$api.get('/auth/settings')) + clearInterval(checkHomebridgeInterval) + this.progress = 100 + this.restoreUploading = false + this.step = 'restore-complete' + } catch (error) { + // not up yet + } + }, 1000) } catch (error) { - this.restoreUploading = false console.error(error) - this.$toastr.error(error.error.message || this.$translate.instant('users.toast_failed_to_add_user'), this.$translate.instant('toast.title_error')) - } - } - - openRestoreModal() { - const ref = this.$modal.open(RestoreComponent, { - size: 'lg', - backdrop: 'static', - }) - ref.componentInstance.setupWizardRestore = true - - ref.result.then((success) => { - if (success === true) { - this.waitForHomebridgeToRestart() - } - }) - } - - async waitForHomebridgeToRestart() { - this.step = 'restarting' - - // Remove tokens - window.localStorage.removeItem(environment.jwt.tokenKey) - this.$auth.token = null - - // Wait at least 15 seconds - await new Promise(resolve => setTimeout(resolve, 15000)) - - const checkHomebridgeInterval = setInterval(async () => { - try { - await firstValueFrom(this.$api.get('/auth/settings')) - clearInterval(checkHomebridgeInterval) - location.reload() - } catch (e) { - // Not up yet + this.restoreUploading = false + this.restoreFailed = true + this.progress = 20 + this.step = 'restore-backup' + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } finally { + if (this.io) { + this.io.end() } - }, 1000) + } } } diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 24c99f7e2..81ea6e04e 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Сканирайте, за да добавите към Homekit", "status.cpu.load": "Използва", "status.cpu.temp": "Темп.", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 2d6127aad..8f234e503 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Arxiu de còpia de seguretat restaurat", "backup.backup_warning": "Els arxius de còpia de seguretat contenen informació confidencial i no s'han de compartir amb els altres.", - "backup.button_restore_backup": "Restaurar còpia de seguretat", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Carregant…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Començar", "setup.create_account": "Crear Compte", - "setup.create_account_reason": "S'ha de configurar l'autenticació de contrasenya a la interfície web d'administració de Homebridge. Encara que Homebridge només sigui accessible a la teva xarxa local, és important protegir-lo de l'accés sense restriccions.", - "setup.open_dashboard": "Obriu Tauler", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Benvingut/da a Homebridge", - "setup_wizard_message_complete_message": "El procediment de configuració s'ha completat i ja estàs preparat per començar a utilitzar Homebridge.", - "setup_wizard_message_complete_title": "Felicitats!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Felicitats!", + "setup_wizard_completed": "El procediment de configuració s'ha completat i ja estàs preparat per començar a utilitzar Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Escaneja per afegir a HomeKit", "status.cpu.load": "Càrrega", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 76704e648..e17ddcfe6 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Vygenerujte a stáhněte si aktuální soubor zálohy", "backup.backup_restored": "Záloha byla obnovena", "backup.backup_warning": "Zálohy obsahují citlivé informace a neměly by být sdíleny s ostatními.", - "backup.button_restore_backup": "Obnovit zálohu", "backup.files_auto": "Předešlé automatické zálohy", "backup.label_uploading": "Nahrávám…", "backup.load_error": "Nepodařilo se načíst zálohu konfigurace.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Spárované mosty nelze načíst.", "setup.button_get_started": "Začněme", "setup.create_account": "Vytvořit Účet", - "setup.create_account_reason": "Do webového rozhraní správce Homebridge musí být nakonfigurováno ověřování heslem. I když je Homebridge přístupný pouze ve vaší místní síti, je stále důležité jej chránit před neomezeným přístupem.", - "setup.open_dashboard": "Otevřít Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Vítejte v rozhraní Homebridge", - "setup_wizard_message_complete_message": "Postup nastavení je dokončen. Nyní můžete začít používat Homebridge.", - "setup_wizard_message_complete_title": "Gratulujeme!", - "setup_wizard_message_restore": "Obnovit ze zálohy", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Gratulujeme!", + "setup_wizard_completed": "Postup nastavení je dokončen. Nyní můžete začít používat Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Obnovit ze zálohy", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Naskenováním přidejte do HomeKitu", "status.cpu.load": "Zatížení", "status.cpu.temp": "Teplota", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index 1c3da8f4c..079698c3d 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Erstelle und lade ein aktuelles Backup.", "backup.backup_restored": "Backup-Archiv wiederhergestellt", "backup.backup_warning": "Backup-Archive enhalten sensitive Informationen und sollten nicht mit anderen geteilt werden.", - "backup.button_restore_backup": "Backup wiederherstellen", "backup.files_auto": "Vorherige automatische Backups", "backup.label_uploading": "Lädt hoch …", "backup.load_error": "Config-Backup konnte nicht geladen werden.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Gepairte Bridge konnten nicht geladen werden.", "setup.button_get_started": "Los geht's", "setup.create_account": "Konto erstellen", - "setup.create_account_reason": "Die Passwortauthentifizierung für die Homebridge-Administrationsweboberfläche muss konfiguriert werden. Auch wenn Homebridge nur in deinem lokalen Netzwerk zugänglich ist, ist es wichtig, es vor ungehindertem Zugriff zu schützen.", - "setup.open_dashboard": "Dashboard öffnen", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Wilkommen bei Homebridge", - "setup_wizard_message_complete_message": "Der Einrichtungsvorgang ist abgeschlossen und du kannst Homebridge jetzt verwenden.", - "setup_wizard_message_complete_title": "Herzlichen Glückwunsch!", - "setup_wizard_message_restore": "Wiederherstellen aus Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Herzlichen Glückwunsch!", + "setup_wizard_completed": "Der Einrichtungsvorgang ist abgeschlossen und du kannst Homebridge jetzt verwenden.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Wiederherstellen aus Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannen, um es zu HomeKit hinzuzufügen", "status.cpu.load": "Auslastung", "status.cpu.temp": "Temperatur", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 7cf76e5ad..ce56d1811 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scan to add to HomeKit", "status.cpu.load": "Load", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 4a16a09b3..e4ec03fa9 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generar y descargar un archivo de copia de seguridad actualizado.", "backup.backup_restored": "Copia de seguridad restaurada", "backup.backup_warning": "Los archivos de copias de seguridad contienen información confidencial que no deberías compartir con otros.", - "backup.button_restore_backup": "Restaurar una copia de seguridad", "backup.files_auto": "Copias de Seguridad Automatizadas Anteriores", "backup.label_uploading": "Subiendo...", "backup.load_error": "Error al cargar la copia de seguridad de la configuración.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "No se pudieron cargar los puentes emparejados.", "setup.button_get_started": "Empezar", "setup.create_account": "Crear Cuenta", - "setup.create_account_reason": "Debe configurar una contraseña de autenticación para su interfaz web de Homebridge. Aunque Homebridge sea accesible solo desde la red local, es importante protegerlo de accesos no autorizados.", - "setup.open_dashboard": "Abrir Panel de Control", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bienvenido a Homebridge", - "setup_wizard_message_complete_message": "El procedimiento de configuración se ha completado y ya está listo para empezar a utilizar Homebridge.", - "setup_wizard_message_complete_title": "¡Felicidades!", - "setup_wizard_message_restore": "Restaurar desde Copia de Seguridad", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "¡Felicidades!", + "setup_wizard_completed": "El procedimiento de configuración se ha completado y ya está listo para empezar a utilizar Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restaurar desde Copia de Seguridad", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Escanear para agregar a HomeKit.", "status.cpu.load": "Carga", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index fb3622b79..4db28522a 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Varmuuskopio palautettu", "backup.backup_warning": "Varmuuskopio sisältää arkaluontoista tietoa, älä jaa sitä muille.", - "backup.button_restore_backup": "Palauta varmuuskopio", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Ladataan", "backup.load_error": "Asetus varmuuskopion lataus epäonnistui.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paritettuja siltoja ei voitu otta käyttöön.", "setup.button_get_started": "Aloitetaan", "setup.create_account": "Luo käyttäjätunnus", - "setup.create_account_reason": "Kirjautuminen Homebridgen web hallintaan täytyy määritellä. Vaikka Homebridge on vain omassa lähiverkossasi on siltikin tärkeää estää rajoittamaton pääsy järjestelmään.", - "setup.open_dashboard": "Avaa käyttöpaneeli", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Tervetuloa Homebridge järjestelmään", - "setup_wizard_message_complete_message": "Asetukset ovat valmiit ja Homebridge on valmis käyttöön.", - "setup_wizard_message_complete_title": "Onnea!", - "setup_wizard_message_restore": "Palauta varmuuskopiosta", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Onnea!", + "setup_wizard_completed": "Asetukset ovat valmiit ja Homebridge on valmis käyttöön.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Palauta varmuuskopiosta", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skannaa lisätäksesi HomeKit järjestelmään", "status.cpu.load": "Käyttöaste", "status.cpu.temp": "Lämpötila", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 6c6eb0e95..7a6174fc5 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Archive de sauvegarde restaurée", "backup.backup_warning": "Les archives de sauvegarde contiennent des informations sensibles et ne doivent pas être partagées à des tiers.", - "backup.button_restore_backup": "Restaurer une Sauvegarde", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Envoi en cours…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Démarrer", "setup.create_account": "Créer un Compte", - "setup.create_account_reason": "Le Mot de passe d'authentification à l'interface d'administration d'Homebridge doit être configuré. Même si Homebridge n'est accessible que depuis votre réseau local, il est important de protégér son accès.", - "setup.open_dashboard": "Ouvrir le Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bienvenue sur Homebridge", - "setup_wizard_message_complete_message": "La procédure d'installation est terminée et vous êtes maintenant prêt à utiliser Homebridge.", - "setup_wizard_message_complete_title": "Félicitations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Félicitations!", + "setup_wizard_completed": "La procédure d'installation est terminée et vous êtes maintenant prêt à utiliser Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannez pour ajouter à HomeKit", "status.cpu.load": "Charge", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 9835be71a..c327c7d5f 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "גיבוי שחזור", "backup.backup_warning": "גיבוי מכיל מידע רגיש ולא אמור להיות משותף עם אנשים אחרים", - "backup.button_restore_backup": "שחזר מגיבוי", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "מעלה…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "סרוק כדי להוסיף ל-HomeKit", "status.cpu.load": "עומס", "status.cpu.temp": "טמפרטורה", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index 75023d5df..2d8ef7a1a 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Szkennelje be, hogy hozzáadja a HomeKit", "status.cpu.load": "Terhelés", "status.cpu.temp": "Hőmérséklet", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 81f6f3afb..25cc4c68e 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Buat dan unduh file cadangan terbaru.", "backup.backup_restored": "Arsip Cadangan Dipulihkan", "backup.backup_warning": "Arsip cadangan berisikan informasi sensitif dan sebaiknya tidak dibagikan kepada orang lain.", - "backup.button_restore_backup": "Pulihkan Cadangan", "backup.files_auto": "Pencadangan Otomatis Sebelumnya", "backup.label_uploading": "Mengunggah…", "backup.load_error": "Gagal memuat cadangan konfigurasi.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Jembatan berpasangan tidak dapat dimuat.", "setup.button_get_started": "Mulai", "setup.create_account": "Buat akun", - "setup.create_account_reason": "Otentikasi kata sandi untuk antarmuka web admin homebridge Anda harus dikonfigurasi. Bahkan jika Homebridge hanya dapat diakses di jaringan lokal Anda, masih penting untuk melindunginya dari akses tidak terbatas.", - "setup.open_dashboard": "Buka Dasbor", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Selamat datang di Homebridge", - "setup_wizard_message_complete_message": "Prosedur pengaturan selesai dan Anda sekarang siap untuk mulai menggunakan Homebridge.", - "setup_wizard_message_complete_title": "Selamat!", - "setup_wizard_message_restore": "Kembalikan dari cadangan", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Selamat!", + "setup_wizard_completed": "Prosedur pengaturan selesai dan Anda sekarang siap untuk mulai menggunakan Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Kembalikan dari cadangan", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Pindai untuk menambahkan ke HomeKit", "status.cpu.load": "Beban", "status.cpu.temp": "Suhu", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 3801e4cea..5065dc54d 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Archivio di backup ripristinato", "backup.backup_warning": "Gli archivi di backup contengono informazioni sensibili e non dovrebbero essere condivisi con altre persone.", - "backup.button_restore_backup": "Ripristina Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Caricamento in corso…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Inizia", "setup.create_account": "Crea un account utente", - "setup.create_account_reason": "È necessario configurare una password di autenticazione per l'interfaccia web di amministrazione di Homebridge. Anche se Homebridge è accessibile solo dalla rete locale, è comunque importante proteggerlo da accessi non autorizzati.", - "setup.open_dashboard": "Apri la dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Benvenuto in Homebridge", - "setup_wizard_message_complete_message": "La procedura di configurazione è stata completata ed è ora possibile iniziare a utilizzare Homebridge.", - "setup_wizard_message_complete_title": "Congratulazioni!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulazioni!", + "setup_wizard_completed": "La procedura di configurazione è stata completata ed è ora possibile iniziare a utilizzare Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scansiona per aggiungere a HomeKit", "status.cpu.load": "Carico della CPU", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 4129e882d..0f994944c 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "バックアップアーカイブを復元しました", "backup.backup_warning": "バックアップアーカイブには機密情報が含まれているため、第三者と共有することは推奨しません。", - "backup.button_restore_backup": "バックアップを復元", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "アップロード中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "さぁ、始めよう!", "setup.create_account": "アカウントを作成", - "setup.create_account_reason": "Homebridgeの管理者用Webインターフェイスへのパスワード認証を設定する必要があります。Homebridgeがローカルネットワークでのみアクセス可能な場合でも、不正なアクセスから保護することが重要です。", - "setup.open_dashboard": "ダッシュボードを開く", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Homebridgeへようこそ!", - "setup_wizard_message_complete_message": "これでセットアップは完了です。Homebridgeを使用できます!", - "setup_wizard_message_complete_title": "おめでとう!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "おめでとう!", + "setup_wizard_completed": "これでセットアップは完了です。Homebridgeを使用できます!", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "スキャンして HomeKit に追加します", "status.cpu.load": "負荷", "status.cpu.temp": "温度", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 4649229e3..e8ec9d11f 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "백업 기록파일 복원됨", "backup.backup_warning": "백업 기록파일에는 민감한 정보가 포함되어 있기 때문에 다른사람과 공유해서는 안됩니다.", - "backup.button_restore_backup": "백업 복원", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "업로드 중…", "backup.load_error": "설정 백업을 로드하지 못했습니다.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "페어링된 Bridge를 불러오는 데 실패했습니다.", "setup.button_get_started": "설치 마법사 시작", "setup.create_account": "계정 생성", - "setup.create_account_reason": "Homebridge 관리자 페이지 비밀번호를 설정하세요. Homebridge를 로컬 네트워크에서만 사용하는 경우라도 해커의 표적이 될 수 있습니다. 꼭 비밀번호를 설정 후 사용하세요.", - "setup.open_dashboard": "대시보드 열기", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Homebridge에 오신 것을 환영합니다", - "setup_wizard_message_complete_message": "설치가 완료되었습니다. 이제 Homebridge를 사용할 준비가 되었습니다.", - "setup_wizard_message_complete_title": "축하합니다!", - "setup_wizard_message_restore": "백업에서 복원하기", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "축하합니다!", + "setup_wizard_completed": "설치가 완료되었습니다. 이제 Homebridge를 사용할 준비가 되었습니다.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "백업에서 복원하기", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "HomeKit에 추가하려면 스캔하세요", "status.cpu.load": "로드", "status.cpu.temp": "온도", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index b6abd9e21..c81c93bbf 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Поратена бекап архива", "backup.backup_warning": "Бекап архивите содржат сензитивни информации и не треба да се споделуваат.", - "backup.button_restore_backup": "Поврати бекап", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Се прикачува…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Скенирајте за да додадете во HomeKit", "status.cpu.load": "Товар", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 339b00c78..0e06449b3 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archief Teruggeplaatst", "backup.backup_warning": "Backup archieven bevatten gevoelige informatie en moeten niet met anderen worden gedeelt.", - "backup.button_restore_backup": "Backup Terugplaatsen", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Aan het uploaden…", "backup.load_error": "Laden van configuratie backup is mislukt.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Gekoppelde bridges konden niet geladen worden.", "setup.button_get_started": "Beginnen", "setup.create_account": "Account aanmaken", - "setup.create_account_reason": "Wachtwood authenticatie voor de Homebridge admin web interface moet geconfigureerd worden. Ook als Homebridge alleen toegankelijk is in Uw lokale netwerk, is het nog steeds belangrijk om te beveiligen tegen onbeperkte toegang.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welkom bij Homebridge", - "setup_wizard_message_complete_message": "De setup procedure is compleet and U bent nu klaar om gebruik te maken van Homebridge.", - "setup_wizard_message_complete_title": "Felicitaties!", - "setup_wizard_message_restore": "Herstel vanuit Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Felicitaties!", + "setup_wizard_completed": "De setup procedure is compleet and U bent nu klaar om gebruik te maken van Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Herstel vanuit Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannen om toe te voegen aan HomeKit.", "status.cpu.load": "Belasting", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index fb89f2ed5..e4ab789ba 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skann for å legge til HomeKit", "status.cpu.load": "Bruk", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 541d3f69e..fd40ddf54 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Przywracanie backupu zakończone sukcesem", "backup.backup_warning": "Backup zawiera ważne informacje i nie powinien być udostępniany nikomu.", - "backup.button_restore_backup": "Przywróć z backupu", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Przywracanie…", "backup.load_error": "Nie udało się załadować backupu.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Nie można było załadować sparowanych mostków.", "setup.button_get_started": "Rozpocznij", "setup.create_account": "Utwórz konto", - "setup.create_account_reason": "Hasło administratora do interfejsu Homebridge musi zostać utworzone. Obojętnie czy Homebridge jest dostępny tylko w sieci lokalnej, wymagane jest zabezpieczenie go przed nieautoryzowanym dostępem.", - "setup.open_dashboard": "Otwórz dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Witaj w Homebridge", - "setup_wizard_message_complete_message": "Procedura została zakończona, możesz zacząć używać Homebridge.", - "setup_wizard_message_complete_title": "Gratulacje!", - "setup_wizard_message_restore": "Przywróć z backupu", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Gratulacje!", + "setup_wizard_completed": "Procedura została zakończona, możesz zacząć używać Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Przywróć z backupu", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Zeskanuj aby dodać do HomeKit", "status.cpu.load": "Obciążenie", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index a8c2bf364..4e35f1a73 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Arquivo de Backup Restaurado", "backup.backup_warning": "Os arquivos de backup possuem informações privadas e não devem de ser compartilhados com outras pessoas.", - "backup.button_restore_backup": "Restaurar Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Enviando…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Digitalize para adicionar ao HomeKit", "status.cpu.load": "Utilização", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index d02c1b9f8..887c6e296 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Ficheiro de Backup Restaurado", "backup.backup_warning": "Os ficheiro de backup contem informação privada e não devem de ser partilhados com outros.", - "backup.button_restore_backup": "Restaurar Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "A Enviar…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Começar", "setup.create_account": "Criar Conta", - "setup.create_account_reason": "A autenticação por palavra-passe deverá de ser configurada para a página de administração do Homebridge. Mesmo que o Homebridge seja acessível apenas na rede local, é importante protege-lo de acessos não autorizados.", - "setup.open_dashboard": "Abrir Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bem-vindo ao Homebridge", - "setup_wizard_message_complete_message": "O processo de configuração está concluído e está pronto para utilizar o Homebridge.", - "setup_wizard_message_complete_title": "Parabéns!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Parabéns!", + "setup_wizard_completed": "O processo de configuração está concluído e está pronto para utilizar o Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Digitalize para adicionar ao HomeKit", "status.cpu.load": "Utilização", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index aae991770..3976f41f4 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Создать и скачать актуальный файл резервной копии.", "backup.backup_restored": "Архив резервной копии восстановлен", "backup.backup_warning": "Архивы резервных копий содержат конфиденциальную информацию и не должны передаваться третьим лицам.", - "backup.button_restore_backup": "Восстановить из резервной копии", "backup.files_auto": "Предыдущие автоматические копии", "backup.label_uploading": "Загрузка…", "backup.load_error": "Ошибка загрузки конфигурации резервной копии.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Не удалось загрузить привязанные мосты.", "setup.button_get_started": "Начать работу", "setup.create_account": "Создать аккаунт", - "setup.create_account_reason": "Необходимо настроить аутентификацию по паролю для вашего веб-интерфейса администратора Homebridge. Даже если Homebridge доступен только в вашей локальной сети, важно защитить его от неограниченного доступа.", - "setup.open_dashboard": "Открыть панель управления", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Добро пожаловать в Homebridge", - "setup_wizard_message_complete_message": "Процедура настройки завершена, вы готовы начать использовать Homebridge.", - "setup_wizard_message_complete_title": "Поздравляем!", - "setup_wizard_message_restore": "Восстановить из резервной копии", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Поздравляем!", + "setup_wizard_completed": "Процедура настройки завершена, вы готовы начать использовать Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Восстановить из резервной копии", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Сканируйте для добавления в HomeKit", "status.cpu.load": "Нагрузка", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index 2e5c98437..da7199576 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Varnostno kopiranje arhiva obnovljeno", "backup.backup_warning": "Rezervni arhivi vsebujejo občutljive podatke in jih ne smete deliti z drugimi.", - "backup.button_restore_backup": "Obnovi varnostno kopijo", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Nalaganje …", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skenirajte za dodajanje v HomeKit", "status.cpu.load": "Naloži", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index e2171398c..312cbac57 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Säkerhetskopia återställd", "backup.backup_warning": "Säkerhetskopian innehåller känslig information och bör inte delas med andra.", - "backup.button_restore_backup": "Återställ säkerhetskopia", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Laddar upp…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Kom igång", "setup.create_account": "Skapa konto", - "setup.create_account_reason": "Lösenordsautentisering till ditt Homebridge admin-webbgränssnitt måste konfigureras. Även om Homebridge endast kan nås i ditt lokala nätverk är det fortfarande viktigt att skydda den från obehörig åtkomst.", - "setup.open_dashboard": "Öppna instrumentpanel", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Välkommen till Homebridge", - "setup_wizard_message_complete_message": "Installationsprocessen är klar och du kan nu börja använda Homebridge.", - "setup_wizard_message_complete_title": "Grattis!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Grattis!", + "setup_wizard_completed": "Installationsprocessen är klar och du kan nu börja använda Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skanna för att lägga till i HomeKit", "status.cpu.load": "Används", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 96b87e876..94e10b32a 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "สร้างและดาวน์โหลดไฟล์สำรองข้อมูลที่อัปเดต", "backup.backup_restored": "กู้คืนที่เก็บข้อมูลสำรองแล้ว", "backup.backup_warning": "คลังข้อมูลสำรองมีข้อมูลที่ละเอียดอ่อนและไม่ควรแชร์กับผู้อื่น", - "backup.button_restore_backup": "คืนค่าการสำรองข้อมูล", "backup.files_auto": "การสำรองข้อมูลอัตโนมัติก่อนหน้านี้", "backup.label_uploading": "กำลังอัปโหลด…", "backup.load_error": "ไม่สามารถโหลดการสำรองข้อมูลการกำหนดค่าได้", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "บริดจ์จับคู่ไม่สามารถโหลดได้", "setup.button_get_started": "เริ่ม", "setup.create_account": "สร้างบัญชี", - "setup.create_account_reason": "การตรวจสอบรหัสผ่านสำหรับเว็บอินเตอร์เฟสผู้ดูแลระบบ Homebridge ของคุณต้องได้รับการกำหนดค่า แม้ว่า Homebridge จะสามารถเข้าถึงได้เฉพาะในเครือข่ายท้องถิ่นของคุณ ก็ยังเป็นสิ่งสำคัญที่จะต้องปกป้องจากการเข้าถึงที่ไม่จำกัด", - "setup.open_dashboard": "เปิดแดชบอร์ด", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "ยินดีต้อนรับสู่ Homebridge", - "setup_wizard_message_complete_message": "ขั้นตอนการตั้งค่าเสร็จสมบูรณ์ และตอนนี้คุณก็พร้อมที่จะเริ่มใช้ Homebridge แล้ว", - "setup_wizard_message_complete_title": "ยินดีด้วย!", - "setup_wizard_message_restore": "กู้คืนจากการสำรองข้อมูล", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "ยินดีด้วย!", + "setup_wizard_completed": "ขั้นตอนการตั้งค่าเสร็จสมบูรณ์ และตอนนี้คุณก็พร้อมที่จะเริ่มใช้ Homebridge แล้ว", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "กู้คืนจากการสำรองข้อมูล", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "สแกนเพื่อเพิ่มลงใน HomeKit", "status.cpu.load": "โหลด", "status.cpu.temp": "อุณหภูมิ", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index b6f098262..2988dbbc8 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Yedekleme Arşivi Geri Yüklendi", "backup.backup_warning": "Yedekleme arşivleri hassas bilgiler barındırırlar ve başka kişilerle paylaşılmamalıdırlar.", - "backup.button_restore_backup": "Yedeği Geri Yükle", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Yükleniyor…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "HomeKit'e eklemek için tarayın", "status.cpu.load": "Yükle", "status.cpu.temp": "Sıcaklık", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 728160d55..43693817e 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Створіть і завантажте оновлений файл резервної копії.", "backup.backup_restored": "Резервна копія відновлена", "backup.backup_warning": "Архіви резервних копій містять конфіденціїну інформацію і не повинні передаватись іншим особам.", - "backup.button_restore_backup": "Відновити", "backup.files_auto": "Попередні автоматичні резервні копії", "backup.label_uploading": "Завантаження…", "backup.load_error": "Не вдалося завантажити резервну копію конфігурації.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Не вдалося завантажити парні мости.", "setup.button_get_started": "Розпочати", "setup.create_account": "Створити обліковий запис", - "setup.create_account_reason": "Необхідно налаштувати автентифікацію за допомогою пароля для веб-інтерфейсу адміністратора Homebridge. Навіть якщо Homebridge доступний тільки у Вашій локальній мережі, важливо захистити його від необмеженого доступу.", - "setup.open_dashboard": "Відкрийте панель приладів", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Ласкаво просимо до Homebridge", - "setup_wizard_message_complete_message": "Процедуру встановлення завершено, тепер Ви можете почати використовувати Homebridge.", - "setup_wizard_message_complete_title": "Вітаємо!", - "setup_wizard_message_restore": "Відновити з резервної копії", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Вітаємо!", + "setup_wizard_completed": "Процедуру встановлення завершено, тепер Ви можете почати використовувати Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Відновити з резервної копії", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Скануйте, щоб додати до HomeKit", "status.cpu.load": "Завантаження", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index c2d14ce60..00b3af8b3 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "已从备份档案中恢复", "backup.backup_warning": "备份文档包含了敏感信息,请勿与他人共享。", - "backup.button_restore_backup": "恢复备份", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "上传中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "扫描添加到HomeKit", "status.cpu.load": "负载", "status.cpu.temp": "温度", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index a80b77ed4..a6c0f76ad 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "備份檔案已回復", "backup.backup_warning": "備份檔案包含敏感資訊、請不要隨意與其他人共享。", - "backup.button_restore_backup": "回復備份", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "上傳中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "掃描加入到HomeKit", "status.cpu.load": "負載", "status.cpu.temp": "溫度", diff --git a/ui/src/scss/base/layout.scss b/ui/src/scss/base/layout.scss index f2f802fea..3eb5ee25a 100644 --- a/ui/src/scss/base/layout.scss +++ b/ui/src/scss/base/layout.scss @@ -38,6 +38,11 @@ a:focus { color: #4caf50 !important; } +.cyan-text, +.cyan-text a { + color: #00bcd4 !important; +} + .red-text, .red-text a { color: #ff0000 !important; diff --git a/ui/src/scss/themes/themes-dark.scss b/ui/src/scss/themes/themes-dark.scss index c65ad1bc8..195accfb4 100644 --- a/ui/src/scss/themes/themes-dark.scss +++ b/ui/src/scss/themes/themes-dark.scss @@ -174,7 +174,8 @@ background-color: $secondaryBackground !important; } - .login-card { + .login-card, + .setup-card { background-color: rgba($secondaryBackground, 0.97) !important; } diff --git a/ui/src/scss/themes/themes-light.scss b/ui/src/scss/themes/themes-light.scss index 948e5e254..3274f9e8e 100644 --- a/ui/src/scss/themes/themes-light.scss +++ b/ui/src/scss/themes/themes-light.scss @@ -74,6 +74,11 @@ color: $primary; } + .grey-text, + .grey-text a { + color: #666666 !important; + } + .btn-primary, .btn-default { background-color: $primary !important; From b9b155648280395ebc6c3c7bd576358e16cb647b Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 7 Jun 2025 23:24:03 +0100 Subject: [PATCH 16/40] on uninstall plugin, only offer to remove config when exists --- .../uninstall-plugin/uninstall-plugin.component.html | 4 ++-- .../uninstall-plugin/uninstall-plugin.component.ts | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html index 1ef7a5b02..d9b80955c 100644 --- a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html +++ b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html @@ -20,7 +20,7 @@
    - @if (pluginAlias && pluginType) { + @if (isConfigured) {

  • {{ 'plugins.uninstall_warn_1' | translate }}
  • {{ 'plugins.uninstall_warn_2' | translate }}
  • - } @if (!pluginAlias || !pluginType) { + } @if (isConfigured && (!pluginAlias || !pluginType)) { {{ 'plugins.uninstall_remove_config_required' | translate }} diff --git a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts index 0ad8c0a54..9245f3203 100644 --- a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts @@ -35,6 +35,7 @@ export class UninstallPluginComponent implements OnInit { public removeConfig = true public removeChildBridges = true public hasChildBridges = false + public isConfigured = false public pluginType: 'platform' | 'accessory' public pluginAlias: string @@ -50,6 +51,11 @@ export class UninstallPluginComponent implements OnInit { const schema = await this.getAlias() this.pluginType = schema.pluginType this.pluginAlias = schema.pluginAlias + + const existingConfig = await firstValueFrom(this.$api.get(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`)) + if (existingConfig.length) { + this.isConfigured = true + } } finally { this.loading = false } @@ -59,7 +65,7 @@ export class UninstallPluginComponent implements OnInit { this.uninstalling = true // Remove the plugin config if exists and specified by the user - if (this.removeConfig && this.pluginType && this.pluginAlias) { + if (this.removeConfig && this.isConfigured) { try { await this.removePluginConfig() } catch (error) { From 26ab8c608102cba2a611cc988b0e7b18c21dd023 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:59:55 +0100 Subject: [PATCH 17/40] style HBv2/UIv5 icons on status page based on readiness --- CHANGELOG.md | 1 + .../update-info-widget.component.html | 10 ++++++-- .../update-info-widget.component.ts | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2fe8b917..627ac9322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - updates to the `th.json` language file (#2472) (@tomzt) - auto restart after version change of hb or ui - redesigned setup wizard page +- style HBv2/UIv5 icons on status page based on readiness ### Homebridge Dependencies diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html index 284491836..9e70bd154 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html @@ -36,7 +36,10 @@ placement="top" aria-label="Homebridge v2 Readiness" > - + } } @if (!homebridgePkg.installedVersion) { Homebridge @@ -89,7 +92,10 @@ placement="top" aria-label="Homebridge UI v5 Readiness" > - + } } @if (!homebridgeUiPkg.installedVersion) { Homebridge UI diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts index ce188f8b4..114d8799d 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts @@ -6,6 +6,7 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' +import { ApiService } from '@/app/core/api.service' import { InformationComponent } from '@/app/core/components/information/information.component' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' @@ -25,6 +26,7 @@ import { UiV5ModalComponent } from '@/app/modules/status/widgets/update-info-wid ], }) export class UpdateInfoWidgetComponent implements OnInit { + private $api = inject(ApiService) private $modal = inject(NgbModal) $plugin = inject(ManagePluginsService) $settings = inject(SettingsService) @@ -45,6 +47,9 @@ export class UpdateInfoWidgetComponent implements OnInit { public isRunningHbV2 = false public isRunningUiV5 = false + public isHbV2Ready = false + public isUiV5Ready = false + private io: IoNamespace constructor() {} @@ -69,6 +74,20 @@ export class UpdateInfoWidgetComponent implements OnInit { this.getNodeInfo(), ]) } + + this.isHbV2Ready = this.homebridgeUiPkg.readyForV5.node + + if (!this.isRunningHbV2) { + const installedPlugins = await firstValueFrom(this.$api.get('/plugins')) + const allHb2Ready = installedPlugins + .filter((x: any) => x.name !== 'homebridge-config-ui-x') + .every((x: any) => { + const hbEngines = x.engines?.homebridge?.split('||').map((s: string) => s.trim()) || [] + return hbEngines.some((v: string) => v.startsWith('^2') || v.startsWith('>=2')) + }) + + this.isHbV2Ready = this.isHbV2Ready && allHb2Ready + } } async checkHomebridgeVersion() { @@ -101,6 +120,10 @@ export class UpdateInfoWidgetComponent implements OnInit { this.homebridgeUiPkg = response this.$settings.env.homebridgeUiVersion = response.installedVersion this.isRunningUiV5 = response.installedVersion.startsWith('5.') + this.isUiV5Ready = this.homebridgeUiPkg.readyForV5.node + && this.homebridgeUiPkg.readyForV5.service + && this.homebridgeUiPkg.readyForV5.pnpm + && this.homebridgeUiPkg.readyForV5.arch } catch (error) { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) From ba787d0a9cbed24bcf96fbf5b3355f2d7a5a4d67 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:34:44 +0100 Subject: [PATCH 18/40] security system modal only show valid modes --- CHANGELOG.md | 1 + .../lightbulb/lightbulb.manage.component.html | 4 +- .../securitysystem.component.html | 18 ++- .../securitysystem.manage.component.html | 18 +++ .../securitysystem.manage.component.ts | 2 + .../hap-icons/securitysystem-active.svg | 2 +- .../hap-icons/securitysystem-triggered.svg | 103 ++++++++++++++++++ ui/src/scss/base/buttons.scss | 2 +- ui/src/scss/themes/themes-light.scss | 7 ++ 9 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 ui/src/assets/hap-icons/securitysystem-triggered.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 627ac9322..8e4bb8d49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - auto restart after version change of hb or ui - redesigned setup wizard page - style HBv2/UIv5 icons on status page based on readiness +- security system modal only show valid modes ### Homebridge Dependencies diff --git a/ui/src/app/core/accessories/types/lightbulb/lightbulb.manage.component.html b/ui/src/app/core/accessories/types/lightbulb/lightbulb.manage.component.html index 273b01fef..e6d54b3e3 100644 --- a/ui/src/app/core/accessories/types/lightbulb/lightbulb.manage.component.html +++ b/ui/src/app/core/accessories/types/lightbulb/lightbulb.manage.component.html @@ -29,10 +29,12 @@

    {{ 'platform.docker.title_restarting' | translate }}

    - @if (!error) { -

    {{ 'restart.please_wait_while_server_restarts' | translate }}

    - } @if (error) { + @if (error) {
    {{ error }}
    - } @if (!this.error) { + } @else { +

    {{ 'restart.please_wait_while_server_restarts' | translate }}

    diff --git a/ui/src/app/modules/restart/restart.component.html b/ui/src/app/modules/restart/restart.component.html index bdbe2c403..907d09578 100644 --- a/ui/src/app/modules/restart/restart.component.html +++ b/ui/src/app/modules/restart/restart.component.html @@ -8,11 +8,10 @@

    {{ 'menu.restart.title' | translate }}

    {{ 'restart.title_restart' | translate }}

    - @if (!error) { -

    {{ 'restart.please_wait_while_server_restarts' | translate }}

    - } @if (error) { + @if (error) {
    {{ error }}
    - } @if (!this.error) { + } @else { +

    {{ 'restart.please_wait_while_server_restarts' | translate }}

    diff --git a/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.html b/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.html new file mode 100644 index 000000000..a14e5e207 --- /dev/null +++ b/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.html @@ -0,0 +1,117 @@ + diff --git a/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.ts b/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.ts new file mode 100644 index 000000000..f9f9e7563 --- /dev/null +++ b/ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.ts @@ -0,0 +1,91 @@ +import { NgClass, TitleCasePipe } from '@angular/common' +import { Component, inject, Input, OnInit } from '@angular/core' +import { FormsModule } from '@angular/forms' +import { NgbActiveModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { TranslatePipe, TranslateService } from '@ngx-translate/core' +import { ToastrService } from 'ngx-toastr' +import { firstValueFrom } from 'rxjs' + +import { ApiService } from '@/app/core/api.service' +import { SettingsService } from '@/app/core/settings.service' + +@Component({ + templateUrl: './accessory-control-lists.component.html', + standalone: true, + imports: [ + NgClass, + TranslatePipe, + FormsModule, + TitleCasePipe, + NgbTooltip, + ], +}) +export class AccessoryControlListsComponent implements OnInit { + $activeModal = inject(NgbActiveModal) + private $api = inject(ApiService) + private $settings = inject(SettingsService) + private $toastr = inject(ToastrService) + private $translate = inject(TranslateService) + + private originalBlacklist: string[] = [] + private updatedBlacklist: string[] = [] + + @Input() existingBlacklist: string[] = [] + + public clicked: boolean = false + public mainPairing: any = {} + public pairings: any[] = [] + + constructor() {} + + get blacklistHasUpdated() { + return this.updatedBlacklist.join(',') !== this.originalBlacklist.join(',') + } + + async ngOnInit(): Promise { + this.updatedBlacklist = this.existingBlacklist + .map(x => x.trim().toUpperCase()) + .sort((a, b) => a.localeCompare(b)) + this.originalBlacklist = [...this.updatedBlacklist] + + try { + const pairings = await firstValueFrom(this.$api.get('/server/pairings')) + this.mainPairing = pairings.find(p => p._main) + this.pairings = pairings + .filter(p => !p._main) + .sort((a, b) => a.name.localeCompare(b.name)) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.$activeModal.close() + } + } + + toggleList(username: string) { + if (this.updatedBlacklist.includes(username)) { + this.updatedBlacklist = this.updatedBlacklist.filter(x => x !== username) + } else { + this.updatedBlacklist.push(username) + this.updatedBlacklist.sort((a, b) => a.localeCompare(b)) + } + } + + isInList(username: string) { + return this.updatedBlacklist.includes(username) + } + + async updateBlacklist() { + this.clicked = true + try { + await firstValueFrom(this.$api.put('/config-editor/ui/accessory-control/instance-blacklist', { + body: this.updatedBlacklist, + })) + this.$settings.setEnvItem('accessoryControl.instanceBlacklist', this.updatedBlacklist) + this.$activeModal.close() + } catch (error) { + this.clicked = false + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } +} diff --git a/ui/src/app/modules/settings/backup/backup.component.ts b/ui/src/app/modules/settings/backup/backup.component.ts index 349738170..a1ec7b4f9 100644 --- a/ui/src/app/modules/settings/backup/backup.component.ts +++ b/ui/src/app/modules/settings/backup/backup.component.ts @@ -1,6 +1,7 @@ import { DatePipe, NgClass } from '@angular/common' import { Component, inject, OnInit } from '@angular/core' import { FormControl, ReactiveFormsModule } from '@angular/forms' +import { Router } from '@angular/router' import { NgbActiveModal, NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { saveAs } from 'file-saver' @@ -27,15 +28,17 @@ export class BackupComponent implements OnInit { $activeModal = inject(NgbActiveModal) private $api = inject(ApiService) private $modal = inject(NgbModal) + private $router = inject(Router) private $settings = inject(SettingsService) private $toastr = inject(ToastrService) private $translate = inject(TranslateService) + private restartToastIsShown = false + public clicked = false public scheduledBackups = [] public backupTime: string public deleting = null - public currentSettingEnabled = false public currentSettingPath = '' public enabledFormControl = new FormControl(false) @@ -54,14 +57,14 @@ export class BackupComponent implements OnInit { this.pathFormControl.patchValue(this.currentSettingPath) this.enabledFormControl.valueChanges - .pipe(debounceTime(400)) + .pipe(debounceTime(750)) .subscribe(async (value) => { this.currentSettingEnabled = value await this.saveUiSettingChange('scheduledBackupDisable', !this.currentSettingEnabled) }) this.pathFormControl.valueChanges - .pipe(debounceTime(400)) + .pipe(debounceTime(1500)) .subscribe(async (value) => { this.currentSettingPath = value await this.saveUiSettingChange('scheduledBackupPath', this.currentSettingPath) @@ -71,6 +74,7 @@ export class BackupComponent implements OnInit { async saveUiSettingChange(key: string, value: any) { try { await firstValueFrom(this.$api.put('/config-editor/ui', { key, value })) + this.showRestartToast() } catch (error) { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) @@ -168,5 +172,28 @@ export class BackupComponent implements OnInit { }) } + showRestartToast() { + if (!this.restartToastIsShown) { + this.restartToastIsShown = true + const ref = this.$toastr.info( + this.$translate.instant('settings.changes.saved'), + this.$translate.instant('menu.hbrestart.title'), + { + timeOut: 0, + tapToDismiss: true, + disableTimeOut: true, + positionClass: 'toast-bottom-right', + enableHtml: true, + }, + ) + + if (ref && ref.onTap) { + ref.onTap.subscribe(() => { + this.$router.navigate(['/restart']) + }) + } + } + } + protected readonly Date = Date } diff --git a/ui/src/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component.html b/ui/src/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component.html index 82d58458f..21e2ae493 100644 --- a/ui/src/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component.html +++ b/ui/src/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component.html @@ -40,7 +40,7 @@ }" > {{ (item._isPaired ? 'status.widget.qr_paired' : 'status.widget.qr_unpaired') | translate }} · - {{item._username }} + {{ item._username }}
    -
    diff --git a/ui/src/app/modules/settings/select-network-interfaces/select-network-interfaces.component.ts b/ui/src/app/modules/settings/select-network-interfaces/select-network-interfaces.component.ts index 0c1f23171..70b4d3928 100644 --- a/ui/src/app/modules/settings/select-network-interfaces/select-network-interfaces.component.ts +++ b/ui/src/app/modules/settings/select-network-interfaces/select-network-interfaces.component.ts @@ -1,8 +1,33 @@ -import { Component, inject, Input } from '@angular/core' +import { Component, inject, Input, OnInit } from '@angular/core' import { FormsModule } from '@angular/forms' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe } from '@ngx-translate/core' +interface NetworkAdapterAvailable { + carrierChanges?: number + default?: boolean + dhcp?: boolean + dnsSuffix?: string + duplex?: string + ieee8021xAuth?: string + ieee8021xState?: string + iface: string + ifaceName: string + internal: boolean + ip4: string + ip4subnet: string + ip6: string + ip6subnet: string + mac: string + mtu: number + missing?: boolean + operstate: string + selected?: boolean + speed: number + type: string + virtual?: boolean +} + @Component({ templateUrl: './select-network-interfaces.component.html', standalone: true, @@ -11,17 +36,29 @@ import { TranslatePipe } from '@ngx-translate/core' TranslatePipe, ], }) -export class SelectNetworkInterfacesComponent { +export class SelectNetworkInterfacesComponent implements OnInit { $activeModal = inject(NgbActiveModal) - @Input() availableNetworkAdapters: any[] = [] - @Input() bridgeNetworkAdapters: string[] = [] + @Input() adaptersAvailable: NetworkAdapterAvailable[] = [] + + private adaptersOriginal: string[] = [] + + public isUnchanged = true constructor() {} + ngOnInit() { + this.adaptersOriginal = this.adaptersAvailable.filter(x => x.selected).map(x => x.iface) + } + + onAdapterSelectionChange() { + this.isUnchanged = this.adaptersOriginal.length === this.adaptersAvailable.filter(x => x.selected).length + && this.adaptersOriginal.every(original => this.adaptersAvailable.some(x => x.iface === original && x.selected)) + } + submit() { this.$activeModal.close( - this.availableNetworkAdapters.filter((x: any) => x.selected).map((x: any) => x.iface), + this.adaptersAvailable.filter(x => x.selected).map(x => x.iface), ) } } diff --git a/ui/src/app/modules/settings/settings.component.html b/ui/src/app/modules/settings/settings.component.html index b41ef62eb..725f5580b 100644 --- a/ui/src/app/modules/settings/settings.component.html +++ b/ui/src/app/modules/settings/settings.component.html @@ -1,6 +1,6 @@

    {{ 'menu.settings.title' | translate }}

    - +
    {{ 'menu.settings.title' | translate }} class="mt-3 hover-pointer" >
    - + {{ 'settings.general.title_general' | translate }}
    @if (showFields.general) {
    • - Homebridge Name -
      + {{ 'settings.name' | translate }} +
      + @if (hbNameIsSaving) { + + }
    • @@ -62,23 +71,11 @@
    • - @if (hasChangedHbName && !isInvalidHbName) { -
    • - {{ 'settings.changes.saved' | translate }} - -
    • - }
    }
    - +
    class="mt-3 hover-pointer" >
    - + {{ 'settings.general.title_display' | translate }}
    @@ -97,12 +97,8 @@
    • {{ 'settings.display.lang' | translate }} -
      - @@ -133,16 +129,18 @@
      + @if (uiLangIsSaving) { + + }
    • {{ 'settings.display.theme' | translate }} -
      - @@ -157,46 +155,58 @@
      + @if (uiThemeIsSaving) { + + }
    • {{ 'settings.display.lighting_mode' | translate }} -
      - + @if (uiLightIsSaving) { + + }
    • {{ 'settings.display.menu_mode' | translate }} -
      - + @if (uiMenuIsSaving) { + + }
    • {{ 'settings.display.temp_units' | translate }} -
      - + @if (uiTempIsSaving) { + + }
    • @@ -214,260 +224,722 @@
      }
    - + @if ($settings.env.serviceMode || $settings.env.runningInDocker) { -
    -
    -
    - - {{ 'settings.title_startup_options' | translate }} -
    -
    - @if (showFields.startup) { -
      - @if ($settings.env.serviceMode) { -
    • - - {{ 'settings.startup.debug' | translate }} -D
      - - {{ (isHbV2 ? 'settings.startup.debug_desc_v2' : 'settings.startup.debug_desc_v1') | translate }} - -
      - - -
    • - } @if ($settings.env.serviceMode) { -
    • - - {{ 'settings.startup.insecure' | translate }} -I
      - {{ 'settings.startup.insecure_desc' | translate }} -
      - - -
    • - } @if ($settings.env.serviceMode) { -
    • - - {{ 'settings.startup.keep_accessories' | translate }} -K
      - {{ 'settings.startup.keep_accessories_desc' | translate }} -
      - - -
    • - } @if ($settings.env.serviceMode) { -
    • - - DEBUG
      - -
      -
      +
      +
      + + {{ 'settings.title_startup_options' | translate }} +
      +
      +@if (showFields.startup) { +
        + @if ($settings.env.serviceMode) { +
      • + + {{ 'settings.startup.debug' | translate }} -D
        + + {{ (isHbV2 ? 'settings.startup.debug_desc_v2' : 'settings.startup.debug_desc_v1') | translate }} + +
        +
        +
        +
        -
      • - } @if ($settings.env.serviceMode) { -
      • - - NODE_OPTIONS
        - {{ 'settings.service.node_tooltip' | translate }} -
        -
        + @if (hbDebugIsSaving) { + + } +
        +
      • +
      • + + {{ 'settings.startup.insecure' | translate }} -I
        + {{ 'settings.startup.insecure_desc' | translate }} +
        +
        +
        +
        -
      • - } @if ($settings.env.runningInDocker) { -
      • - - {{ 'menu.docker.startup_script' | translate }}
        - {{ 'platform.docker.script_help' | translate }} -
        - - - -
      • - } @if (hasChangedService) { -
      • - {{ 'settings.changes.saved' | translate }} - -
      • - } -
      - } - -} - - -
      -
      -
      - - {{ 'settings.network.title_network' | translate }} -
      -
      - @if (showFields.network) { -
        -
      • - - {{ 'settings.network.title_network_interfaces' | translate }}
        -
        {{ 'settings.network.message_network_interface' | translate }}
        - @for (adapter of bridgeNetworkAdapters; track adapter) { - - @if (adapter.missing) { - - } {{ adapter.iface }}: - {{ adapter.missing ? ('settings.mdns_advertiser_not_connected' | translate) : adapter.ip4 || adapter.ip6 - }} - - } -
        - -
      • -
      • - - {{ 'settings.mdns_advertiser' | translate }}
        - {{ 'settings.mdns_advertiser_help' | translate }} -
        -
        - + @if (hbInsecureIsSaving) { + + } +
        +
      • +
      • + + {{ 'settings.startup.keep_accessories' | translate }} -K
        + {{ 'settings.startup.keep_accessories_desc' | translate }} +
        +
        +
        + +
        -
      • -
      • - - {{ 'settings.network.port_hb' | translate }}
        - {{ 'settings.network.port_hb_desc' | translate }} -
        -
        + @if (hbKeepIsSaving) { + + } +
        +
      • +
      • + + {{ 'settings.startup.metrics' | translate }}
        + {{ 'settings.startup.metrics_desc' | translate }} +
        +
        +
        +
        -
      • -
      • - - {{ 'settings.network.port_ui' | translate }}
        - {{ 'settings.network.port_ui_desc' | translate }} + @if (uiMetricsIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.hb_package' | translate }}
      + {{ 'settings.network.hb_package_desc' | translate }} +
      +
      + + @if (hbPackageIsSaving) { + + } +
      +
    • + @if ($settings.env.platform === 'linux') { +
    • + + {{ 'settings.linux.shutdown' | translate }}
      + {{ 'settings.linux.shutdown_desc' | translate }} +
      +
      + + @if (hbLinuxShutdownIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.linux.restart' | translate }}
      + {{ 'settings.linux.restart_desc' | translate }} +
      +
      + + @if (hbLinuxRestartIsSaving) { + + } +
      +
    • + @if ($settings.env.runningOnRaspberryPi) { +
    • + + {{ 'settings.linux.temp' | translate }}
      + {{ 'settings.linux.temp_desc' | translate }} +
      +
      + + @if (uiTempFileIsSaving) { + + } +
      +
    • + } } +
    • + + DEBUG
      + +
      +
      + + @if (hbEnvDebugIsSaving) { + + } +
      +
    • +
    • + + NODE_OPTIONS
      + {{ 'settings.service.node_tooltip' | translate }} +
      +
      + + @if (hbEnvNodeIsSaving) { + + } +
      +
    • + } @if ($settings.env.runningInDocker) { +
    • + + {{ 'menu.docker.startup_script' | translate }}
      + {{ 'platform.docker.script_help' | translate }} +
      + + + +
    • + } +
    • + + {{ 'settings.startup.log_max' | translate }}
      + {{ 'settings.startup.log_max_desc' | translate }} +
      +
      + + @if (hbLogSizeIsSaving) { + + } +
      +
    • + @if (hbLogSizeFormControl.value > 0) { +
    • + + {{ 'settings.startup.log_truncate' | translate }}
      + {{ 'settings.startup.log_truncate_desc' | translate }} +
      +
      + + @if (hbLogTruncateIsSaving) { + + } +
      +
    • + } +
    +} } + + +
    +
    + + {{ 'settings.network.title_network' | translate }} +
    +
    +@if (showFields.network) { +
      +
    • + + {{ 'settings.network.title_network_interfaces' | translate }}
      +
      {{ 'settings.network.message_network_interface' | translate }}
      + @for (adapter of adaptersSelected; track adapter) { + + @if (adapter.missing) { + + } {{ adapter.iface }}: + {{ adapter.missing ? ('settings.mdns_advertiser_not_connected' | translate) : adapter.ip4 || adapter.ip6 + }} -
      + } + + +
    • +
    • + + {{ 'settings.mdns_advertiser' | translate }}
      + {{ 'settings.mdns_advertiser_help' | translate }} +
      +
      + + @if (hbMDnsIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.port_hb' | translate }}
      + {{ 'settings.network.port_hb_desc' | translate }} +
      +
      + + @if (hbPortIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.port_ui' | translate }}
      + {{ 'settings.network.port_ui_desc' | translate }} +
      +
      + + @if (uiPortIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.port_start' | translate }}
      + {{ 'settings.network.port_start_desc' | translate }} +
      +
      + + @if (hbStartPortIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.port_end' | translate }}
      + {{ 'settings.network.port_end_desc' | translate }} +
      +
      + + @if (hbEndPortIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.host' | translate }}
      + +
      +
      + + @if (uiHostIsSaving) { + + } +
      +
    • +
    • + + {{ 'settings.network.proxy' | translate }}
      + {{ 'settings.network.proxy_desc' | translate }} +
      +
      + + @if (uiProxyHostIsSaving) { + + } +
      +
    • +
    +} + + +
    +
    + + {{ 'settings.network.title_security' | translate }} +
    +
    +@if (showFields.security) { +
      +
    • + + {{ 'settings.security.auth' | translate }}
      + {{ 'settings.security.auth_desc' | translate }} +
      +
      +
      +
      -
    • - @if ((hasChangedHbPort && !isInvalidHbPort) || hasChangedUiSettings || hasChangedMdns || - hasChangedBridgeNetworkAdapters) { -
    • - {{ 'settings.changes.saved' | translate }} -
    + + @if (uiAuthFormControl.value) { +
  • + + {{ 'settings.startup.session' | translate }}
    + {{ 'settings.startup.session_desc' | translate }} +
    +
    + + @if (uiSessionTimeoutIsSaving) { + + } +
    +
  • + } +
  • + + {{ 'settings.security.https' | translate }}
    + {{ 'settings.security.https_desc' | translate }} +
    +
    + +
    +
  • + @if (this.uiSslTypeFormControl.value === 'keycert') { +
  • + {{ 'settings.security.key' | translate }} +
    + + @if (uiSslKeyIsSaving) { + + } +
    +
  • +
  • + {{ 'settings.security.cert' | translate }} +
    + + @if (uiSslCertIsSaving) { + + } +
    +
  • + } @if (this.uiSslTypeFormControl.value === 'pfx') { +
  • + {{ 'settings.security.pfx' | translate }} +
    + + @if (uiSslPfxIsSaving) { + + } +
    +
  • +
  • + {{ 'settings.security.pass' | translate }} +
    + + @if (uiSslPassphraseIsSaving) { + + } +
    +
  • } - +
  • + + {{ 'settings.security.ui_control' | translate }}
    + {{ 'settings.security.ui_control_desc' | translate }} +
    + +
  • + +} - + @if ($settings.env.serviceMode) {
    class="mt-3 hover-pointer" >
    - + {{ 'settings.cache.title' | translate }}
    @@ -487,6 +962,30 @@

    {{ 'settings.cache.desc' | translate }}

    } @if (showFields.cache) {
      +
    • + + {{ 'settings.accessory.debug' | translate }}
      + {{ 'settings.accessory.debug_desc' | translate }} +
      +
      +
      + + +
      + @if (uiAccDebugIsSaving) { + + } +
      +
    • {{ 'reset.accessory_ind.title' | translate }}
      @@ -534,7 +1033,7 @@
    } - +
    class="mt-3 hover-pointer" >
    - + {{ 'reset.bridges.title' | translate }}
    diff --git a/ui/src/app/modules/settings/settings.component.ts b/ui/src/app/modules/settings/settings.component.ts index 784640c31..3004318ee 100644 --- a/ui/src/app/modules/settings/settings.component.ts +++ b/ui/src/app/modules/settings/settings.component.ts @@ -1,7 +1,8 @@ +import { animate, style, transition, trigger } from '@angular/animations' import { NgClass, TitleCasePipe } from '@angular/common' import { Component, inject, OnInit } from '@angular/core' -import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms' -import { RouterLink } from '@angular/router' +import { FormControl, FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms' +import { Router, RouterLink } from '@angular/router' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' @@ -11,6 +12,7 @@ import { debounceTime } from 'rxjs/operators' import { ApiService } from '@/app/core/api.service' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' +import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' import { BackupComponent } from '@/app/modules/settings/backup/backup.component' import { RemoveAllAccessoriesComponent } from '@/app/modules/settings/remove-all-accessories/remove-all-accessories.component' import { RemoveBridgeAccessoriesComponent } from '@/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component' @@ -20,6 +22,39 @@ import { ResetIndividualBridgesComponent } from '@/app/modules/settings/reset-in import { SelectNetworkInterfacesComponent } from '@/app/modules/settings/select-network-interfaces/select-network-interfaces.component' import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.component' +interface NetworkAdapterAvailable { + carrierChanges?: number + default?: boolean + dhcp?: boolean + dnsSuffix?: string + duplex?: string + ieee8021xAuth?: string + ieee8021xState?: string + iface: string + ifaceName: string + internal: boolean + ip4: string + ip4subnet: string + ip6: string + ip6subnet: string + mac: string + mtu: number + missing?: boolean + operstate: string + selected: boolean + speed: number + type: string + virtual?: boolean +} + +interface NetworkAdapterSelected { + iface: string + missing: boolean + selected: true + ip4?: string + ip6?: string +} + @Component({ templateUrl: './settings.component.html', standalone: true, @@ -31,159 +66,1034 @@ import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.c TitleCasePipe, TranslatePipe, ], + animations: [ + trigger('fadeInOut', [ + transition(':enter', [ + style({ opacity: 0 }), + animate('750ms', style({ opacity: 1 })), + ]), + transition(':leave', [ + animate('750ms', style({ opacity: 0 })), + ]), + ]), + ], }) export class SettingsComponent implements OnInit { private $api = inject(ApiService) private $modal = inject(NgbModal) private $plugin = inject(ManagePluginsService) + private $router = inject(Router) $settings = inject(SettingsService) private $toastr = inject(ToastrService) private $translate = inject(TranslateService) - public originalServiceForm = { - HOMEBRIDGE_DEBUG: false, - HOMEBRIDGE_KEEP_ORPHANS: false, - HOMEBRIDGE_INSECURE: true, - ENV_DEBUG: '', - ENV_NODE_OPTIONS: '', - } - - public originalUiSettingsForm = { - port: 0, - } - - public originalMdnsSetting = '' - public originalBridgeNetworkAdapters: string[] = [] - public originalHbPort = 0 - public originalHbName = '' - - public hasChangedService = false - public hasChangedUiSettings = false - public hasChangedMdns = false - public hasChangedBridgeNetworkAdapters = false - public hasChangedHbPort = false - public hasChangedHbName = false - - public isInvalidHbPort = false - public isInvalidHbName = false - public isInvalidHbUiPort = false - - public serviceForm = new FormGroup({ - HOMEBRIDGE_DEBUG: new FormControl(false), - HOMEBRIDGE_KEEP_ORPHANS: new FormControl(false), - HOMEBRIDGE_INSECURE: new FormControl(true), - ENV_DEBUG: new FormControl(''), - ENV_NODE_OPTIONS: new FormControl(''), - }) + private restartToastIsShown = false - public uiSettingsForm = new FormGroup({ - port: new FormControl(0), - }) - - public legacyMdnsFormControl = new UntypedFormControl(false) - public showAvahiMdnsOption = false - public showResolvedMdnsOption = false - public availableNetworkAdapters: any[] = [] - public bridgeNetworkAdapters: string[] = [] - public hbPortFormControl = new FormControl(0) - public hbNameFormControl = new FormControl('') - public isHbV2 = false public showFields = { general: true, display: true, startup: true, network: true, + security: true, reset: true, cache: true, } + public isHbV2 = false + public showAvahiMdnsOption = false + public showResolvedMdnsOption = false + public adaptersAvailable: NetworkAdapterAvailable[] = [] + public adaptersSelected: NetworkAdapterSelected[] = [] + public showPfxPassphrase = false + + public hbNameIsInvalid = false + public hbNameIsSaving = false + public hbNameFormControl = new FormControl('') + + public uiLangIsSaving = false + public uiLangFormControl = new FormControl('') + + public uiThemeIsSaving = false + public uiThemeFormControl = new FormControl('') + + public uiLightIsSaving = false + public uiLightFormControl = new FormControl('') + + public uiMenuIsSaving = false + public uiMenuFormControl = new FormControl('') + + public uiTempIsSaving = false + public uiTempFormControl = new FormControl('') + + public hbDebugIsSaving = false + public hbDebugFormControl = new FormControl(false) + + public hbInsecureIsSaving = false + public hbInsecureFormControl = new FormControl(false) + + public hbKeepIsSaving = false + public hbKeepFormControl = new FormControl(false) + + public hbEnvDebugIsSaving = false + public hbEnvDebugFormControl = new FormControl('') + + public hbEnvNodeIsSaving = false + public hbEnvNodeFormControl = new FormControl('') + + public hbLogSizeIsInvalid = false + public hbLogSizeIsSaving = false + public hbLogSizeFormControl = new FormControl(-1) + + public hbLogTruncateIsInvalid = false + public hbLogTruncateIsSaving = false + public hbLogTruncateFormControl = new FormControl(0) + + public hbMDnsIsSaving = false + public hbMDnsFormControl = new FormControl('') + + public hbPortIsInvalid = false + public hbPortIsSaving = false + public hbPortFormControl = new FormControl(0) + + public hbStartPortIsInvalid = false + public hbStartPortIsSaving = false + public hbStartPortFormControl = new FormControl(0) + + public hbEndPortIsInvalid = false + public hbEndPortIsSaving = false + public hbEndPortFormControl = new FormControl(0) + + public uiPortIsInvalid = false + public uiPortIsSaving = false + public uiPortFormControl = new FormControl(0) + + public uiAuthIsSaving = false + public uiAuthFormControl = new UntypedFormControl(true) + + public uiSessionTimeoutIsInvalid = false + public uiSessionTimeoutIsSaving = false + public uiSessionTimeoutFormControl = new FormControl(0) + + public uiSslTypeFormControl = new FormControl('off') + + public uiSslKeyIsSaving = false + public uiSslKeyFormControl = new FormControl('') + + public uiSslCertIsSaving = false + public uiSslCertFormControl = new FormControl('') + + public uiSslPfxIsSaving = false + public uiSslPfxFormControl = new FormControl('') + + public uiSslPassphraseIsSaving = false + public uiSslPassphraseFormControl = new FormControl('') + + public uiHostIsSaving = false + public uiHostFormControl = new FormControl('') + + public uiProxyHostIsSaving = false + public uiProxyHostFormControl = new FormControl('') + + public hbPackageIsSaving = false + public hbPackageFormControl = new FormControl('') + + public uiMetricsIsSaving = false + public uiMetricsFormControl = new FormControl(true) + + public uiAccDebugIsSaving = false + public uiAccDebugFormControl = new FormControl(false) + + public uiTempFileIsSaving = false + public uiTempFileFormControl = new FormControl('') + + public hbLinuxShutdownIsSaving = false + public hbLinuxShutdownFormControl = new FormControl('') + + public hbLinuxRestartIsSaving = false + public hbLinuxRestartFormControl = new FormControl('') + public readonly linkDebug = '' constructor() {} - ngOnInit() { + async ngOnInit() { this.isHbV2 = this.$settings.env.homebridgeVersion.startsWith('2') - this.hbNameFormControl.patchValue(this.$settings.env.homebridgeInstanceName) - this.hbNameFormControl.valueChanges.subscribe((name: string) => this.setHomebridgeName(name)) - this.originalHbName = this.$settings.env.homebridgeInstanceName - this.initUiSettingsForm() - this.initNetworkingOptions() + await this.initNetworkingOptions() + if (this.$settings.env.serviceMode) { - this.initServiceModeForm() + await this.initServiceModeForm() } + + this.hbNameFormControl.patchValue(this.$settings.env.homebridgeInstanceName) + this.hbNameFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbNameSave(value)) + + this.uiLangFormControl.patchValue(this.$settings.env.lang) + this.uiLangFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiLangSave(value)) + + this.uiThemeFormControl.patchValue(this.$settings.theme) + this.uiThemeFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiThemeSave(value)) + + this.uiLightFormControl.patchValue(this.$settings.lightingMode) + this.uiLightFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: 'auto' | 'light' | 'dark') => this.uiLightSave(value)) + + this.uiMenuFormControl.patchValue(this.$settings.menuMode) + this.uiMenuFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: 'default' | 'freeze') => this.uiMenuSave(value)) + + this.uiTempFormControl.patchValue(this.$settings.env.temperatureUnits) + this.uiTempFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiTempSave(value)) + + this.hbLogSizeFormControl.patchValue(this.$settings.env.log?.maxSize) + this.hbLogSizeFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.hbLogSizeSave(value)) + + this.hbLogTruncateFormControl.patchValue(this.$settings.env.log?.truncateSize) + this.hbLogTruncateFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.hbLogTruncateSave(value)) + + this.uiPortFormControl.patchValue(this.$settings.env.port) + this.uiPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.uiPortSave(value)) + + this.uiAuthFormControl.patchValue(this.$settings.formAuth) + this.uiAuthFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiAuthSave(value)) + + this.uiSessionTimeoutFormControl.patchValue(this.$settings.sessionTimeout) + this.uiSessionTimeoutFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: number) => this.uiSessionTimeoutSave(value)) + + this.uiSslKeyFormControl.patchValue(this.$settings.env.ssl?.key || '') + this.uiSslKeyFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslKeySave(value)) + + this.uiSslCertFormControl.patchValue(this.$settings.env.ssl?.cert || '') + this.uiSslCertFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslCertSave(value)) + + this.uiSslPfxFormControl.patchValue(this.$settings.env.ssl?.pfx || '') + this.uiSslPfxFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslPfxSave(value)) + + this.uiSslPassphraseFormControl.patchValue(this.$settings.env.ssl?.passphrase || '') + this.uiSslPassphraseFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslPassphraseSave(value)) + + this.uiSslTypeFormControl.patchValue(this.uiSslKeyFormControl.value || this.uiSslCertFormControl.value + ? 'keycert' + : (this.uiSslPfxFormControl.value || this.uiSslPassphraseFormControl.value) ? 'pfx' : 'off') + this.uiSslTypeFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiSslTypeSave(value)) + + this.uiHostFormControl.patchValue(this.$settings.env.host || '') + this.uiHostFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiHostSave(value)) + + this.uiProxyHostFormControl.patchValue(this.$settings.env.proxyHost || '') + this.uiProxyHostFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiProxyHostSave(value)) + + this.hbPackageFormControl.patchValue(this.$settings.env.homebridgePackagePath || '') + this.hbPackageFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbPackageSave(value)) + + this.uiMetricsFormControl.patchValue(!this.$settings.env.disableServerMetricsMonitoring) + this.uiMetricsFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiMetricsSave(value)) + + this.uiAccDebugFormControl.patchValue(this.$settings.env.accessoryControl?.debug) + this.uiAccDebugFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiAccDebugSave(value)) + + this.uiTempFileFormControl.patchValue(this.$settings.env.temp) + this.uiTempFileFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiTempFileSave(value)) + + this.hbLinuxShutdownFormControl.patchValue(this.$settings.env.linux?.shutdown) + this.hbLinuxShutdownFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbLinuxShutdownSave(value)) + + this.hbLinuxRestartFormControl.patchValue(this.$settings.env.linux?.restart) + this.hbLinuxRestartFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbLinuxRestartSave(value)) } - initUiSettingsForm() { - this.originalUiSettingsForm = { - port: this.$settings.env.port, + async initServiceModeForm() { + try { + const serviceModeData = await firstValueFrom(this.$api.get('/platform-tools/hb-service/homebridge-startup-settings')) + + this.hbDebugFormControl.patchValue(serviceModeData.HOMEBRIDGE_DEBUG) + this.hbDebugFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbDebugSave(value)) + + this.hbInsecureFormControl.patchValue(serviceModeData.HOMEBRIDGE_INSECURE) + this.hbInsecureFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbInsecureSave(value)) + + this.hbKeepFormControl.patchValue(serviceModeData.HOMEBRIDGE_KEEP_ORPHANS) + this.hbKeepFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbKeepSave(value)) + + this.hbEnvDebugFormControl.patchValue(serviceModeData.ENV_DEBUG) + this.hbEnvDebugFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbEnvDebugSave(value)) + + this.hbEnvNodeFormControl.patchValue(serviceModeData.ENV_NODE_OPTIONS) + this.hbEnvNodeFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbEnvNodeSave(value)) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) } - this.uiSettingsForm.patchValue({ - port: this.$settings.env.port, - }) - this.uiSettingsForm.valueChanges.pipe(debounceTime(500)).subscribe((data) => { - let hasChangedUiSettings = false - Object.keys(data).forEach((key) => { - if (this.originalUiSettingsForm[key] !== data[key]) { - this.saveUiSettingChange(key, data[key]) - hasChangedUiSettings = true - } - }) - this.hasChangedUiSettings = hasChangedUiSettings + } + + async initNetworkingOptions() { + try { + await this.getNetworkSettings() + const onLinux = ( + this.$settings.env.runningInLinux + || this.$settings.env.runningInDocker + || this.$settings.env.runningInSynologyPackage + || this.$settings.env.runningInPackageMode + ) + if (onLinux) { + this.showAvahiMdnsOption = true + this.showResolvedMdnsOption = true + } + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + + async getNetworkSettings() { + return Promise.all([ + firstValueFrom(this.$api.get('/server/network-interfaces/system')), + firstValueFrom(this.$api.get('/server/network-interfaces/bridge')), + firstValueFrom(this.$api.get('/server/mdns-advertiser')), + firstValueFrom(this.$api.get('/server/port')), + firstValueFrom(this.$api.get('/server/ports')), + ]).then(([system, adapters, mdnsAdvertiser, port, ports]: [NetworkAdapterAvailable[], string[], { advertiser: string }, { port: number }, { start?: number, end?: number }]) => { + this.adaptersAvailable = system + this.buildBridgeNetworkAdapterList(adapters) + + this.hbMDnsFormControl.patchValue(mdnsAdvertiser.advertiser) + this.hbMDnsFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.hbMDnsSave(value)) + + this.hbPortFormControl.patchValue(port.port) + this.hbPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbPortSave(port)) + + this.hbStartPortFormControl.patchValue(ports.start) + this.hbStartPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbStartPortSave(port)) + + this.hbEndPortFormControl.patchValue(ports.end) + this.hbEndPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbEndPortSave(port)) }) } - initServiceModeForm() { - this.$api.get('/platform-tools/hb-service/homebridge-startup-settings').subscribe({ - next: (data) => { - Object.keys(data).forEach((key) => { - this.originalServiceForm[key] = data[key] + async saveUiSettingChange(key: string, value: any) { + // Save the new property to the config file + try { + await firstValueFrom(this.$api.put('/config-editor/ui', { key, value })) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + + async hbNameSave(value: string) { + // https://github.com/homebridge/HAP-NodeJS/blob/ee41309fd9eac383cdcace39f4f6f6a3d54396f3/src/lib/util/checkName.ts#L12 + if (!value || !(/^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u).test(value)) { + this.hbNameIsInvalid = true + return + } + + try { + this.hbNameIsSaving = true + await firstValueFrom(this.$api.put('/server/name', { name: value })) + this.$settings.setEnvItem('homebridgeInstanceName', value) + this.hbNameIsInvalid = false + setTimeout(() => { + this.hbNameIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbNameIsSaving = false + } + } + + async uiLangSave(value: string) { + try { + this.uiLangIsSaving = true + this.$settings.setLang(value) + await this.saveUiSettingChange('lang', value) + setTimeout(() => { + this.uiLangIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiLangIsSaving = false + } + } + + async uiThemeSave(value: string) { + try { + this.uiThemeIsSaving = true + this.$settings.setTheme(value) + await this.saveUiSettingChange('theme', value) + setTimeout(() => { + this.uiThemeIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiThemeIsSaving = false + } + } + + async uiLightSave(value: 'auto' | 'light' | 'dark') { + try { + this.uiLightIsSaving = true + this.$settings.setLightingMode(value, 'user') + await this.saveUiSettingChange('lightingMode', value) + setTimeout(() => { + this.uiLightIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiLightIsSaving = false + } + } + + async uiMenuSave(value: 'default' | 'freeze') { + try { + this.uiMenuIsSaving = true + this.$settings.setMenuMode(value) + await this.saveUiSettingChange('menuMode', value) + window.location.reload() + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiMenuIsSaving = false + } + } + + async uiTempSave(value: string) { + try { + this.uiTempIsSaving = true + this.$settings.setEnvItem('temperatureUnits', value) + await this.saveUiSettingChange('tempUnits', value) + setTimeout(() => { + this.uiTempIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiTempIsSaving = false + } + } + + async hbDebugSave(value: boolean) { + try { + this.hbDebugIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbDebugIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, }) - this.serviceForm.patchValue(data) - this.serviceForm.valueChanges.pipe(debounceTime(500)).subscribe(this.saveServiceModeSettings.bind(this)) - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbDebugIsSaving = false + } } - saveUiSettingChange(key: string, value: any) { - // Extra things to do per key - switch (key) { - case 'lang': - this.$settings.setLang(value) - break - case 'lightingMode': - this.$settings.setLightingMode(value, 'user') - break - case 'menuMode': - this.$settings.setMenuMode(value) - window.location.reload() - break - case 'theme': - this.$settings.setTheme(value) - break - case 'tempUnits': - this.$settings.setEnvItem('temperatureUnits', value) + async hbInsecureSave(value: boolean) { + try { + this.hbInsecureIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbInsecureIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbInsecureIsSaving = false + } + } + + async hbKeepSave(value: boolean) { + try { + this.hbKeepIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbKeepIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbKeepIsSaving = false + } + } + + async hbEnvDebugSave(value: string) { + try { + this.hbEnvDebugIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbEnvDebugIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEnvDebugIsSaving = false + } + } + + async hbEnvNodeSave(value: string) { + try { + this.hbEnvNodeIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: value, + })) + setTimeout(() => { + this.hbEnvNodeIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEnvNodeIsSaving = false + } + } + + async hbLogSizeSave(value: number) { + if (value && (typeof value !== 'number' || value < -1 || Number.isInteger(value) === false)) { + this.hbLogSizeIsInvalid = true + return + } + + try { + this.hbLogSizeIsSaving = true + this.$settings.setEnvItem('log.maxSize', value) + if (!value || value === -1) { + // If the value is -1, we set the log.maxSize to undefined + // This will remove the setting from the config file + await this.saveUiSettingChange('log.truncateSize', null) + this.hbLogTruncateIsInvalid = false + } + await this.saveUiSettingChange('log.maxSize', value) + this.hbLogSizeIsInvalid = false + setTimeout(() => { + this.hbLogSizeIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLogSizeIsSaving = false + } + } + + async hbLogTruncateSave(value: number) { + if (value && (typeof value !== 'number' || value < 0 || Number.isInteger(value) === false)) { + this.hbLogTruncateIsInvalid = true + return + } + + try { + this.hbLogTruncateIsSaving = true + this.$settings.setEnvItem('log.truncateSize', value) + await this.saveUiSettingChange('log.truncateSize', value) + this.hbLogTruncateIsInvalid = false + setTimeout(() => { + this.hbLogTruncateIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLogTruncateIsSaving = false + } + } + + async hbMDnsSave(value: string) { + try { + this.hbMDnsIsSaving = true + await firstValueFrom(this.$api.put('/server/mdns-advertiser', { advertiser: value })) + setTimeout(() => { + this.hbMDnsIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbMDnsIsSaving = false + } + } + + async hbPortSave(value: number) { + if (value === this.uiPortFormControl.value) { + this.hbPortIsInvalid = true + return + } + + try { + this.hbPortIsSaving = true + await firstValueFrom(this.$api.put('/server/port', { port: value })) + this.hbPortIsInvalid = false + setTimeout(() => { + this.hbPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbPortIsSaving = false + } + } + + async hbStartPortSave(value: number) { + try { + this.hbStartPortIsSaving = true + await firstValueFrom(this.$api.put('/server/ports', { start: value, end: this.hbEndPortFormControl.value })) + this.hbStartPortIsInvalid = false + setTimeout(() => { + this.hbStartPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbStartPortIsSaving = false + } + } + + async hbEndPortSave(value: number) { + try { + this.hbEndPortIsSaving = true + await firstValueFrom(this.$api.put('/server/ports', { start: this.hbStartPortFormControl.value, end: value })) + this.hbEndPortIsInvalid = false + setTimeout(() => { + this.hbEndPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEndPortIsSaving = false + } + } + + async uiPortSave(value: number) { + if (!value || typeof value !== 'number' || value < 1025 || value > 65533 || Number.isInteger(value) === false || value === this.hbPortFormControl.value) { + this.uiPortIsInvalid = true + return + } + + try { + this.uiPortIsSaving = true + this.$settings.setEnvItem('port', value) + await this.saveUiSettingChange('port', value) + this.uiPortIsInvalid = false + setTimeout(() => { + this.uiPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiPortIsSaving = false + } + } + + async uiAuthSave(value: boolean) { + try { + this.uiAuthIsSaving = true + this.$settings.setItem('formAuth', value) + await this.saveUiSettingChange('auth', value ? 'form' : 'none') + setTimeout(() => { + this.uiAuthIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiAuthIsSaving = false + } + } + + async uiSessionTimeoutSave(value: number) { + if (value && (typeof value !== 'number' || value < 600 || value > 86400000 || Number.isInteger(value) === false)) { + this.uiSessionTimeoutIsInvalid = true + return + } + + try { + this.uiSessionTimeoutIsSaving = true + this.$settings.setItem('sessionTimeout', value) + await this.saveUiSettingChange('sessionTimeout', value) + this.uiSessionTimeoutIsInvalid = false + setTimeout(() => { + this.uiSessionTimeoutIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSessionTimeoutIsSaving = false + } + } + + async uiSslKeySave(value: string) { + try { + this.uiSslKeyIsSaving = true + this.$settings.setEnvItem('ssl.key', value) + await this.saveUiSettingChange('ssl.key', value) + setTimeout(() => { + this.uiSslKeyIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslKeyIsSaving = false + } + } + + async uiSslCertSave(value: string) { + try { + this.uiSslCertIsSaving = true + this.$settings.setEnvItem('ssl.cert', value) + await this.saveUiSettingChange('ssl.cert', value) + setTimeout(() => { + this.uiSslCertIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslCertIsSaving = false + } + } + + async uiSslPfxSave(value: string) { + try { + this.uiSslPfxIsSaving = true + this.$settings.setEnvItem('ssl.pfx', value) + await this.saveUiSettingChange('ssl.pfx', value) + setTimeout(() => { + this.uiSslPfxIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslPfxIsSaving = false + } + } + + async uiSslPassphraseSave(value: string) { + try { + this.uiSslPassphraseIsSaving = true + this.$settings.setEnvItem('ssl.passphrase', value) + await this.saveUiSettingChange('ssl.passphrase', value) + setTimeout(() => { + this.uiSslPassphraseIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslPassphraseIsSaving = false + } + } + + async uiSslTypeSave(value: string) { + switch (value) { + case 'keycert': + this.uiSslPfxFormControl.patchValue('', { emitEvent: false }) + this.uiSslPassphraseFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.pfx', '') + this.$settings.setEnvItem('ssl.passphrase', '') break - case 'port': - if (!value || typeof value !== 'number' || value < 1025 || value > 65533 || Number.isInteger(value) === false || value === this.hbPortFormControl.value) { - this.isInvalidHbUiPort = true - return - } - this.$settings.setEnvItem('port', value) - this.isInvalidHbUiPort = false + case 'pfx': + this.uiSslKeyFormControl.patchValue('', { emitEvent: false }) + this.uiSslCertFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.key', '') + this.$settings.setEnvItem('ssl.cert', '') break + default: + this.uiSslKeyFormControl.patchValue('', { emitEvent: false }) + this.uiSslCertFormControl.patchValue('', { emitEvent: false }) + this.uiSslPfxFormControl.patchValue('', { emitEvent: false }) + this.uiSslPassphraseFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.key', '') + this.$settings.setEnvItem('ssl.cert', '') + this.$settings.setEnvItem('ssl.pfx', '') + this.$settings.setEnvItem('ssl.passphrase', '') + await this.saveUiSettingChange('ssl', '') + this.showRestartToast() } + } - // Save the new property to the config file - firstValueFrom(this.$api.put('/config-editor/ui', { key, value })) - .catch((error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }) + async uiHostSave(value: string) { + try { + this.uiHostIsSaving = true + this.$settings.setEnvItem('host', value) + await this.saveUiSettingChange('host', value) + setTimeout(() => { + this.uiHostIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiHostIsSaving = false + } + } + + async uiProxyHostSave(value: string) { + try { + this.uiProxyHostIsSaving = true + this.$settings.setEnvItem('proxyHost', value) + await this.saveUiSettingChange('proxyHost', value) + setTimeout(() => { + this.uiProxyHostIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiProxyHostIsSaving = false + } + } + + async hbPackageSave(value: string) { + try { + this.hbPackageIsSaving = true + this.$settings.setEnvItem('homebridgePackagePath', value) + await this.saveUiSettingChange('homebridgePackagePath', value) + setTimeout(() => { + this.hbPackageIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbPackageIsSaving = false + } + } + + async uiMetricsSave(value: boolean) { + try { + this.uiMetricsIsSaving = true + this.$settings.setEnvItem('disableServerMetricsMonitoring', !value) + await this.saveUiSettingChange('disableServerMetricsMonitoring', !value) + setTimeout(() => { + this.uiMetricsIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiMetricsIsSaving = false + } + } + + async uiAccDebugSave(value: boolean) { + try { + this.uiAccDebugIsSaving = true + this.$settings.setEnvItem('accessoryControl.debug', value) + await this.saveUiSettingChange('accessoryControl.debug', value) + setTimeout(() => { + this.uiAccDebugIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiAccDebugIsSaving = false + } + } + + async uiTempFileSave(value: string) { + try { + this.uiTempFileIsSaving = true + this.$settings.setEnvItem('temp', value) + await this.saveUiSettingChange('temp', value) + setTimeout(() => { + this.uiTempFileIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiTempFileIsSaving = false + } + } + + async hbLinuxShutdownSave(value: string) { + try { + this.hbLinuxShutdownIsSaving = true + this.$settings.setEnvItem('linux.shutdown', value) + await this.saveUiSettingChange('linux.shutdown', value) + setTimeout(() => { + this.hbLinuxShutdownIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLinuxShutdownIsSaving = false + } + } + + async hbLinuxRestartSave(value: string) { + try { + this.hbLinuxRestartIsSaving = true + this.$settings.setEnvItem('linux.restart', value) + await this.saveUiSettingChange('linux.restart', value) + setTimeout(() => { + this.hbLinuxRestartIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLinuxRestartIsSaving = false + } } openUiSettings() { @@ -209,18 +1119,6 @@ export class SettingsComponent implements OnInit { }) } - saveServiceModeSettings(data = this.serviceForm.value) { - this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', data).subscribe({ - next: () => { - this.hasChangedService = JSON.stringify(data) !== JSON.stringify(this.originalServiceForm) - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } - resetHomebridgeState() { this.$modal.open(ResetAllBridgesComponent, { size: 'lg', @@ -242,6 +1140,25 @@ export class SettingsComponent implements OnInit { }) } + async accessoryUiControl() { + try { + const ref = this.$modal.open(AccessoryControlListsComponent, { + size: 'lg', + backdrop: 'static', + }) + + ref.componentInstance.existingBlacklist = this.$settings.env.accessoryControl?.instanceBlacklist || [] + + await ref.result + this.showRestartToast() + } catch (error) { + if (error !== 'Dismiss') { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + } + removeSingleCachedAccessories() { this.$modal.open(RemoveIndividualAccessoriesComponent, { size: 'lg', @@ -256,142 +1173,77 @@ export class SettingsComponent implements OnInit { }) } - async initNetworkingOptions() { - try { - this.getNetworkSettings() - const onLinux = ( - this.$settings.env.runningInLinux - || this.$settings.env.runningInDocker - || this.$settings.env.runningInSynologyPackage - || this.$settings.env.runningInPackageMode - ) - if (onLinux) { - this.showAvahiMdnsOption = true - this.showResolvedMdnsOption = true - } - } catch (e) {} - } - - async getNetworkSettings() { - return Promise.all([ - firstValueFrom(this.$api.get('/server/network-interfaces/system')), - firstValueFrom(this.$api.get('/server/network-interfaces/bridge')), - firstValueFrom(this.$api.get('/server/mdns-advertiser')), - firstValueFrom(this.$api.get('/server/port')), - ]).then(([system, adapters, mdnsAdvertiser, port]) => { - this.availableNetworkAdapters = system - this.buildBridgeNetworkAdapterList(adapters) - this.legacyMdnsFormControl.patchValue(mdnsAdvertiser.advertiser) - this.originalMdnsSetting = mdnsAdvertiser.advertiser - this.originalBridgeNetworkAdapters = this.bridgeNetworkAdapters.map((x: any) => x.iface) - this.legacyMdnsFormControl.valueChanges.subscribe((advertiser: string) => { - this.setHomebridgeMdnsSetting(advertiser) - }) - this.hbPortFormControl.patchValue(port.port) - this.hbPortFormControl.valueChanges.subscribe((port: number) => this.setHomebridgePort(port)) - this.originalHbPort = port.port + async selectNetworkInterfaces() { + const ref = this.$modal.open(SelectNetworkInterfacesComponent, { + size: 'lg', + backdrop: 'static', }) - } - async setHomebridgeMdnsSetting(advertiser: string) { - this.$api.put('/server/mdns-advertiser', { advertiser }).subscribe({ - next: () => { - this.hasChangedMdns = advertiser !== this.originalMdnsSetting - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } + ref.componentInstance.adaptersAvailable = this.adaptersAvailable - async setNetworkInterfaces(adapters: string[]) { - this.$api.put('/server/network-interfaces/bridge', { adapters }).subscribe({ - next: () => { - this.hasChangedBridgeNetworkAdapters = this.originalBridgeNetworkAdapters.join(',') !== adapters.join(',') - }, - error: (error) => { + try { + const adapters: string[] = await ref.result + this.buildBridgeNetworkAdapterList(adapters) + await firstValueFrom(this.$api.put('/server/network-interfaces/bridge', { adapters })) + this.showRestartToast() + } catch (error) { + if (error !== 'Dismiss') { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } - - async setHomebridgeName(name: string) { - // https://github.com/homebridge/HAP-NodeJS/blob/ee41309fd9eac383cdcace39f4f6f6a3d54396f3/src/lib/util/checkName.ts#L12 - if (!name || !(/^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u).test(name)) { - this.isInvalidHbName = true - return - } - - this.$api.put('/server/name', { name }).subscribe({ - next: () => { - this.hasChangedHbName = this.originalHbName !== name - this.$settings.setEnvItem('homebridgeInstanceName', name) - this.isInvalidHbName = false - }, - error: () => { - this.isInvalidHbName = true - }, - }) - } - - async setHomebridgePort(port: number) { - if (port === this.uiSettingsForm.get('port').value) { - this.isInvalidHbPort = true - return + } } - - this.$api.put('/server/port', { port }).subscribe({ - next: () => { - this.hasChangedHbPort = this.originalHbPort !== port - this.isInvalidHbPort = false - }, - error: () => { - this.isInvalidHbPort = true - }, - }) } buildBridgeNetworkAdapterList(adapters: string[]) { if (!adapters.length) { - this.bridgeNetworkAdapters = [] + this.adaptersSelected = [] return } - this.bridgeNetworkAdapters = adapters.map((interfaceName) => { - const i = this.availableNetworkAdapters.find((x: any) => x.iface === interfaceName) + this.adaptersSelected = adapters.map((interfaceName) => { + const i = this.adaptersAvailable.find(x => x.iface === interfaceName) if (i) { - i.selected = true - i.missing = false - return i + return { + iface: i.iface, + selected: true, + missing: false, + ip4: i.ip4, + ip6: i.ip6, + } } else { return { iface: interfaceName, + selected: true, missing: true, } } }) } - selectNetworkInterfaces() { - const ref = this.$modal.open(SelectNetworkInterfacesComponent, { - size: 'lg', - backdrop: 'static', - }) - - ref.componentInstance.availableNetworkAdapters = this.availableNetworkAdapters - ref.componentInstance.bridgeNetworkAdapters = this.bridgeNetworkAdapters - - ref.result - .then((adapters: string[]) => { - this.buildBridgeNetworkAdapterList(adapters) - this.setNetworkInterfaces(adapters) - }) - .catch(() => { /* do nothing */ }) - } - toggleSection(section: string) { this.showFields[section] = !this.showFields[section] } + + showRestartToast() { + if (!this.restartToastIsShown) { + this.restartToastIsShown = true + const ref = this.$toastr.info( + this.$translate.instant('settings.changes.saved'), + this.$translate.instant('menu.hbrestart.title'), + { + timeOut: 0, + tapToDismiss: true, + disableTimeOut: true, + positionClass: 'toast-bottom-right', + enableHtml: true, + }, + ) + + if (ref && ref.onTap) { + ref.onTap.subscribe(() => { + this.$router.navigate(['/restart']) + }) + } + } + } } diff --git a/ui/src/app/modules/settings/settings.module.ts b/ui/src/app/modules/settings/settings.module.ts index c2be4fdf4..5f613d788 100644 --- a/ui/src/app/modules/settings/settings.module.ts +++ b/ui/src/app/modules/settings/settings.module.ts @@ -4,6 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { TranslateModule } from '@ngx-translate/core' +import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' import { BackupComponent } from '@/app/modules/settings/backup/backup.component' import { RestoreComponent } from '@/app/modules/settings/backup/restore/restore.component' import { RemoveAllAccessoriesComponent } from '@/app/modules/settings/remove-all-accessories/remove-all-accessories.component' @@ -25,6 +26,7 @@ import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.c NgbModule, SettingsRoutingModule, SettingsComponent, + AccessoryControlListsComponent, ResetAllBridgesComponent, ResetIndividualBridgesComponent, RemoveAllAccessoriesComponent, diff --git a/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts b/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts index 62c567177..258b97076 100644 --- a/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts +++ b/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts @@ -60,6 +60,7 @@ export class WallpaperComponent { formData.append('wallpaper', this.selectedFile, this.selectedFile.name) this.$api.post('/server/wallpaper', formData).subscribe({ next: () => { + this.$settings.setItem('wallpaper', `ui-wallpaper.${this.selectedFile.name.split('.').pop()}`) this.$activeModal.close() this.$toastr.success(this.$translate.instant('settings.display.wallpaper_success'), this.$translate.instant('toast.title_success')) }, diff --git a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html index 4d7206258..316323643 100644 --- a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html +++ b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html @@ -15,24 +15,17 @@ @for (widget of availableWidgets; track widget) {
  • {{ widget.name }} -
    - - -
    + /> + +
  • } diff --git a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts index 2799e32d9..a6313d4ba 100644 --- a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts +++ b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts @@ -1,4 +1,5 @@ import { Component, inject, Input, OnInit } from '@angular/core' +import { FormsModule } from '@angular/forms' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' @@ -9,6 +10,7 @@ import { SettingsService } from '@/app/core/settings.service' standalone: true, imports: [ TranslatePipe, + FormsModule, ], }) export class WidgetVisibilityComponent implements OnInit { @@ -141,7 +143,7 @@ export class WidgetVisibilityComponent implements OnInit { .sort((a, b) => a.name.localeCompare(b.name)) .map(x => ({ ...x, - shown: !this.dashboard.some((i: any) => i.component === x.component), + shown: this.dashboard.some((i: any) => i.component === x.component), })) } diff --git a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts index e3714f86d..17063bd86 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts @@ -76,6 +76,7 @@ export class HbV2ModalComponent implements OnInit { hb2Ready, } }) + .sort((a, b) => a.name.localeCompare(b.name)) // Skip if there are no plugins installed if (this.installedPlugins.length === 0) { diff --git a/ui/src/app/modules/support/support.component.html b/ui/src/app/modules/support/support.component.html index 1935acd38..e4dc9df01 100644 --- a/ui/src/app/modules/support/support.component.html +++ b/ui/src/app/modules/support/support.component.html @@ -12,7 +12,10 @@

    {{ 'support.title' | translate }}

    class="mt-3 hover-pointer" >
    - + {{ 'support.links.title' | translate }}
    @@ -95,7 +98,7 @@
    class="mt-3 hover-pointer" >
    - + {{ 'support.dev.title' | translate }}
    diff --git a/ui/src/app/shared/layout/sidebar/sidebar.component.ts b/ui/src/app/shared/layout/sidebar/sidebar.component.ts index 998abf931..edf874eaf 100644 --- a/ui/src/app/shared/layout/sidebar/sidebar.component.ts +++ b/ui/src/app/shared/layout/sidebar/sidebar.component.ts @@ -43,7 +43,6 @@ export class SidebarComponent implements OnInit, OnDestroy { constructor() { const router = this.router - this.isMobile = window.innerWidth < 768 let resizeTimeout: any window.addEventListener('resize', () => { diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 81ea6e04e..bf3106017 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Всички резервни копия са изтрити", "config.title_backup_loaded": "Резервното копие е заредено", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Отказ", "form.button_close": "Затвори", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Промени", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 8f234e503..f97086ebc 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Totes les còpies de seguretat eliminades", "config.title_backup_loaded": "Còpia de seguretat carregada", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancel·lar", "form.button_close": "Tancar", @@ -159,7 +160,6 @@ "form.button_download": "Descarregar", "form.button_edit": "Editar", "form.button_enable": "Activar", - "form.button_hide": "Amagar", "form.button_lock": "Bloquejar", "form.button_more_info": "Més Informació", "form.button_remove": "Eliminar", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Aquesta Raspberry Pi informa que actualment està sota tensió; comproveu que estigui connectat a una font d'alimentació adequada. La baixa tensió pot provocar inestabilitat del sistema i corrupció de la targeta SD.", "rpi.throttled.previously_message": "Aquest Raspberry Pi ha informat d'un esdeveniment de baixa tensió des que es va reiniciar per última vegada; comproveu que estigui connectat a una font d'alimentació adequada.", "rpi.throttled.undervoltage_title": "Baixa de Tensió", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Mètode de difusió mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si tens problemes per connectar a Homebridge, prova d’utilitzar un mètode de difusió mDNS alternatiu.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nom de la interfície", - "settings.network.label_ip_address": "Adreça IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si no es selecciona cap interfície de xarxa, Homebridge intentarà determinar automàticament quines interfícies difondre.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Xarxa", "settings.network.title_network_interfaces": "Interfícies de xarxa", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opcions d'arrencada", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Començar", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index e17ddcfe6..fca7ceeb7 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Všechny zálohy byly smazány", "config.title_backup_loaded": "Záloha byla načtena", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Zpět", "form.button_cancel": "Zrušit", "form.button_close": "Zavřít", @@ -159,7 +160,6 @@ "form.button_download": "Stáhnout", "form.button_edit": "Editovat", "form.button_enable": "Povolit", - "form.button_hide": "Skrýt", "form.button_lock": "Zamknout", "form.button_more_info": "Více informací", "form.button_remove": "Odstranit", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Toto Raspberry Pi hlásí podpětí; zkontrolujte, zda je připojen ke vhodnému zdroji napájení. Podpětí může způsobit nestabilitu systému a poškození SD karty.", "rpi.throttled.previously_message": "Toto Raspberry Pi hlásilo podpětí od posledního restartu; zkontrolujte, zda je připojen ke vhodnému zdroji napájení.", "rpi.throttled.undervoltage_title": "Podpětí", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge uchovává příslušenství v mezipaměti, aby nebylo odstraněno a znovu přidáváno do HomeKitu při každém restartu Homebridge. Někdy může být tato mezipaměť neaktuální ve vztahu k aktuálnímu stavu příslušenství v Homebridge.", "settings.cache.title": "Příslušenství", "settings.changes.saved": "Vaše změny byly uloženy a k jejich použití je třeba restartovat.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Displej", "settings.general.title_general": "Obecné", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Inzerent", "settings.mdns_advertiser_exp": "experimentální", "settings.mdns_advertiser_help": "Pokud máte potíže s připojením k Homebridge, zkuste použít některého z alternativních inzerentů mDNS.", "settings.mdns_advertiser_not_connected": "Není připojeno", "settings.mdns_advertiser_rec": "doporučeno", - "settings.network.label_interface_name": "Jméno rozhraní", - "settings.network.label_ip_address": "IP Adresa", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Pokud nejsou vybrána žádná síťová rozhraní, Homebridge se pokusí automaticky určit, na kterých rozhraních má inzerovat.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Portové číslo, na kterém běží Homebridge most. Toto číslo musí být mezi 1025 a 65533 a nemělo by být stejné jako port pro rozhraní Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Port UI", "settings.network.port_ui_desc": "Portové číslo, na kterém běží Homebridge UI.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Síť", "settings.network.title_network_interfaces": "Síťové Rozhraní", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Nepodařilo se resetovat most.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Některé pluginy vyžadují nastavení proměnné prostředí DEBUG pro povolení podrobného protokolování chybové úrovně.", "settings.service.node_tooltip": "Možnosti běhu Node.js pro tento proces. Toto by mělo zůstat prázdné, pokud nevíte, co děláte.", "settings.startup.debug": "Homebridge Režim ladění", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Pro ovládání příslušenství prostřednictvím rozhraní Homebridge UI musíte běžet Homebridge v nezabezpečeném režimu.", "settings.startup.keep_accessories": "Zachovat příslušenství od odinstalovaných pluginů", "settings.startup.keep_accessories_desc": "Pokud je povoleno, příslušenství platformových pluginů zůstane v cache i po odinstalaci pluginu. To může být užitečné, pokud plánujete plugin později znovu nainstalovat.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Možnosti spuštění", "settings.unpair_bridge.load_error": "Spárované mosty nelze načíst.", "setup.button_get_started": "Začněme", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index 079698c3d..a69b125b7 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle Backups gelöscht", "config.title_backup_loaded": "Backup geladen", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Zurück", "form.button_cancel": "Abbrechen", "form.button_close": "Schließen", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Bearbeiten", "form.button_enable": "Aktivieren", - "form.button_hide": "Verstecken", "form.button_lock": "Sperren", "form.button_more_info": "Mehr Informationen", "form.button_remove": "Entfernen", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Dieser Raspberry Pi meldet, dass er derzeit unter zu niedriger Spannung steht; bitte überprüfen Sie, ob er an eine geeignete Stromversorgung angeschlossen ist. Eine Unterspannung kann zur Instabilität des Systems und zur Beschädigung der SD-Karte führen.", "rpi.throttled.previously_message": "Dieser Raspberry Pi hat seit dem letzten Neustart ein Unterspannungsereignis gemeldet; bitte überprüfen Sie, ob er an eine geeignete Stromversorgung angeschlossen ist.", "rpi.throttled.undervoltage_title": "Unterspannung", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge verwaltet Zubehöre im Cache, damit es nicht bei jedem Neustart von Homebridge entfernt und neu zu HomeKit hinzugefügt wird. Manchmal kann dieser Cache nicht mehr mit den tatsächlichen Zubehör in Homebridge synchronisiert werden.", "settings.cache.title": "Zubehör", "settings.changes.saved": "Ihre Änderungen wurden gespeichert und erfordern einen Neustart, um wirksam zu werden..", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Anzeige", "settings.general.title_general": "Allgemein", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimentell", "settings.mdns_advertiser_help": "Wenn du Probleme hast, dich mit Homebridge zu verbinden, versuche einen der alternativen mDNS Advertiser zu verwenden.", "settings.mdns_advertiser_not_connected": "Nicht verbunden", "settings.mdns_advertiser_rec": "empfohlen", - "settings.network.label_interface_name": "Schnittstellen-Name", - "settings.network.label_ip_address": "IP-Adresse", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Wenn keine Netzwerkschnittstellen ausgewählt sind, versucht Homebridge automatisch zu bestimmen, welche Schnittstellen angezeigt werden sollen.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Die Portnummer, unter der die Homebridge-Bridge ausgeführt werden soll. Diese muss zwischen 1025 und 65533 liegen und sollte nicht mit dem Port der Homebridge-Benutzeroberfläche übereinstimmen.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Die Portnummer, über die die Homebridge UI ausgeführt werden soll.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Netzwerk", "settings.network.title_network_interfaces": "Netzwerkschnittstellen", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Zurücksetzen der Bridge fehlgeschlagen.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Bei einigen Plugins müssen Sie die Umgebungsvariable DEBUG setzen {{ link }}, um die Protokollierung auf Debug-Ebene zu aktivieren.", "settings.service.node_tooltip": "Node.js-Laufzeitoptionen für den Homebridge-Prozess. Dies sollte leer bleiben, wenn Sie nicht wissen, was Sie tun.", "settings.startup.debug": "Homebridge 'Debug' Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Um Ihre Zubehör über die Homebridge-Benutzeroberfläche zu steuern, müssen Sie Homebridge im 'Insecure' Mode ausführen.", "settings.startup.keep_accessories": "Behalte Zubehöre von nicht installierten Plugins", "settings.startup.keep_accessories_desc": "Wenn diese Option aktiviert ist, verbleiben Zubehöre von Plattform-Plugins im Cache, auch wenn das Plugin deinstalliert wird. Dies kann nützlich sein, wenn Sie planen, das Plugin später erneut zu installieren.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startoptionen", "settings.unpair_bridge.load_error": "Gepairte Bridge konnten nicht geladen werden.", "setup.button_get_started": "Los geht's", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index ce56d1811..014fb2e92 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "All Backups Deleted", "config.title_backup_loaded": "Backup Loaded", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancel", "form.button_close": "Close", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Edit", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine on which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Homebridge UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on. This must be between 1025 and 65533, and should not be the same as the Homebridge port.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index e4ec03fa9..6d0d07281 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Todas las copias de seguridad eliminadas", "config.title_backup_loaded": "Copia de seguridad cargada", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Atrás", "form.button_cancel": "Cancelar", "form.button_close": "Cerrar", @@ -159,7 +160,6 @@ "form.button_download": "Descargar", "form.button_edit": "Editar", "form.button_enable": "Activar", - "form.button_hide": "Ocultar", "form.button_lock": "Bloquear", "form.button_more_info": "Más Información", "form.button_remove": "Eliminar", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Esta Raspberry Pi está reportando una baja de voltaje; por favor, compruebe que está conectada a una fuente de alimentación adecuada. El bajo voltaje puede provocar la inestabilidad del sistema y daños en la tarjeta SD.", "rpi.throttled.previously_message": "Esta Raspberry Pi ha reportado una baja en el voltaje desde que se reinició por última vez; por favor, compruebe que está conectada a una fuente de alimentación adecuada.", "rpi.throttled.undervoltage_title": "Baja de Voltaje", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge mantiene los accesorios en caché para que no sean eliminados y vueltos a añadir a HomeKit cada vez que Homebridge se reinicia. A veces esta caché puede desincronizarse con los accesorios reales en Homebridge.", "settings.cache.title": "Accesorios", "settings.changes.saved": "Tus cambios se han guardado y requieren un reinicio para surtir efecto.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Pantalla", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Difusión mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si experimentas problemas para conectarte a Homebridge, prueba con alguna de las alternativas de difusión mDNS.", "settings.mdns_advertiser_not_connected": "No Conectado", "settings.mdns_advertiser_rec": "recomendado", - "settings.network.label_interface_name": "Nombre de la Interfaz", - "settings.network.label_ip_address": "Dirección IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si no se seleccionan interfaces de red, Homebridge intentará determinar automáticamente qué interfaces difundir.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Puerto de Homebridge", "settings.network.port_hb_desc": "El número de puerto en el que se ejecutará el puente Homebridge. Debe estar entre 1025 y 65533, y no debe ser el mismo que el puerto de la interfaz de Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Puerto de la Interfaz", "settings.network.port_ui_desc": "El número de puerto en el que se ejecutará la interfaz de Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Red", "settings.network.title_network_interfaces": "Interfaces de Red", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Error al restablecer el puente.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Algunos plugins requieren que configures la variable DEBUG {{ link }} para habilitar el registro a nivel debug.", "settings.service.node_tooltip": "Opciones de ejecución de Node.js para este proceso. Se recomienda dejar esta sección en blanco a menos que sepas lo que estás haciendo.", "settings.startup.debug": "Modo Debug de Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Para controlar tus accesorios a través de la interfaz de Homebridge, debes ejecutar Homebridge en modo inseguro.", "settings.startup.keep_accessories": "Mantener accesorios de los plugins desinstalados", "settings.startup.keep_accessories_desc": "Si está activado, los accesorios de los plugins de plataforma permanecerán en la caché incluso después de que el plugin sea desinstalado. Esto puede ser útil si planeas reinstalar el plugin más tarde.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opciones de Arranque", "settings.unpair_bridge.load_error": "No se pudieron cargar los puentes emparejados.", "setup.button_get_started": "Empezar", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 4db28522a..5f178b6fe 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Kaikki varmuuskopiot poistettu", "config.title_backup_loaded": "Varmuuskopio ladattu", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Peru", "form.button_close": "Sulje", @@ -159,7 +160,6 @@ "form.button_download": "Lataa", "form.button_edit": "Muokkaa", "form.button_enable": "Ota käyttöön", - "form.button_hide": "Piilota", "form.button_lock": "Lukitse", "form.button_more_info": "Lisää tietoa", "form.button_remove": "Poista", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi ilmoittaa juuri havainneensa alijännitteen; tarkista, että se on kytketty sopivaan virtalähteeseen. Alijännite voi johtaa järjestelmän epävakauteen ja SD-kortin vioittumiseen.", "rpi.throttled.previously_message": "Raspberry Pi ilmoittaa havainneensa alijännitteen uudelleenkäynnistyksen jälkeenkin; tarkista, että se on kytketty sopivaan virtalähteeseen.", "rpi.throttled.undervoltage_title": "Alijännite", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge säilyttää tietoja laitteista välimuistissa joten niitä ei poisteta ja lisätä uudelleen HomeKit:in joka kerta kun Homebridge käynnistyy uudelleen. Joskus nämä tiedot poikkeavat Homebridgen todellisesta laitteistosta.", "settings.cache.title": "Laitteet", "settings.changes.saved": "Muutokset on tallennettu ja niiden käyttöönotto vaatii uudellenkäynnistyksen.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Näyttö", "settings.general.title_general": "Yleiset", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS mainostaja", "settings.mdns_advertiser_exp": "kokeellinen", "settings.mdns_advertiser_help": "Jos sinulla on ongelmia Homebridgen yhdistämisessä HomeKitiin (kaikki lisävarusteet näyttävät Home-sovelluksessa No Response), yritä käyttää jotakin vaihtoehtoista mDNS-mainostajaa.", "settings.mdns_advertiser_not_connected": "Ei yhdistetty", "settings.mdns_advertiser_rec": "suositeltava", - "settings.network.label_interface_name": "Sovittimen nimi", - "settings.network.label_ip_address": "IP osoite", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jos verkkosovitinta ei valita, Homebridge yrittää automaattisesti valita sovittimen jota käyttää.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridgen Portti", "settings.network.port_hb_desc": "Homebridgen käyttämän portin numero. On oltava väliltä 1025-65533, ei saa olla sama kuin Homebridge UI:n portti.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Homebridge UI:n Portti", "settings.network.port_ui_desc": "Homebridge UI:n käyttämän portin numero. On oltava väliltä 1025-65533, ei saa olla sama kuin Homebridgen portti.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Verkkosovitin", "settings.network.title_network_interfaces": "Verkkosovittimet", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Jotkut laajennukset tarvitsevat DEBUG {{ link }} ympäristömuuttujan jotta voivat kirjata debug tason lokitietoja.", "settings.service.node_tooltip": "Node.js ajonaikaiset asetukset tälle prosessille. Jätä tyhjäksi, ellet tiedä mitä olet tekemässä.", "settings.startup.debug": "Homebridge vianhaku tila", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Hallitaksesi laitteitasi Homebridge UI:n kautta Homebridgen on toimittava turvattomassa tilassa.", "settings.startup.keep_accessories": "Pidä poistettujen lisäosien laitteet", "settings.startup.keep_accessories_desc": "Jos valittu, niin laitteiden tiedot säilytetään välimuistissa vaikka siihen liittyvä lisäosa poistetaan. Tästä voi olla hyötyä jos myöhemmin asennat lisäosan uudelleen.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Käynnistäminen ja ympäristö", "settings.unpair_bridge.load_error": "Paritettuja siltoja ei voitu otta käyttöön.", "setup.button_get_started": "Aloitetaan", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 7a6174fc5..b981f6744 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Toutes les sauvegardes ont été supprimées", "config.title_backup_loaded": "Sauvegarde chargée", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Annuler", "form.button_close": "Fermer", @@ -159,7 +160,6 @@ "form.button_download": "Télécharger", "form.button_edit": "Modifier", "form.button_enable": "Activer", - "form.button_hide": "Hide", "form.button_lock": "Verrouiller", "form.button_more_info": "Plus d'informations", "form.button_remove": "Supprimer", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Ce Raspberry Pi rencontre actuellement une situation de sous-tension ; Vérifiez qu'il est connecté à une alimentation adaptée. Une sous-tension peut engendrer une instabilité du système et une corruption de sa carte SD.", "rpi.throttled.previously_message": "Ce Raspberry Pi a rencontré une situation de sous-tension depuis son dernier redémarrage ; Vérifiez qu'il est connecté à une alimentation adaptée.", "rpi.throttled.undervoltage_title": "Sous Tension", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "Général", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Diffuseur mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si vous avez des difficultés à vous connecter à Homebridge, essayez d'utiliser un des diffuseurs mDNS alternatif.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nom de l'Interface", - "settings.network.label_ip_address": "Adresse IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si aucune interface réseau n'est sélectionnée, Homebridge essaiera de déterminer automatiquement les interfaces à gérer.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Réseau", "settings.network.title_network_interfaces": "Interfaces Réseau", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Certains plugins exigent que vous définissiez la variable d'environnement DEBUG {{ link }} pour activer le niveau de journalisation de débogage.", "settings.service.node_tooltip": "Options d'exécution Node.js pour le processus Homebridge. Ce champ doit rester vide sauf si vous savez ce que vous faites.", "settings.startup.debug": "Mode de débogage Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Conserver les accessoires des plugins non installés", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Options de démarrage", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Démarrer", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index c327c7d5f..7bee3bd5f 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "כל הגיבויים נמחקו", "config.title_backup_loaded": "גיבוי נטען", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "בטל", "form.button_close": "סגור", @@ -159,7 +160,6 @@ "form.button_download": "הורד", "form.button_edit": "ערוך", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "שם ממשק", - "settings.network.label_ip_address": "כתובת איפי", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "רשת", "settings.network.title_network_interfaces": "ממשק רשת", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index 2d8ef7a1a..bfb6715ac 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Minden biztonsági mentés törölve", "config.title_backup_loaded": "Biztonsági mentés visszaállítva", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Mégse", "form.button_close": "Bezár", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Szerkesztés", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 25cc4c68e..dee4eab3b 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Semua Cadangan Dihapus", "config.title_backup_loaded": "Cadangan Dimuat", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Kembali", "form.button_cancel": "Batal", "form.button_close": "Tutup", @@ -159,7 +160,6 @@ "form.button_download": "Unduh", "form.button_edit": "Ubah", "form.button_enable": "Aktifkan", - "form.button_hide": "Sembunyikan", "form.button_lock": "Kunci", "form.button_more_info": "Info Lebih Lanjut", "form.button_remove": "Hapus", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi ini melaporkan saat ini sedang dalam tegangan; Silakan periksa itu terhubung ke catu daya yang sesuai. Di bawah tegangan dapat mengakibatkan ketidakstabilan sistem dan korupsi kartu SD.", "rpi.throttled.previously_message": "Raspberry Pi ini telah melaporkan acara yang kurang tegangan sejak terakhir di-boot ulang; Silakan periksa itu terhubung ke catu daya yang sesuai.", "rpi.throttled.undervoltage_title": "Di bawah tegangan", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge memelihara aksesori dalam cache sehingga tidak dilepas dan ditahan kembali ke HomeKit setiap kali Homebridge restart. Terkadang cache ini bisa tidak selaras dengan aksesori aktual di Homebridge.", "settings.cache.title": "Aksesoris", "settings.changes.saved": "Perubahan Anda telah disimpan dan mengharuskan restart untuk berlaku.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Penampilan", "settings.general.title_general": "Umum", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Pengiklan mDNS", "settings.mdns_advertiser_exp": "Eksperimental", "settings.mdns_advertiser_help": "Jika Anda mengalami masalah saat menghubungkan ke Homebridge, coba gunakan salah satu pengiklan mDNS alternatif.", "settings.mdns_advertiser_not_connected": "Tidak terhubung", "settings.mdns_advertiser_rec": "direkomendasikan", - "settings.network.label_interface_name": "Nama Antarmuka", - "settings.network.label_ip_address": "Alamat IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jika tidak ada antarmuka jaringan yang terpilih, Homebridge akan mencoba menentukan secara otomatis antarmuka yang akan diumumkan.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Port Homebridge", "settings.network.port_hb_desc": "Nomor port untuk menjalankan Homebridge Bridge menyala.Ini harus antara 1025 dan 65533, dan tidak boleh sama dengan port UI Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Port UI", "settings.network.port_ui_desc": "Nomor port untuk menjalankan Homebridge UI.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Jaringan", "settings.network.title_network_interfaces": "Antarmuka Jaringan", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Gagal mengatur ulang jembatan.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Beberapa plugin mengharuskan Anda untuk mengatur variabel lingkungan debug {{ link }} untuk mengaktifkan pencatatan level debug.", "settings.service.node_tooltip": "Opsi runtime node.js untuk proses ini. Ini harus tetap kosong kecuali Anda tahu apa yang Anda lakukan.", "settings.startup.debug": "Mode Debug Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Untuk mengontrol aksesori Anda melalui Homebridge UI, Anda harus menjalankan Homebridge dalam mode tidak aman.", "settings.startup.keep_accessories": "Simpan aksesoris plugin yang tidak diinstal", "settings.startup.keep_accessories_desc": "Jika diaktifkan, aksesori plugin platform akan tetap berada di cache bahkan setelah plugin tidak diinstal. Ini bisa berguna jika Anda berencana untuk menginstal ulang plugin nanti.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opsi Startup", "settings.unpair_bridge.load_error": "Jembatan berpasangan tidak dapat dimuat.", "setup.button_get_started": "Mulai", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 5065dc54d..b58fe77a3 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Backup eliminati", "config.title_backup_loaded": "Backup caricato", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancella", "form.button_close": "Chiudi", @@ -159,7 +160,6 @@ "form.button_download": "Scarica", "form.button_edit": "Modifica", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Questo Raspberry Pi segnala che la sua tensione di alimentazione è bassa; verificare che sia collegato a un'alimentazione adeguata. Una tensione di alimentazione bassa può causare l'instabilità del sistema e la corruzione della scheda SD.", "rpi.throttled.previously_message": "Questo Raspberry Pi ha segnalato un calo della tensione di alimentazione dall'ultimo riavvio; verificare che sia collegato a un'alimentazione adeguata.", "rpi.throttled.undervoltage_title": "Calo di Tensione", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Annunciatore mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se stai avendo problemi a collegarti a Homebridge, prova a utilizzare un altro annunciatore mDNS.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome dell'interfaccia", - "settings.network.label_ip_address": "Indirizzo IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nessuna interfaccia di rete è selezionata, Homebridge sceglierà automaticamente su quali annunciarsi.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rete", "settings.network.title_network_interfaces": "Interfacce di rete", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opzioni di avvio", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Inizia", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 0f994944c..ca65958db 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "バックアップは全て削除されました", "config.title_backup_loaded": "バックアップを読み込みました", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "キャンセル", "form.button_close": "閉じる", @@ -159,7 +160,6 @@ "form.button_download": "ダウンロード", "form.button_edit": "編集", "form.button_enable": "有効化", - "form.button_hide": "Hide", "form.button_lock": "ロック", "form.button_more_info": "詳細情報", "form.button_remove": "削除", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "このRaspberry Piは現在電圧不足であると報告しています。適切な電源に接続されているか確認してください。電圧不足はシステムを不安定にし、SDカードの破損を引き起こす可能性があります。", "rpi.throttled.previously_message": "このRaspberry Piは、最後に再起動してから電圧不足が発生しています。", "rpi.throttled.undervoltage_title": "電圧不足を検出", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS広告主", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Homebridgeへの接続に問題がある場合は、別のmDNS広告主を使用してみてください。", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "インターフェイス名", - "settings.network.label_ip_address": "IPアドレス", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "ネットワークインターフェイスが選択されていない場合、Homebridgeは送受信するインターフェイスを自動的に設定しようとします。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "ネットワーク", "settings.network.title_network_interfaces": "ネットワークインターフェイス", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "プラグインによっては、デバッグレベルのロギングを有効にするためにDEBUG環境変数を設定する必要があります {{ link }}。", "settings.service.node_tooltip": "HomebridgeプロセスのNode.jsランタイム・オプション。よくわからない場合は、空白のままが良いでしょう。", "settings.startup.debug": "Homebridge デバッグモード", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "未インストールのプラグインのアクセサリーを保管する", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "起動オプション", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "さぁ、始めよう!", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index e8ec9d11f..c911bc7ac 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "모든 백업을 삭제하였습니다", "config.title_backup_loaded": "백업이 로드되었습니다", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "취소", "form.button_close": "닫기", @@ -159,7 +160,6 @@ "form.button_download": "다운로드", "form.button_edit": "수정", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "이 Raspberry Pi의 전압(Low voltage)이 불안정 합니다. 전압이 낮은경우 시스템이 불안정해지고 SD카드가 손상될 수 있습니다. Pi 버전에 맞게 적절한 전원을 공급 하거나 케이블을 점검 하세요.", "rpi.throttled.previously_message": "마지막 재부팅 이후 Raspberry Pi로 부터 전압 부족 이벤트를 수신하였습니다. Pi 버전에 맞게 적절한 전원을 공급 하거나 케이블을 점검 하세요.", "rpi.throttled.undervoltage_title": "저전압", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge는 액세서리를 캐시에 유지하여 매번 재시작할 때 HomeKit에서 제거되었다가 다시 추가되지 않도록 합니다. 그러나 이 캐시가 실제 Homebridge의 액세서리와 동기화되지 않을 때도 있습니다.", "settings.cache.title": "액세서리", "settings.changes.saved": "변경 사항이 저장되었습니다. 적용하려면 재시작이 필요합니다.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "디스플레이", "settings.general.title_general": "일반", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS 광고자", "settings.mdns_advertiser_exp": "실험적", "settings.mdns_advertiser_help": "Homebridge를 HomeKit에 연결하는 데 문제가 있는 경우(홈 앱에서 모든 액세서리가 '응답 없음'으로 표시되는 경우), 다른 mDNS 광고자를 사용해 보세요.", "settings.mdns_advertiser_not_connected": "연결되지 않음", "settings.mdns_advertiser_rec": "권장", - "settings.network.label_interface_name": "인터페이스 이름", - "settings.network.label_ip_address": "IP 주소", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "네트워크 인터페이스가 선택되지 않으면, Homebridge는 자동으로 발송할 인터페이스 결정합니다.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge 포트", "settings.network.port_hb_desc": "Homebridge Bridge를 실행할 포트 번호입니다. 1025에서 65533 사이여야 하며 Homebridge UI 포트와 동일하지 않아야 합니다.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI 포트", "settings.network.port_ui_desc": "Homebridge UI를 실행할 포트 번호입니다.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "네트워크", "settings.network.title_network_interfaces": "네트워크 인터페이스", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "일부 플러그인은 디버그 수준의 로그를 활성화하려면 DEBUG {{ link }} 환경 변수를 설정해야 합니다.", "settings.service.node_tooltip": "이 프로세스의 Node.js 런타임 옵션입니다. 잘 알고 있는 경우가 아니라면 빈칸으로 두는 것이 좋습니다.", "settings.startup.debug": "Homebridge 디버그 모드", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Homebridge UI를 통해 액세서리를 제어하려면 Homebridge를 비보안 모드에서 실행해야 합니다.", "settings.startup.keep_accessories": "제거된 플러그인의 액세서리 유지", "settings.startup.keep_accessories_desc": "활성화하면, 플랫폼 플러그인의 액세서리는 플러그인을 삭제한 후에도 캐시에 남아 있습니다. 나중에 플러그인을 다시 설치하려는 경우 유용할 수 있습니다.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "시작 옵션", "settings.unpair_bridge.load_error": "페어링된 Bridge를 불러오는 데 실패했습니다.", "setup.button_get_started": "설치 마법사 시작", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index c81c93bbf..41f5f69cc 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Сите бекапи се избришани", "config.title_backup_loaded": "Вчитан бекап", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Откажи", "form.button_close": "Затвори", @@ -159,7 +160,6 @@ "form.button_download": "Симни", "form.button_edit": "Измени", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Име на интерфејс", - "settings.network.label_ip_address": "IP адреса", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Ако немате одбрано ниеден мрежен интерфејс, Homebridge ќе проба автоматски да одреди на кои интерфејси да испраќа advertisements.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Мрежа", "settings.network.title_network_interfaces": "Мрежни интерфејси", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Опции за стартување", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 0e06449b3..a6dc1ed46 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle backups zijn verwijderd", "config.title_backup_loaded": "Backup Geladen", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Annuleren", "form.button_close": "Sluiten", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Bewerken", "form.button_enable": "Activeren", - "form.button_hide": "Verbergen", "form.button_lock": "Vergrendelen", "form.button_more_info": "Meer Info", "form.button_remove": "Verwijderen", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Deze Raspberry Pi rapporteert een te laag voltage; controleer of verbonden is met een geschikte power supply. Een te laag voltage kan in systeem instabilitei of SD card corruptie veroorzaken.", "rpi.throttled.previously_message": "Deze Raspberry Pi rapporteert een te laag voltage event vanaf de laatste reboot; controleer of verbonden is met een geschikte power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge bewaart accessoires in cache zodat zij niet verwijderd worden en opnieuw toegevoegd aan HomeKit iedere keer dat Homebridge herstart. Soms kan deze cache out of sync raken met de daadwerkelijke accessoires in Homebridge.", "settings.cache.title": "Accessoires", "settings.changes.saved": "Uw wijzigingen zijn opgeslagen en vereisen een herstart om actief te worden.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Scherm", "settings.general.title_general": "Algemeen", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimenteel", "settings.mdns_advertiser_help": "Als U problemen ervaart bij het koppelen met Homebridge, probeer dan een van de alternatieve mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Niet Verbonden", "settings.mdns_advertiser_rec": "aanbevolen", - "settings.network.label_interface_name": "Interface Naam", - "settings.network.label_ip_address": "IP Adres", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Als geen netwerk interfaces geselecteerd zijn, dan zal Homebridge automatisch proberen vast te stellen welke interfaces advertised moeten worden.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Het port nummmer waarop Homebridge bridge moet draaien. Dit moet liggen tussen 1025 en 65533, en mag niet hetzelfde zijn als de Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Het port number waarop de Homebridge UI moet draaien.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Netwerk", "settings.network.title_network_interfaces": "Netwerk Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Sommige plugins vereisen om de DEBUG environment variabele {{ link }} te configureren om debug level logging te activeren.", "settings.service.node_tooltip": "Node.js runtime opties voor dit proces. Dit moet leeg blijven tenzij je weet wat je doet.", "settings.startup.debug": "Homebridge Debug Modus", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Om accessories via de Homebridge UI te bedienen moet Homebridge in insecure modus opereren.", "settings.startup.keep_accessories": "Bewaar Accessoires Van gedeïnstalleerde Plugins", "settings.startup.keep_accessories_desc": "Indine geactiveerd, zullen accessoires van platform plugins in cache bewaard blijven ook als de plugin is gedeïnstalleerd. Dit kan handig zijn als U van plan bent de plugin later opnieuw te installeren.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup Opties", "settings.unpair_bridge.load_error": "Gekoppelde bridges konden niet geladen worden.", "setup.button_get_started": "Beginnen", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index e4ab789ba..59ce8f862 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle sikkerhetskopier slettet", "config.title_backup_loaded": "Backup lastet", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Avbryt", "form.button_close": "Lukk", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Rediger", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index fd40ddf54..ab03283ac 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Wszystkie kopie zapasowe zostały usunięte", "config.title_backup_loaded": "Backup został załadowany", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Anuluj", "form.button_close": "Zamknij", @@ -159,7 +160,6 @@ "form.button_download": "Pobierz", "form.button_edit": "Edytuj", "form.button_enable": "Włącz", - "form.button_hide": "Ukryj", "form.button_lock": "Zablokuj", "form.button_more_info": "Więcej info", "form.button_remove": "Usuń", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi zgłasza aktualnie za niskie napięcie - sprawdź czy jest zasilane z odpowiedniego zasilacza. Zbyt niskie napięcie może powodować niestabilną prace i uszkodzić kartę SD.", "rpi.throttled.previously_message": "Raspberry Pi zgłaszało zbyt niskie napięcie od ostatniego uruchomienia - sprawdź czy jest zasilane z odpowiedniego zasilacza.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge utrzymuje pamięć podręczną z informacjami o akcesoriach aby nie były one usuwane i ponownie dodawane do HomeKit za każdym razem gdy Homebridge uruchamia się ponownie. Czasami pamięć podręczna może stać się niezsynchronizowana z rzeczywistymi akcesoriami w Homebridge.", "settings.cache.title": "Akcesoria", "settings.changes.saved": "Twoje zmiany zostały zapisane i wymagają ponownego uruchomienia.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Wygląd", "settings.general.title_general": "Ogólne", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Rozgłaszacz mDNS", "settings.mdns_advertiser_exp": "eksperymentalny", "settings.mdns_advertiser_help": "Jeśli masz problem z połączeniem Homebridge do HomeKit, spróbuj użyć alternatywnego rozgłaszania mDNS.", "settings.mdns_advertiser_not_connected": "Rozłączony", "settings.mdns_advertiser_rec": "zalecane", - "settings.network.label_interface_name": "Nazwa interfejsu", - "settings.network.label_ip_address": "Adres IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jeśli żaden interfejs nie zostanie wybrany, Homebridge wybierze automatycznie.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Port Homebridge. Musi być między 1025 a 65533 i nie powinien być taki sam jak port Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Port Homebridge UI. Nie powinien być taki sam jak port Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Sieć", "settings.network.title_network_interfaces": "Interfejsy sieciowe", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Niektóre wtyczki wymagają ustawienia zmiennej środowiskowej DEBUG {{ link }} aby umożliwić rejestrowanie poziomu debugowania.", "settings.service.node_tooltip": "Opcje uruchomieniowe Node.js dla procesu Homebridge. To pole powinno być puste, chyba że wiesz co robisz.", "settings.startup.debug": "Tryb Homebridge Debug", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Aby sterować akcesoriami za pomocą interfejsu użytkownika Homebridge, musisz uruchomić Homebridge w trybie niezabezpieczonym (Insecure).", "settings.startup.keep_accessories": "Zachowaj akcesoria odinstalowanych wtyczek", "settings.startup.keep_accessories_desc": "Akcesoria wtyczek (tych typu platform) pozostaną w pamięci podręcznej nawet po odinstalowaniu wtyczki. Może to być przydatne jeśli planujesz ponownie zainstalować wtyczkę w przyszłości.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opcje specjalne", "settings.unpair_bridge.load_error": "Nie można było załadować sparowanych mostków.", "setup.button_get_started": "Rozpocznij", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 4e35f1a73..3a996a273 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Todos os backups foram removidos", "config.title_backup_loaded": "Backup Carregado", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancelar", "form.button_close": "Fechar", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Editar", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Subtensão", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Anunciante mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se você está tendo problemas ao conectar com o Homebridge, tente usar um dos anunciantes mDNS alternativos.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome da Interface", - "settings.network.label_ip_address": "Endereço IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nenhuma interface de rede for selecionada, Homebridge tentará determinar automaticamente qual interface irá utilizar.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rede", "settings.network.title_network_interfaces": "Interfaces de Rede", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opções de Inicialização", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 887c6e296..76cb2c820 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Eliminados Todos os Backups", "config.title_backup_loaded": "Backup Carregado", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancelar", "form.button_close": "Fechar", @@ -159,7 +160,6 @@ "form.button_download": "Descarregar", "form.button_edit": "Editar", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Este Raspberry Pi está a reportar que se encontra atualmente em subtensão; por favor verifique se está conectado a uma fonte de alimentação apropriada. Subtensão poderá provocar instabilidade de sistema e corromper o cartão SD.", "rpi.throttled.previously_message": "Este Raspberry Pi reportou um evento de subtensão desde a ultima inicialização; por favor verifique se está conectado a uma fonte de alimentação apropriada.", "rpi.throttled.undervoltage_title": "Subtensão", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Encaminhamento mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se estiver a ter problemas a conectar ao Homebridge, tente um dos encaminhamentos mDNS alternativos.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome da Interface", - "settings.network.label_ip_address": "Endereço IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nenhuma interface de rede estiver selecionada, o Homebridge irá tentar determinar automaticamente qual interface a utilizar.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rede", "settings.network.title_network_interfaces": "Interfaces de Rede", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opções de Inicio", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Começar", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 3976f41f4..5e12a1e7a 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Все резервные копии удалены", "config.title_backup_loaded": "Резервная копия загружена", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Назад", "form.button_cancel": "Отмена", "form.button_close": "Закрыть", @@ -159,7 +160,6 @@ "form.button_download": "Скачать", "form.button_edit": "Редактировать", "form.button_enable": "Включить", - "form.button_hide": "Скрыть", "form.button_lock": "Заблокировать", "form.button_more_info": "Дополнительная информация", "form.button_remove": "Удалить", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Этот Raspberry Pi сообщает о текущем пониженном напряжении; проверьте подключение к подходящему источнику питания. Недостаточное питание может привести к нестабильной работе системы и повреждению SD-карты.", "rpi.throttled.previously_message": "Этот Raspberry Pi зафиксировал событие пониженного напряжения с момента последней перезагрузки; проверьте подключение к подходящему источнику питания.", "rpi.throttled.undervoltage_title": "Пониженное напряжение", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge хранит аксессуары в кэше, чтобы они не удалялись и не добавлялись заново в HomeKit при каждом перезапуске Homebridge. Иногда кэш может стать несогласованным с реальными аксессуарами в Homebridge.", "settings.cache.title": "Аксессуары", "settings.changes.saved": "Ваши изменения сохранены. Для вступления в силу требуется перезапуск.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Отображение", "settings.general.title_general": "Основные", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Рекламодатель mDNS", "settings.mdns_advertiser_exp": "экспериментально", "settings.mdns_advertiser_help": "Если у вас возникают проблемы с подключением Homebridge к HomeKit (все аксессуары отображаются как 'Нет ответа' в приложении Дом), попробуйте использовать альтернативного рекламодателя mDNS.", "settings.mdns_advertiser_not_connected": "Нет подключения", "settings.mdns_advertiser_rec": "рекомендуется", - "settings.network.label_interface_name": "Имя интерфейса", - "settings.network.label_ip_address": "IP-адрес", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Если ни один сетевой интерфейс не выбран, Homebridge попытается определить интерфейсы для рекламы автоматически.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Порт Homebridge", "settings.network.port_hb_desc": "Номер порта, на котором работает мост Homebridge. Диапазон допустимых значений — от 1025 до 65533. Порт не должен совпадать с портом интерфейса Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "Порт Homebridge UI", "settings.network.port_ui_desc": "Номер порта, на котором работает интерфейс Homebridge UI. Диапазон допустимых значений — от 1025 до 65533. Порт не должен совпадать с портом Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Сеть", "settings.network.title_network_interfaces": "Сетевые интерфейсы", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Не удалось сбросить мост.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Некоторые плагины требуют установки переменной окружения DEBUG {{ link }} для включения журналирования отладки.", "settings.service.node_tooltip": "Параметры выполнения среды Node.js для этого процесса. Оставьте поле пустым, если вы не уверены, что делаете.", "settings.startup.debug": "Режим отладки Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Для управления вашими аксессуарами через Homebridge UI необходимо запустить Homebridge в небезопасном режиме.", "settings.startup.keep_accessories": "Сохранять аксессуары удалённых плагинов", "settings.startup.keep_accessories_desc": "Если включено, аксессуары платформенных плагинов останутся в кэше даже после удаления плагина. Это может быть полезно, если вы планируете переустановить плагин позже.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Параметры запуска и окружения", "settings.unpair_bridge.load_error": "Не удалось загрузить привязанные мосты.", "setup.button_get_started": "Начать работу", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index da7199576..af2c2300b 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Vse varnostne kopije so izbrisane", "config.title_backup_loaded": "Varnostna kopija naložena", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Prekini", "form.button_close": "zapri", @@ -159,7 +160,6 @@ "form.button_download": "Prenesi", "form.button_edit": "Uredi", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS oglaševalec", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Če imate težave s povezovanjem z Homebridgeom, poskusite uporabiti enega od nadomestnih oglaševalcev mDNS.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Ime vmesnika", - "settings.network.label_ip_address": "IP naslov", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Če ni izbran noben omrežni vmesnik, bo Homebridge poskušal samodejno določiti, katere vmesnike oglaševati.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Omrežje", "settings.network.title_network_interfaces": "Omrežni vmesniki", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Možnosti zagona", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 312cbac57..9e7e239bc 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alla säkerhetskopior raderade", "config.title_backup_loaded": "Säkerhetskopia återställd", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Avbryt", "form.button_close": "Stäng", @@ -159,7 +160,6 @@ "form.button_download": "Ladda ner", "form.button_edit": "Redigera", "form.button_enable": "Aktivera", - "form.button_hide": "Dölj", "form.button_lock": "Lås", "form.button_more_info": "Mer info", "form.button_remove": "Ta bort", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Denna Raspberry Pi rapporterar att det för närvarande är underspänning; kontrollera att den är ansluten till en lämplig strömkälla. Underspänning kan resultera i systeminstabilitet och skada på SD-kortet.", "rpi.throttled.previously_message": "Denna Raspberry Pi har rapporterat en underspänningshändelse sedan den startades om senast; kontrollera att den är ansluten till en lämplig strömkälla.", "rpi.throttled.undervoltage_title": "Underspänning", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "Allmänt", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS-annonsör", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Om du har problem med att ansluta till Homebridge, prova att använda någon av de alternativa mDNS-annonsörerna.", "settings.mdns_advertiser_not_connected": "Ej ansluten", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Gränssnittsnamn", - "settings.network.label_ip_address": "IP-adress", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Om inga nätverksgränssnitt väljs kommer Homebridge att försöka avgöra vilka gränssnitt som ska annonseras automatiskt.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Nätverk", "settings.network.title_network_interfaces": "Nätverksgränssnitt", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Vissa plugins kräver att du sätter miljövariabeln DEBUG {{ link }} för att aktivera debug-loggning.", "settings.service.node_tooltip": "Node.js runtime-alternativ för den här processen. Denna bör vara tom om du inte vet vad du gör.", "settings.startup.debug": "Homebridge Debug-läge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Behåll tillbehör till avinstallerade plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startalternativ", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Kom igång", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 94e10b32a..d14c64143 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "ลบข้อมูลสำรองทั้งหมดแล้ว", "config.title_backup_loaded": "โหลดข้อมูลสำรองแล้ว", "form.auto_save": "การเปลี่ยนแปลงจะได้รับการบันทึกโดยอัตโนมัติ", + "form.button_allow": "Allow", "form.button_back": "ย้่อนกลับ", "form.button_cancel": "ยกเลิก", "form.button_close": "ปิด", @@ -159,7 +160,6 @@ "form.button_download": "ดาวน์โหลด", "form.button_edit": "แก้ไข", "form.button_enable": "เปิดการใช้งาน", - "form.button_hide": "ซ่อน", "form.button_lock": "ล๊อค", "form.button_more_info": "ข้อมูลเพิ่มเติม", "form.button_remove": "ลบ", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi นี้กำลังรายงานว่าปัจจุบันมีแรงดันไฟฟ้าต่ำ โปรดตรวจสอบว่าได้เชื่อมต่อกับแหล่งจ่ายไฟที่เหมาะสมแล้ว แรงดันไฟต่ำอาจส่งผลให้ระบบไม่เสถียรและการ์ด SD เสียหาย", "rpi.throttled.previously_message": "Raspberry Pi นี้รายงานเหตุการณ์ที่มีแรงดันไฟฟ้าต่ำตั้งแต่มีการรีบูตครั้งล่าสุด โปรดตรวจสอบว่าได้เชื่อมต่อกับแหล่งจ่ายไฟที่เหมาะสมแล้ว", "rpi.throttled.undervoltage_title": "ตรวจพบแรงดันไฟฟ้าต่ำ", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge จะเก็บอุปกรณ์เสริมไว้ในแคช เพื่อไม่ให้อุปกรณ์เสริมเหล่านั้นถูกลบออกและเพิ่มกลับเข้าไปใน HomeKit ทุกครั้งที่รีสตาร์ท Homebridge บางครั้งแคชนี้อาจไม่ซิงค์กับอุปกรณ์เสริมจริงใน Homebridge", "settings.cache.title": "อุปกรณ์เสริม", "settings.changes.saved": "การเปลี่ยนแปลงของคุณได้รับการบันทึกแล้วและต้องรีสตาร์ทจึงจะมีผล.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "อัปเดตวอลเปเปอร์สำเร็จแล้ว", "settings.general.title_display": "การแดงผล", "settings.general.title_general": "ทั่วไป", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "การทดลอง", "settings.mdns_advertiser_help": "หากคุณประสบปัญหาในการเชื่อมต่อกับ Homebridge ให้ลองใช้ mDNS รายใดรายหนึ่ง.", "settings.mdns_advertiser_not_connected": "ไม่ได้เชื่อมต่อ", "settings.mdns_advertiser_rec": "ที่แนะนำ", - "settings.network.label_interface_name": "ชื่ออินเทอร์เฟซ", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "หากไม่ได้เลือกอินเทอร์เฟซเครือข่าย Homebridge จะพยายามกำหนดโดยอัตโนมัติว่าจะใช้อินเทอร์เฟซใด", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "พอร์ต Homebridge", "settings.network.port_hb_desc": "หมายเลขพอร์ตที่จะเรียกใช้ Homebridge bridge ต้องอยู่ระหว่าง 1025 ถึง 65533 และไม่ควรเป็นหมายเลขเดียวกับพอร์ต Homebridge UI", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "พอร์ต UI", "settings.network.port_ui_desc": "หมายเลขพอร์ตที่จะรัน Homebridge UI", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "เครือข่าย", "settings.network.title_network_interfaces": "การเชื่อมต่อเครือข่าย", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "การรีเซ็ตบริดจ์ล้มเหลว", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "ปลั๊กอินบางตัวต้องการให้คุณตั้งค่าตัวแปรสภาพแวดล้อม DEBUG {{ link }} เพื่อเปิดใช้งานการบันทึกระดับการดีบัก", "settings.service.node_tooltip": "ตัวเลือกรันไทม์ Node.js สำหรับกระบวนการ Homebridge ควรเว้นว่างไว้ ยกเว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่", "settings.startup.debug": "โหมด Debug Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "หากต้องการควบคุมอุปกรณ์เสริมของคุณผ่าน Homebridge UI คุณต้องใช้งาน Homebridge ในโหมดไม่ปลอดภัย", "settings.startup.keep_accessories": "เก็บอุปกรณ์เสริมของปลั๊กอินที่ถอนการติดตั้งไว้", "settings.startup.keep_accessories_desc": "หากเปิดใช้งาน อุปกรณ์เสริมของปลั๊กอินแพลตฟอร์มจะยังคงอยู่ในแคชแม้ว่าจะถอนการติดตั้งปลั๊กอินแล้วก็ตาม ซึ่งอาจมีประโยชน์หากคุณวางแผนจะติดตั้งปลั๊กอินใหม่ในภายหลัง", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "ตัวเลือกการเริ่มต้น", "settings.unpair_bridge.load_error": "บริดจ์จับคู่ไม่สามารถโหลดได้", "setup.button_get_started": "เริ่ม", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 2988dbbc8..cd59eeace 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Tüm Yedeklemeler Silindi", "config.title_backup_loaded": "Yedekleme Yüklendi", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "İptal Et", "form.button_close": "Kapat", @@ -159,7 +160,6 @@ "form.button_download": "İndir", "form.button_edit": "Düzenle", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Arayüz Adı", - "settings.network.label_ip_address": "IP Adresi", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Eğer herhangi bir ağ arayüzü seçilmezse, Homebridge otomatik olarak yayın yapması gereken arayüzü tesip etmeyi deneyecektir.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Ağ", "settings.network.title_network_interfaces": "Ağ Arayüzleri", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Başlangıç Seçenekleri", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 43693817e..2c42b84e7 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Всі резервні копії видалено", "config.title_backup_loaded": "Резервна копія завантажена", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Назад", "form.button_cancel": "Відмінити", "form.button_close": "Закрити", @@ -159,7 +160,6 @@ "form.button_download": "Завантажити", "form.button_edit": "Редагувати", "form.button_enable": "Увімкнути", - "form.button_hide": "Приховати", "form.button_lock": "Заблокувати", "form.button_more_info": "Більше інформації", "form.button_remove": "Видалити", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Цей Raspberry Pi повідомляє, що зараз він перебуває під низькою напругою. Переконайтеся, що він під'єднаний до відповідного джерела живлення. Низька напруга може призвести до нестабільності системи та пошкодження SD-карти.", "rpi.throttled.previously_message": "Цей Raspberry Pi повідомив про подію низької напруги з моменту останнього перезавантаження. Будь ласка, перевірте, чи під’єднано його до відповідного джерела живлення.", "rpi.throttled.undervoltage_title": "Низька Напруга", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge зберігає аксесуари в кеш-пам’яті, тому вони не видаляються та не додаються повторно до HomeKit кожного разу, коли Homebridge перезапускається. Іноді цей кеш може не синхронізуватися з фактичними аксесуарами в Homebridge.", "settings.cache.title": "Аксесуари", "settings.changes.saved": "Ваші зміни збережено. Щоб вони набрали чинності, потрібно перезавантажити.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Дисплей", "settings.general.title_general": "Загальні", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Рекламіст mDNS", "settings.mdns_advertiser_exp": "експериментальний", "settings.mdns_advertiser_help": "Якщо у Вас виникли проблеми з підключенням до Homebridge, спробуйте скористатися одним із альтернативних рекламвстів mDNS.", "settings.mdns_advertiser_not_connected": "Не з'єднано", "settings.mdns_advertiser_rec": "рекомендований", - "settings.network.label_interface_name": "Назва інтерфейсу", - "settings.network.label_ip_address": "IP Адреса", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Якщо не обрано жодного мережевого інтерфейсу, Homebridge спробує автоматично визначити, які інтерфейси рекламувати.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge порт", "settings.network.port_hb_desc": "Номер порту для запуску мосту Homebridge. Він має бути між 1025 і 65533 і не повинен збігатися з портом інтерфейсу користувача Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI порт", "settings.network.port_ui_desc": "Номер порту для запуску UI Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Мережа", "settings.network.title_network_interfaces": "Інтерфейс мережі", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Не вдалося скинути міст.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Деякі плагіни вимагають встановлення змінного середовища DEBUG {{ link }}, щоб увімкнути ведення журналу на рівні налагодження.", "settings.service.node_tooltip": "Параметри середовища виконання Node.js для процесу Homebridge. Це має бути пустим, якщо Ви не знаєте, що робите.", "settings.startup.debug": "Homebridge режим «Налагодження»", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Щоб керувати аксесуарами через UI Homebridge, необхідно запустити Homebridge у незахищеному режимі.", "settings.startup.keep_accessories": "Зберігайте аксесуари видалених плагінів", "settings.startup.keep_accessories_desc": "Якщо ввімкнено, аксесуари плагінів платформи залишатимуться в кеші навіть після видалення плагіна. Це може бути корисним, якщо Ви плануєте перевстановити плагін пізніше.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Пареметри запуску", "settings.unpair_bridge.load_error": "Не вдалося завантажити парні мости.", "setup.button_get_started": "Розпочати", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 00b3af8b3..15318d538 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "所有备份已删除", "config.title_backup_loaded": "已载入备份", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "取消", "form.button_close": "关闭", @@ -159,7 +160,6 @@ "form.button_download": "下载", "form.button_edit": "编辑", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "如果你无法链接到 Homebridge, 请尝试更换 mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "端口名称", - "settings.network.label_ip_address": "IP 地址", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "如果没有网络端口被选中, Homebridge 将会尝试自动搜索端口并广播。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "网络", "settings.network.title_network_interfaces": "网络端口", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "启动选项", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index a6c0f76ad..001313e5b 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "已刪除所有備份", "config.title_backup_loaded": "已讀取備份", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "取消", "form.button_close": "關閉", @@ -159,7 +160,6 @@ "form.button_download": "下載", "form.button_edit": "編輯", "form.button_enable": "啟用", - "form.button_hide": "隱藏", "form.button_lock": "上鎖", "form.button_more_info": "更多資訊", "form.button_remove": "移除", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "假如於連線 Homebridge 時遇到問題,請試著使用替代的 mDNS Advertiser。", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "介面名稱", - "settings.network.label_ip_address": "IP 位址", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "如果沒有選擇網路介面,Homebridge 將會自動偵測所要使用的網路介面。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and higher than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and lower than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "網路", "settings.network.title_network_interfaces": "網路介面", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "啟動選項", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", From 0a4f98fbbcbade2a01a1b29f830ca6e750d20bca Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 15 Jun 2025 05:33:43 +0100 Subject: [PATCH 20/40] add support for `uiSchema` within plugin configurations --- CHANGELOG.md | 1 + .../app/core/components/schema-form/schema-form.component.html | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d28f9e8..9226975c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - style HBv2/UIv5 icons on status page based on readiness - security system modal only show valid modes - refactor settings page with immediate saving +- add support for `uiSchema` within plugin configurations ### Homebridge Dependencies diff --git a/ui/src/app/core/components/schema-form/schema-form.component.html b/ui/src/app/core/components/schema-form/schema-form.component.html index ab8feed2b..462b7b0f1 100644 --- a/ui/src/app/core/components/schema-form/schema-form.component.html +++ b/ui/src/app/core/components/schema-form/schema-form.component.html @@ -4,6 +4,7 @@ [jsfPatch]="configSchema.fixArrays" [options]="jsonFormOptions" [schema]="configSchema.schema" + [UISchema]="configSchema.uiSchema" [layout]="configSchema.layout" [form]="configSchema.form" [data]="currentData" From 03a92fa3a53976a20988ef4ace4262b33e893efa Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 15 Jun 2025 12:20:08 +0100 Subject: [PATCH 21/40] add option to hide update notifications for specific plugins --- CHANGELOG.md | 1 + config.schema.json | 17 +++++++ src/core/config/config.service.ts | 6 +++ .../config-editor/config-editor.controller.ts | 9 ++++ .../config-editor/config-editor.service.ts | 21 ++++++++ .../manage-plugin/manage-plugin.component.ts | 2 +- .../manage-version.component.html | 21 ++++++++ .../manage-version.component.ts | 39 +++++++++++++- ui/src/app/core/settings.service.ts | 3 ++ .../app/modules/plugins/plugins.component.ts | 51 +++++++++++++------ .../update-info-widget.component.ts | 3 +- ui/src/i18n/bg.json | 2 + ui/src/i18n/ca.json | 2 + ui/src/i18n/cs.json | 2 + ui/src/i18n/de.json | 2 + ui/src/i18n/en.json | 2 + ui/src/i18n/es.json | 2 + ui/src/i18n/fi.json | 2 + ui/src/i18n/fr.json | 2 + ui/src/i18n/he.json | 2 + ui/src/i18n/hu.json | 2 + ui/src/i18n/id.json | 2 + ui/src/i18n/it.json | 2 + ui/src/i18n/ja.json | 2 + ui/src/i18n/ko.json | 2 + ui/src/i18n/mk.json | 2 + ui/src/i18n/nl.json | 2 + ui/src/i18n/no.json | 2 + ui/src/i18n/pl.json | 2 + ui/src/i18n/pt-BR.json | 2 + ui/src/i18n/pt.json | 2 + ui/src/i18n/ru.json | 2 + ui/src/i18n/sl.json | 2 + ui/src/i18n/sv.json | 2 + ui/src/i18n/th.json | 2 + ui/src/i18n/tr.json | 2 + ui/src/i18n/uk.json | 2 + ui/src/i18n/zh-CN.json | 2 + ui/src/i18n/zh-TW.json | 2 + 39 files changed, 211 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9226975c6..80308d2d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - security system modal only show valid modes - refactor settings page with immediate saving - add support for `uiSchema` within plugin configurations +- add option to hide update notifications for specific plugins ### Homebridge Dependencies diff --git a/config.schema.json b/config.schema.json index 809c11f6e..da6edc5ce 100644 --- a/config.schema.json +++ b/config.schema.json @@ -633,6 +633,23 @@ "title": "Disable Server Metrics Monitoring", "type": "boolean", "description": "When enabled, the Homebridge UI will not collect or report CPU or memory stats." + }, + "plugins": { + "title": "Plugins", + "type": "object", + "description": "Settings surrounding plugins used by the Homebridge UI.", + "properties": { + "hideUpdatesFor": { + "type": "array", + "title": "Hide Plugin Updates For", + "description": "A list of plugin names for which frontend update notifications will be hidden.", + "items": { + "type": "string", + "title": "Plugin Name", + "pattern": "^(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$" + } + } + } } } }, diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index eeaa89b0f..dbe9e73a2 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -107,6 +107,9 @@ export class ConfigService { debug?: boolean instanceBlacklist?: string[] } + plugins?: { + hideUpdatesFor?: string[] + } temp?: string tempUnits?: string wallpaper?: string @@ -253,6 +256,9 @@ export class ConfigService { debug: this.ui.accessoryControl?.debug, instanceBlacklist: this.ui.accessoryControl?.instanceBlacklist || [], }, + plugins: { + hideUpdatesFor: this.ui.plugins?.hideUpdatesFor || [], + }, linux: { shutdown: this.ui.linux?.shutdown, restart: this.ui.linux?.restart, diff --git a/src/modules/config-editor/config-editor.controller.ts b/src/modules/config-editor/config-editor.controller.ts index 2c29ff8dd..b9ef4af75 100644 --- a/src/modules/config-editor/config-editor.controller.ts +++ b/src/modules/config-editor/config-editor.controller.ts @@ -102,6 +102,15 @@ export class ConfigEditorController { return this.configEditorService.setAccessoryControlInstanceBlacklist(body) } + @UseGuards(AdminGuard) + @Put('/ui/plugins/hide-updates-for') + @ApiOperation({ summary: 'Update the plugins hide updates for.' }) + @ApiBody({ description: 'Array of plugin names to hide updates for in the UI.', type: 'json', isArray: true }) + @Put() + setPluginsHideUpdatesFor(@Body() { body }) { + return this.configEditorService.setPluginsHideUpdatesFor(body) + } + @UseGuards(AdminGuard) @ApiOperation({ summary: 'List the available Homebridge `config.json` backups.' }) @Get('/backups') diff --git a/src/modules/config-editor/config-editor.service.ts b/src/modules/config-editor/config-editor.service.ts index 06b445eac..c4de83543 100644 --- a/src/modules/config-editor/config-editor.service.ts +++ b/src/modules/config-editor/config-editor.service.ts @@ -358,6 +358,27 @@ export class ConfigEditorService { await this.updateConfigFile(config) } + /** + * Set the plugin hide update list (this request is not partial) + */ + public async setPluginsHideUpdatesFor(value: string[]) { + // 1. Get the current config for the Homebridge UI + const config = await this.getConfigFile() + const pluginConfig = config.platforms.find(x => x.platform === 'config') + + // 2. Ensure the plugins object exists and set the hideUpdatesFor property + if (!pluginConfig.plugins) { + pluginConfig.plugins = {} + } + pluginConfig.plugins.hideUpdatesFor = (value || []) + .filter(x => typeof x === 'string' && x.trim() !== '' && /^(?:@[\w-]+(?:\.[\w-]+)*\/)?homebridge-[\w-]+$/i.test(x.trim())) + .map(x => x.trim().toLowerCase()) + + // 3. Clean and save the UI config block + config.platforms[config.platforms.findIndex(x => x.platform === 'config')] = this.cleanUpUiConfig(pluginConfig) + await this.updateConfigFile(config) + } + /** * Mark a plugin as disabled */ diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts index 24649bd89..247349580 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts @@ -145,7 +145,7 @@ export class ManagePluginComponent implements OnInit, OnDestroy { next: () => { this.$activeModal.close() this.$toastr.success(`${this.pastTenseVerb} ${this.pluginName}`, this.toastSuccess) - window.location.href = `/plugins?installed=${this.pluginName}` + window.location.href = `/plugins?action=just-installed&plugin=${this.pluginName}` }, error: (error) => { this.actionFailed = true diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html index dcead1d7d..86fa7e32d 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html @@ -76,6 +76,27 @@
    {{ 'plugins.manage.select_version' | translate }}
    } + + @if (plugin.installedVersion && !['homebridge', 'homebridge-config-ui-x'].includes(plugin.name)) { +
      +
    • +
      + {{ 'plugins.manage.hide_updates' | translate }}
      + {{ 'plugins.manage.hide_updates_desc' | translate }} +
      +
      + + +
      +
    • +
    + }
    }
    diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts index f6026f840..f39334215 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts @@ -1,11 +1,15 @@ import { Component, inject, Input, OnInit } from '@angular/core' -import { FormsModule } from '@angular/forms' +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms' +import { Router } from '@angular/router' import { NgbActiveModal, NgbAlert } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' +import { firstValueFrom } from 'rxjs' +import { debounceTime } from 'rxjs/operators' import { rcompare } from 'semver' import { ApiService } from '@/app/core/api.service' +import { SettingsService } from '@/app/core/settings.service' interface VersionData { version: string @@ -22,16 +26,21 @@ interface VersionData { FormsModule, TranslatePipe, NgbAlert, + ReactiveFormsModule, ], }) export class ManageVersionComponent implements OnInit { $activeModal = inject(NgbActiveModal) private $api = inject(ApiService) + private $router = inject(Router) + private $settings = inject(SettingsService) private $toastr = inject(ToastrService) private $translate = inject(TranslateService) @Input() plugin: any + public isUpdateHidden: boolean = false + public hideUpdatesFormControl = new FormControl(false) public loading = true public versions: Array = [] public versionsWithTags: Array<{ version: string, tag: string }> = [] @@ -42,6 +51,12 @@ export class ManageVersionComponent implements OnInit { ngOnInit(): void { this.versionSelect = this.plugin.installedVersion || this.plugin.latestVersion this.lookupVersions() + + this.isUpdateHidden = this.$settings.env.plugins.hideUpdatesFor && this.$settings.env.plugins.hideUpdatesFor.includes(this.plugin.name) + this.hideUpdatesFormControl.patchValue(this.isUpdateHidden) + this.hideUpdatesFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.toggleHideUpdates(value)) } lookupVersions() { @@ -98,4 +113,26 @@ export class ManageVersionComponent implements OnInit { action: this.plugin.installedVersion ? 'alternate' : 'install', }) } + + async toggleHideUpdates(value: boolean) { + let currentSetting = this.$settings.env.plugins?.hideUpdatesFor || [] + if (value) { + if (!currentSetting.includes(this.plugin.name)) { + currentSetting = [...currentSetting, this.plugin.name].sort((a, b) => a.localeCompare(b)) + } + } else { + currentSetting = currentSetting.filter(x => x !== this.plugin.name) + } + try { + await firstValueFrom(this.$api.put('/config-editor/ui/plugins/hide-updates-for', { + body: currentSetting, + })) + this.$settings.setEnvItem('plugins.hideUpdatesFor', currentSetting) + window.location.href = `/plugins?action=open-manage-version&plugin=${this.plugin.name}` + } catch (error) { + this.hideUpdatesFormControl.patchValue(this.isUpdateHidden, { emitEvent: false }) + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } } diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts index b653b654e..d51fb4d67 100644 --- a/ui/src/app/core/settings.service.ts +++ b/ui/src/app/core/settings.service.ts @@ -52,6 +52,9 @@ interface EnvInterface { debug?: boolean instanceBlacklist?: string[] } + plugins?: { + hideUpdatesFor?: string[] + } linux?: { shutdown?: string restart?: string diff --git a/ui/src/app/modules/plugins/plugins.component.ts b/ui/src/app/modules/plugins/plugins.component.ts index cd6a1c504..2e6992329 100644 --- a/ui/src/app/modules/plugins/plugins.component.ts +++ b/ui/src/app/modules/plugins/plugins.component.ts @@ -60,24 +60,41 @@ export class PluginsComponent implements OnInit, OnDestroy { this.io.socket.emit('monitor-child-bridge-status') // Load list of installed plugins - this.loadInstalledPlugins().then(() => { - // Get query parameters - const justInstalled = this.$router.parseUrl(this.$router.url).queryParams.installed - if (justInstalled) { - const plugin = this.installedPlugins.find(x => x.name === justInstalled) - if (plugin) { - if (plugin.isConfigured) { - this.$modal.open(RestartHomebridgeComponent, { - size: 'lg', - backdrop: 'static', - }) - } else { - this.$plugin.settings(plugin) + await this.loadInstalledPlugins() + + // Get any query parameters + const { action: queryAction, plugin: queryPlugin } = this.$router.parseUrl(this.$router.url).queryParams + if (queryAction) { + const plugin = this.installedPlugins.find(x => x.name === queryPlugin) + switch (queryAction) { + case 'just-installed': { + if (plugin) { + if (plugin.isConfigured) { + this.$modal.open(RestartHomebridgeComponent, { + size: 'lg', + backdrop: 'static', + }) + } else { + this.$plugin.settings(plugin) + } + } + break + } + case 'open-manage-version': { + if (plugin) { + this.$plugin.installAlternateVersion(plugin) } + break } - this.$router.navigate(['/plugins']) } - }) + + // Clear the query parameters so that we don't keep showing the same action + this.$router.navigate([], { + queryParams: {}, + replaceUrl: true, + queryParamsHandling: '', + }) + } }) this.io.socket.on('child-bridge-status-update', (data) => { @@ -177,6 +194,10 @@ export class PluginsComponent implements OnInit, OnDestroy { const pluginChildBridges = this.getPluginChildBridges(plugin) plugin.hasChildBridgesUnpaired = pluginChildBridges.some(x => !x.paired) + + if (this.$settings.env.plugins?.hideUpdatesFor?.includes(plugin.name)) { + plugin.updateAvailable = false + } } catch (err) { // May not be technically correct, but if we can't load the config, assume it is configured plugin.isConfigured = true diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts index 114d8799d..482855d28 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts @@ -133,7 +133,8 @@ export class UpdateInfoWidgetComponent implements OnInit { async getOutOfDatePlugins() { try { const outOfDatePlugins = await firstValueFrom(this.io.request('get-out-of-date-plugins')) - this.homebridgePluginStatus = outOfDatePlugins.filter((x: any) => x.name !== 'homebridge-config-ui-x') + this.homebridgePluginStatus = outOfDatePlugins + .filter((x: any) => x.name !== 'homebridge-config-ui-x' && !this.$settings.env.plugins?.hideUpdatesFor?.includes(x.name)) this.homebridgePluginStatusDone = true } catch (error) { console.error(error) diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index bf3106017..eb897103a 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирай", "plugins.manage.installed": "Инсталиран", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index f97086ebc..d3110d6c1 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informació del plugin", "plugins.manage.install": "Instal·lar", "plugins.manage.installed": "Instal·lat", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index fca7ceeb7..27c5df681 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Povolit", "plugins.manage.github_support": "Můžete vyjádřit svou podporu tomuto pluginu tím, že mu na GitHubu dáte {{ iconStar }} (nebo této verzi {{ iconThumbsUp }})!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informace o pluginu", "plugins.manage.install": "Instalovat", "plugins.manage.installed": "Instalováno", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index a69b125b7..bd82e370e 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktivieren", "plugins.manage.github_support": "Sie können Ihre Unterstützung zeigen, indem Sie dieses Plugin mit einem {{ iconStar }} (oder dem Release ein {{ iconThumbsUp }}) auf GitHub geben!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installieren", "plugins.manage.installed": "Installiert", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 014fb2e92..b26920f47 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Install", "plugins.manage.installed": "Installed", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 6d0d07281..004a5f524 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Habilitar", "plugins.manage.github_support": "Puedes mostrar tu apoyo dando a este plugin una {{ iconStar }} (o a la versión una {{ iconThumbsUp }}) en GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Información del Plugin", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 5f178b6fe..10d41edb9 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ota käyttöön", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Tietoja laajennuksesta", "plugins.manage.install": "Asenna", "plugins.manage.installed": "Asennettu", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index b981f6744..3723b61b3 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activer", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informations sur le plugin", "plugins.manage.install": "Installer", "plugins.manage.installed": "Installé", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 7bee3bd5f..4b2d02511 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "מאופשר", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "התקן", "plugins.manage.installed": "הותקן", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index bfb6715ac..fa031c6c9 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Telepítés", "plugins.manage.installed": "Telepítve", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index dee4eab3b..3ce0c6f67 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktifkan", "plugins.manage.github_support": "Anda dapat menunjukkan dukungan Anda dengan memberikan plugin ini {{ iconStar }} (atau rilis A {{ iconThumbsUp }}) di github!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informasi Plugin", "plugins.manage.install": "Pasang", "plugins.manage.installed": "Terpasang", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index b58fe77a3..13ee6a323 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Attiva", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installa", "plugins.manage.installed": "Installato", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index ca65958db..b2382e369 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "有効化", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "プラグイン情報", "plugins.manage.install": "インストール", "plugins.manage.installed": "インストール済", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index c911bc7ac..1b4a0ce7e 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "활성화", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "플러그인 정보", "plugins.manage.install": "설치", "plugins.manage.installed": "설치됨", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 41f5f69cc..5aa111add 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирај", "plugins.manage.installed": "Инсталирано", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index a6dc1ed46..f44356cc6 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activeren", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installeer", "plugins.manage.installed": "Geïnstalleerd", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 59ce8f862..16c8eb96f 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installere", "plugins.manage.installed": "Installert", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index ab03283ac..82e1f8205 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Włącz", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informacje wtyczki", "plugins.manage.install": "Instaluj", "plugins.manage.installed": "Zainstalowane", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 3a996a273..624209e65 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 76cb2c820..41f94dbfe 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 5e12a1e7a..b8931aa22 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Включить", "plugins.manage.github_support": "Вы можете поддержать проект, поставив {{ iconStar }} плагину (или {{ iconThumbsUp }} релизу) на GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Информация о плагине", "plugins.manage.install": "Установить", "plugins.manage.installed": "Установлен", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index af2c2300b..b00879247 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Omogoči", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Namestite", "plugins.manage.installed": "Nameščeno", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 9e7e239bc..054ddf811 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktivera", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin-information", "plugins.manage.install": "Installera", "plugins.manage.installed": "Installerad", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index d14c64143..fd07d9dbf 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "เปิดการใช้งาน", "plugins.manage.github_support": "คุณสามารถแสดงการสนับสนุนของคุณโดยมอบ {{ iconStar }} ให้กับปลั๊กอินนี้ (หรือเผยแพร่ {{ iconThumbsUp }}) บน GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "ข้อมูลปลั๊กอิน", "plugins.manage.install": "ติดตั้ง", "plugins.manage.installed": "ติดตั้งแล้ว", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index cd59eeace..8cecf648d 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Etkinleştir", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Yükle", "plugins.manage.installed": "Yüklü", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 2c42b84e7..d9cc81777 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Увімкнути", "plugins.manage.github_support": "Ви можете продемонструвати свою підтримку, поставивши цьому плагіну {{ iconStar }} (або випуску {{ iconThumbsUp }}) на GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Інформація про плагін", "plugins.manage.install": "Встановлення", "plugins.manage.installed": "Плагін встановлено", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 15318d538..a8b39b091 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安装", "plugins.manage.installed": "已安装", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index 001313e5b..86b53f9ac 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "開啟", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安裝", "plugins.manage.installed": "已安裝", From 6a451fd3844ebf53682af01f69f90cfd32def97d Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:35:23 +0100 Subject: [PATCH 22/40] improve plugin search and result ordering Co-Authored-By: Just Jam <4944618+justjam2013@users.noreply.github.com> --- CHANGELOG.md | 1 + src/modules/plugins/plugins.service.ts | 165 +++++++++++++++---------- 2 files changed, 99 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80308d2d6..2c1c7ae09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - refactor settings page with immediate saving - add support for `uiSchema` within plugin configurations - add option to hide update notifications for specific plugins +- improve plugin search and result ordering (@justjam2013) ### Homebridge Dependencies diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index dfbd2157c..3058d5e44 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -248,6 +248,47 @@ export class PluginsService { } } + private extractTerms(query: string, separator: RegExp): string[] { + return query + .toLowerCase() + .split(separator) + .map(term => term.trim()) + .filter(term => term && term !== 'homebridge' && term !== 'plugin') + } + + private getPluginKeywords(plugin: any): string[] { + return Array.isArray(plugin.keywords) + ? plugin.keywords.map(k => k.toLowerCase()) + : [] + } + + private matchesPlugin(plugin: HomebridgePlugin, searchTerms: string[]): 'exactName' | 'exactKeyword' | 'partial' | null { + const pluginName = plugin.name.toLowerCase() + const pluginKeywords = this.getPluginKeywords(plugin) + const pluginDescription = (plugin.description || '').toLowerCase() + + // Separator: '-' character, only get the terms from the plugin name, ignoring any scope + const nameTerms = this.extractTerms(pluginName.substring(pluginName.lastIndexOf('/') + 1), /-/) + + // The search terms contain all the parts of the name + if (nameTerms.every(term => searchTerms.includes(term))) { + return 'exactName' + } + // The keywords or name contain all the search terms + if (searchTerms.every(term => pluginKeywords.includes(term)) + || searchTerms.every(term => nameTerms.includes(term))) { + return 'exactKeyword' + } + if ( + searchTerms.some(term => pluginName.includes(term)) + || searchTerms.some(term => pluginKeywords.some(k => k.includes(term))) + || searchTerms.some(term => pluginDescription.includes(term)) + ) { + return 'partial' + } + return null + } + /** * Search the npm registry for homebridge plugins * @param query @@ -257,21 +298,26 @@ export class PluginsService { await this.getInstalledPlugins() } - query = query.trim().toLowerCase() + const searchTerms = this.extractTerms(query, /\s+/) // Separator: whitespace (spaces, tabs and new lines) characters + const normalizedQuery = searchTerms.length > 0 ? searchTerms.join(' ') : 'homebridge' - if ((query.startsWith('homebridge-') || this.isScopedPlugin(query)) && !this.hiddenPlugins.includes(query)) { - // Change the query to the scoped version if it exists, and the 'old' version is not installed - if (!this.installedPlugins.find(x => x.name === query) && Object.keys(this.newScopePlugins).includes(query)) { - query = `@homebridge-plugins/${query}` + if ( + (normalizedQuery.startsWith('homebridge-') || this.isScopedPlugin(normalizedQuery)) + && !this.hiddenPlugins.includes(normalizedQuery) + ) { + if ( + !this.installedPlugins.find(x => x.name === normalizedQuery) + && Object.keys(this.newScopePlugins).includes(normalizedQuery) + ) { + return await this.searchNpmRegistrySingle(`@homebridge-plugins/${normalizedQuery}`) } - return await this.searchNpmRegistrySingle(query) + return await this.searchNpmRegistrySingle(normalizedQuery) } // There seems to be a new 64-character limit on the text query (which allows for 15 characters of a query) // Get the top 99 plugins now, later we filter down to the top 30 - const q = `${(!query || !query.length) ? '' : `${query.substring(0, 15)}+`}keywords:homebridge-plugin+not:deprecated&size=99` + const q = `${normalizedQuery.substring(0, 15)}+keywords:homebridge-plugin+not:deprecated&size=99` let searchResults: INpmSearchResults - try { searchResults = (await firstValueFrom(this.httpService.get(`https://registry.npmjs.org/-/v1/search?text=${q}`))).data } catch (e) { @@ -279,79 +325,64 @@ export class PluginsService { throw new InternalServerErrorException(`Failed to search the npm registry as ${e.message}, see logs.`) } - const result: HomebridgePlugin[] = searchResults.objects - .filter(x => x.package.name.indexOf('homebridge-') === 0 || this.isScopedPlugin(x.package.name)) + const plugins: HomebridgePlugin[] = searchResults.objects + .filter(x => x.package.name.startsWith('homebridge-') || this.isScopedPlugin(x.package.name)) .filter(x => !this.hiddenPlugins.includes(x.package.name)) .map((pkg) => { - let plugin: HomebridgePlugin = { - name: pkg.package.name, - displayName: this.pluginNames[pkg.package.name], - private: false, - } + const isInstalled = this.installedPlugins.find(x => x.name === pkg.package.name) // See if the plugin is already installed - const isInstalled = this.installedPlugins.find(x => x.name === plugin.name) if (isInstalled) { - plugin = isInstalled - plugin.lastUpdated = pkg.package.date - plugin.keywords = pkg.package.keywords - return plugin + return { + ...isInstalled, + lastUpdated: pkg.package.date, + keywords: pkg.package.keywords || [], + } } // It's not installed; finish building the response - plugin.publicPackage = true - plugin.installedVersion = null - plugin.latestVersion = pkg.package.version - plugin.lastUpdated = pkg.package.date - plugin.description = (pkg.package.description) - ? pkg.package.description.replace(/\(?(?:https?|ftp):\/\/[\n\S]+/g, '').trim() - : pkg.package.name - plugin.keywords = pkg.package.keywords - plugin.links = pkg.package.links - plugin.author = this.pluginAuthors[pkg.package.name] || ((pkg.package.publisher) ? pkg.package.publisher.username : null) - plugin.verifiedPlugin = this.verifiedPlugins.includes(pkg.package.name) - plugin.verifiedPlusPlugin = this.verifiedPlusPlugins.includes(pkg.package.name) - plugin.icon = this.pluginIcons[pkg.package.name] - ? `${this.pluginListUrl}${this.pluginIcons[pkg.package.name]}` - : null - plugin.isHbScoped = pkg.package.name.startsWith('@homebridge-plugins/') - plugin.newHbScope = this.newScopePlugins[pkg.package.name] - plugin.isHbMaintained = this.maintainedPlugins.includes(pkg.package.name) - return plugin + return { + name: pkg.package.name, + displayName: this.pluginNames[pkg.package.name], + private: false, + publicPackage: true, + installedVersion: null, + latestVersion: pkg.package.version, + lastUpdated: pkg.package.date, + description: (pkg.package.description || pkg.package.name).replace(/\(?(?:https?|ftp):\/\/[\n\S]+/g, '').trim(), + keywords: pkg.package.keywords || [], + links: pkg.package.links, + author: this.pluginAuthors[pkg.package.name] || (pkg.package.publisher ? pkg.package.publisher.username : null), + verifiedPlugin: this.verifiedPlugins.includes(pkg.package.name), + verifiedPlusPlugin: this.verifiedPlusPlugins.includes(pkg.package.name), + icon: this.pluginIcons[pkg.package.name] ? `${this.pluginListUrl}${this.pluginIcons[pkg.package.name]}` : null, + isHbScoped: pkg.package.name.startsWith('@homebridge-plugins/'), + newHbScope: this.newScopePlugins[pkg.package.name], + isHbMaintained: this.maintainedPlugins.includes(pkg.package.name), + } }) - const searchTerm: string = query - .replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, '') // remove punctuation - - const searchTerms: string[] = searchTerm - .split(/\s+/) // split into words - .filter(term => term.length > 0) // remove empty strings - - // Separate lists for exact matches and partial matches - const exactMatchPlugins: HomebridgePlugin[] = [] - const partialMatchPlugins: HomebridgePlugin[] = [] + const matchGroups = { + exactName: [] as HomebridgePlugin[], + exactKeyword: [] as HomebridgePlugin[], + partial: [] as HomebridgePlugin[], + } - // Filter matching plugins - result.forEach((plugin) => { - const pluginKeywords = plugin.keywords.map(keyword => keyword.toLowerCase()) - const isExactMatch = pluginKeywords.includes(searchTerm) - if (isExactMatch) { - exactMatchPlugins.push(plugin) - return + for (const plugin of plugins) { + const matchType = this.matchesPlugin(plugin, searchTerms) + if (matchType) { + matchGroups[matchType].push(plugin) } + } - const pluginName = plugin.name.toLowerCase() - const pluginDescription = plugin.description.toLowerCase() - const isPartialMatch = searchTerms.some(term => pluginName.includes(term)) - || searchTerms.some(term => pluginKeywords.some(keyword => keyword.includes(term))) - || searchTerms.some(term => pluginDescription.includes(term)) - - if (isPartialMatch) { - partialMatchPlugins.push(plugin) - } - }) + const orderPlugins = (arr: HomebridgePlugin[]) => + orderBy(arr, ['isHbScoped', 'verifiedPlusPlugin', 'verifiedPlugin', 'lastUpdated'], ['desc', 'desc', 'desc']) - return orderBy([...exactMatchPlugins, ...partialMatchPlugins], ['verifiedPlusPlugin', 'verifiedPlugin'], ['desc', 'desc']) + return [ + ...orderPlugins(matchGroups.exactName), + ...orderPlugins(matchGroups.exactKeyword), + ...orderPlugins(matchGroups.partial), + ] .slice(0, 30) .map(plugin => this.fixDisplayName(plugin)) } From 318ae5e3d658216e7a30f95009dbdc5559ec2bbf Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Thu, 19 Jun 2025 16:05:20 +0100 Subject: [PATCH 23/40] Remove Redundant GSH Components Co-Authored-By: Northern Man <19808920+NorthernMan54@users.noreply.github.com> --- CHANGELOG.md | 4 + scripts/lang-sync.ts | 13 ++ .../custom-plugins/custom-plugins.module.ts | 2 - .../custom-plugins/custom-plugins.service.ts | 5 +- ...homebridge-google-smarthome.component.html | 74 -------- .../homebridge-google-smarthome.component.ts | 171 ------------------ ui/src/i18n/bg.json | 2 - ui/src/i18n/ca.json | 2 - ui/src/i18n/cs.json | 2 - ui/src/i18n/de.json | 2 - ui/src/i18n/en.json | 2 - ui/src/i18n/es.json | 2 - ui/src/i18n/fi.json | 2 - ui/src/i18n/fr.json | 2 - ui/src/i18n/he.json | 2 - ui/src/i18n/hu.json | 2 - ui/src/i18n/id.json | 2 - ui/src/i18n/it.json | 2 - ui/src/i18n/ja.json | 2 - ui/src/i18n/ko.json | 2 - ui/src/i18n/mk.json | 2 - ui/src/i18n/nl.json | 2 - ui/src/i18n/no.json | 2 - ui/src/i18n/pl.json | 2 - ui/src/i18n/pt-BR.json | 2 - ui/src/i18n/pt.json | 2 - ui/src/i18n/ru.json | 2 - ui/src/i18n/sl.json | 2 - ui/src/i18n/sv.json | 2 - ui/src/i18n/th.json | 2 - ui/src/i18n/tr.json | 2 - ui/src/i18n/uk.json | 2 - ui/src/i18n/zh-CN.json | 2 - ui/src/i18n/zh-TW.json | 2 - 34 files changed, 18 insertions(+), 307 deletions(-) delete mode 100644 ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html delete mode 100644 ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c1c7ae09..a1e544c4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,10 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - add option to hide update notifications for specific plugins - improve plugin search and result ordering (@justjam2013) +### Other Changes + +- Removed redundant Google Smart Home components (@NorthernMan54) + ### Homebridge Dependencies - `@homebridge/hap-client` @ `v2.2.0` diff --git a/scripts/lang-sync.ts b/scripts/lang-sync.ts index 280410664..e622f160d 100644 --- a/scripts/lang-sync.ts +++ b/scripts/lang-sync.ts @@ -12,6 +12,15 @@ import { readdir, readFile, readJson, stat, writeJson } from 'fs-extra' // Path to the project directory const projectDir = resolve(dirname(__dirname), 'ui/src') +const ignoreKeys = [ + 'plugins.settings.custom.homebridge-gsh.label_account_linked', + 'plugins.settings.custom.homebridge-gsh.label_link_account', + 'plugins.settings.custom.homebridge-gsh.message_about', + 'plugins.settings.custom.homebridge-gsh.message_account_link_required', + 'plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required', + +] + async function getAllFiles(dirPath: string, arrayOfFiles: string[] = []): Promise { const files = await readdir(dirPath) @@ -51,6 +60,10 @@ async function main() { // Check each key const unusedKeys = [] for (const key of keys) { + if (ignoreKeys.includes(key)) { + continue // Skip ignored keys + } + const isUsed = await Promise.all(allFiles.map(file => isKeyUsedInFile(key, file))) .then(results => results.some(result => result)) if (!isUsed) { diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts index a67c04ea1..85b21b5ad 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts @@ -9,7 +9,6 @@ import { NgxMdModule } from 'ngx-md' import { CustomPluginsComponent } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.component' import { CustomPluginsService } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.service' import { HomebridgeDeconzComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-deconz/homebridge-deconz.component' -import { HomebridgeGoogleSmarthomeComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component' import { HomebridgeHueComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-hue/homebridge-hue.component' @NgModule({ @@ -23,7 +22,6 @@ import { HomebridgeHueComponent } from '@/app/core/manage-plugins/custom-plugins NgxMdModule, CustomPluginsComponent, HomebridgeDeconzComponent, - HomebridgeGoogleSmarthomeComponent, HomebridgeHueComponent, ], providers: [ diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts index 85df9739f..0a14bbdee 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts @@ -4,7 +4,6 @@ import { firstValueFrom } from 'rxjs' import { ApiService } from '@/app/core/api.service' import { CustomPluginsComponent } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.component' -import { HomebridgeGoogleSmarthomeComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component' @Injectable({ providedIn: 'root', @@ -13,9 +12,7 @@ export class CustomPluginsService { private $api = inject(ApiService) private $modal = inject(NgbModal) - public plugins = { - 'homebridge-gsh': HomebridgeGoogleSmarthomeComponent, - } + public plugins = {} constructor() {} diff --git a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html b/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html deleted file mode 100644 index cf8392066..000000000 --- a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html +++ /dev/null @@ -1,74 +0,0 @@ - diff --git a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts b/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts deleted file mode 100644 index 2fdb09330..000000000 --- a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { TitleCasePipe } from '@angular/common' -import { Component, inject, Input, OnDestroy, OnInit } from '@angular/core' -import { JwtHelperService } from '@auth0/angular-jwt' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { TranslatePipe, TranslateService } from '@ngx-translate/core' -import { NgxMdModule } from 'ngx-md' -import { ToastrService } from 'ngx-toastr' -import { firstValueFrom } from 'rxjs' - -/* global NodeJS */ -import { ApiService } from '@/app/core/api.service' -import { SchemaFormComponent } from '@/app/core/components/schema-form/schema-form.component' -import { PluginsMarkdownDirective } from '@/app/core/directives/plugins.markdown.directive' -import { SettingsService } from '@/app/core/settings.service' - -@Component({ - selector: 'app-homebridge-google-smarthome', - templateUrl: './homebridge-google-smarthome.component.html', - standalone: true, - imports: [ - NgxMdModule, - PluginsMarkdownDirective, - SchemaFormComponent, - TitleCasePipe, - TranslatePipe, - ], -}) -export class HomebridgeGoogleSmarthomeComponent implements OnInit, OnDestroy { - $activeModal = inject(NgbActiveModal) - private $api = inject(ApiService) - private $jwtHelper = inject(JwtHelperService) - $settings = inject(SettingsService) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - @Input() public plugin: any - @Input() public schema: any - @Input() pluginConfig: Record[] - - public justLinked = false - public gshConfig: Record - public linkType: string - public readonly linkInsecure = '' - - private linkDomain = 'https://homebridge-gsh.iot.oz.nu' - private linkUrl = `${this.linkDomain}/link-account` - private popup: Window - private originCheckInterval: NodeJS.Timeout - - constructor() { - // Listen for sign in events from the link account popup - window.addEventListener('message', this.windowMessageListener, false) - } - - ngOnInit() { - if (!this.pluginConfig.length) { - this.pluginConfig.push({ name: 'Google Smart Home', platform: this.schema.pluginAlias }) - } - - this.gshConfig = this.pluginConfig[0] - - this.parseToken() - } - - windowMessageListener = (e: MessageEvent) => { - if (e.origin !== this.linkDomain) { - console.error('Refusing to process message from', e.origin) - console.error(e) - } - - try { - const data = JSON.parse(e.data) - if (data.token) { - this.processToken(data.token) - } - } catch (error) { - console.error(error) - } - } - - linkAccount() { - const w = 450 - const h = 700 - const y = window.top.outerHeight / 2 + window.top.screenY - (h / 2) - const x = window.top.outerWidth / 2 + window.top.screenX - (w / 2) - this.popup = window.open( - this.linkUrl, - 'oznu-google-smart-home-auth', - 'toolbar=no, location=no, directories=no, status=no, menubar=no scrollbars=no, resizable=no, copyhistory=no, ' - + `width=${w}, height=${h}, top=${y}, left=${x}`, - ) - - // Simple message popup to provide the current hostname - this.originCheckInterval = setInterval(() => { - this.popup.postMessage('origin-check', this.linkDomain) - }, 2000) - } - - unlinkAccount() { - this.gshConfig = { - name: 'Google Smart Home', - platform: this.schema.pluginAlias, - } - - this.pluginConfig.splice(0, this.pluginConfig.length) - this.saveConfig() - } - - processToken(token: string) { - clearInterval(this.originCheckInterval) - if (this.popup) { - this.popup.close() - } - this.gshConfig.token = token - this.gshConfig.notice = 'Keep your token a secret!' - - if (!this.pluginConfig.length) { - this.pluginConfig.push(this.gshConfig) - } - - this.parseToken() - this.saveConfig() - } - - parseToken() { - if (this.gshConfig.token) { - try { - const decoded = this.$jwtHelper.decodeToken(this.gshConfig.token) - this.linkType = decoded.id.split('|')[0].split('-')[0] - } catch (error) { - console.error(error) - this.$toastr.error(this.$translate.instant('plugins.settings.custom.homebridge-gsh.message_invalid_token'), this.$translate.instant('toast.title_error')) - delete this.gshConfig.token - } - } - } - - async saveConfig() { - try { - await firstValueFrom(this.$api.post(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`, this.pluginConfig)) - this.justLinked = true - this.$toastr.success( - this.$translate.instant('plugins.settings.restart_required'), - this.$translate.instant('plugins.settings.plugin_config_saved'), - ) - } catch (error) { - console.error(error) - this.$toastr.error(this.$translate.instant('config.failed_to_save_config'), this.$translate.instant('toast.title_error')) - } - } - - async saveAndClose() { - this.gshConfig.platform = this.schema.pluginAlias - this.pluginConfig[0] = this.gshConfig - - await this.saveConfig() - this.$activeModal.close() - } - - close() { - this.$activeModal.close() - } - - ngOnDestroy() { - clearInterval(this.originCheckInterval) - window.removeEventListener('message', this.windowMessageListener) - if (this.popup) { - this.popup.close() - } - } -} diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index eb897103a..53c66c6ba 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Търсете добавки, които да инсталирате…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index d3110d6c1..c8d0d8e5a 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cercar plugins per instal·lar…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Compte vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular compte", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular compte", "plugins.settings.custom.homebridge-gsh.message_about": "El plugin Homebridge Google Smart Home et permet controlar les accessoris de Homebridge des d'un altaveu intel·ligent Google Home o des de l'aplicació mòbil Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Per activar aquesta funcionalitat has d'iniciar sessió amb el teu compte Google o GitHub; assegura't que fas servir el mateix compte quan estiguis afegint l'acció de Homebridge en l'aplicació mòbil Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge necessita reiniciar perquè els canvis tinguin efecte.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Obrir editor de configuració", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 27c5df681..41a169965 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Vyhledejte pluginy k instalaci…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Účet propojen", "plugins.settings.custom.homebridge-gsh.label_link_account": "Propojit účet", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Odpojit účet", "plugins.settings.custom.homebridge-gsh.message_about": "Plugin Homebridge Google Smart Home vám umožňuje ovládat příslušenství Homebridge z chytrého reproduktoru s aktivovanou službou Google Home nebo z mobilní aplikace Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Chcete-li tuto funkci povolit, musíte se přihlásit pomocí účtu Google nebo GitHub; Při přidávání akce Homebridge do mobilní aplikace Google Home se ujistěte, že používáte stejný účet.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Aby se změny projevily, Homebridge vyžaduje restartování.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Neplatný token propojení účtu v config.json", "plugins.settings.deconz.dump_no_exist": "Soubor dumpu Homebridge deCONZ ještě neexistuje.", "plugins.settings.hue.dump_no_exist": "Soubor dumpu Homebridge Hue ještě neexistuje.", "plugins.settings.label_open_config_editor": "Otevřít editor konfigurace", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index bd82e370e..d0f1dba8d 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Suche nach installierbaren Plugins …", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto verbunden", "plugins.settings.custom.homebridge-gsh.label_link_account": "Konto verbinden", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Kontoverbindung aufheben", "plugins.settings.custom.homebridge-gsh.message_about": "Das Homebridge Google Smart Home-Plugin erlaubt es dir, deine Homebridge-Geräte durch einen Google Home-fähigen smarten Lautsprecher oder durch die Google Home Mobile-App zu steuern.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Um diese Funktionalität zu aktivieren, musst du dich mit deinem Google- or GitHub-Konto anmelden. Stelle sicher, dass du dasselbe Konto verwendest, wenn du die Homebridge-Aktion in der Google Home Mobile-App hinzufügst.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge muss neugestartet werden, damit die Änderungen wirksam werden.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Ungültiger Account-Token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ Dump-Datei existiert noch nicht.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue Dump-Datei existiert noch nicht.", "plugins.settings.label_open_config_editor": "Konfigurations-Editor öffnen", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index b26920f47..8e9909271 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Search for plugins to install…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 004a5f524..7ff82ae8e 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Buscar plugins disponibles para instalar…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Cuenta vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular cuenta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular cuenta", "plugins.settings.custom.homebridge-gsh.message_about": "El plugin Homebridge Google Smart Home te permite controlar tus accesorios de Homebridge desde un altavoz inteligente Google Home o desde la aplicación móvil Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para activar esta funcionalidad debes iniciar sesión con tu cuenta Google o GitHub; asegúrate que usas la misma cuenta cuando estés añadiendo la acción de Homebridge en la aplicación móvil Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge necesita reiniciarse para que los cambios tengan efecto.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Token de vinculación de cuenta inválido en config.json", "plugins.settings.deconz.dump_no_exist": "El archivo de volcado de Homebridge deCONZ aún no existe.", "plugins.settings.hue.dump_no_exist": "El archivo de volcado de Homebridge Hue aún no existe.", "plugins.settings.label_open_config_editor": "Abrir Editor de Configuración", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 10d41edb9..70dfe8e1c 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Etsi aennettavia laajennuksia", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Tili Linkitetty", "plugins.settings.custom.homebridge-gsh.label_link_account": "Linkitä Tili", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Pura tilin linkitys", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home laajennus mahdollistaa Homebridge laitteidesi hallinnan Google Home älykaiuttimella tai sovelluksella.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Toiminnon käyttöönottamiseksi sinun on kirjauduttava Google tai GitHub tilillesi; varmista että käytät samaa tiliä kun lisäät Homebridge toiminnon Google Home sovellukseesi.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge täytyy uudelleenkäynnistää toimintojen käyttöönottamiseksi.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Virheellinen tilin linkitys config.json:ssa", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump tiedostoa ei vielä ole.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump tiedostoa ei vielä ole.", "plugins.settings.label_open_config_editor": "Avaa Asetusten muokkain", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 3723b61b3..e2261b129 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Rechercher des plugins à installer…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Compte associé", "plugins.settings.custom.homebridge-gsh.label_link_account": "Associer le compte", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Dissocier le compte", "plugins.settings.custom.homebridge-gsh.message_about": "Le plugin Homebridge Google Smart Home vous permet de contrôler vos accessoires Homebridge à partir d'un haut-parleur intelligent compatible avec Google Home ou de l'application mobile Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Pour activer cette fonctionnalité, vous devez vous connecter avec votre compte Google ou GitHub. Assurez-vous d'utiliser le même compte lors de l'ajout de l'action Homebridge dans l'application mobile Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge nécessite un redémarrage pour que les modifications prennent effet.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Ouvrir l'éditeur de Config", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 4b2d02511..57ddd112f 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "חפש תוספים להתקנה…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "חשבון קושר", "plugins.settings.custom.homebridge-gsh.label_link_account": "קשר חשבון", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "נתק קשר לחשבון", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "הומברידג' חייב להיות מאותחל על מנת שהשינויים יחולו", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "פתח עורך קונפיגורציה", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index fa031c6c9..6ea5f8f3c 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Pluginek keresése…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 3ce0c6f67..20fb551ee 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cari plugin untuk dipasang…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Akun Terhubung", "plugins.settings.custom.homebridge-gsh.label_link_account": "Hubungkan Akun", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Putuskan Hubungan Akun", "plugins.settings.custom.homebridge-gsh.message_about": "Plugin Homebridge Google Smart Home memungkinkan anda untuk mengontrol aksesoris Homebridge dari pengeras suara berkemampuan Google Home atau aplikasi seluler Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Untuk mengaktifkan fungsi ini, anda harus masuk dengan akun Google atau GitHub anda; pastikan anda menggunakan akun yang sama saat menambahkan tindakan Homebridge di aplikasi seluler Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge membutuhkan pengaktifan ulang agar perubahan dapat diterapkan.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Akun tidak valid menautkan token di config.json", "plugins.settings.deconz.dump_no_exist": "Berkas dump homebridge deCONZ belum ada.", "plugins.settings.hue.dump_no_exist": "Berkas dump Homebridge Hue belum ada.", "plugins.settings.label_open_config_editor": "Buka Editor Konfigurasi", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 13ee6a323..c16bd35a7 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cerca plugin da installare…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account collegato", "plugins.settings.custom.homebridge-gsh.label_link_account": "Collega account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Scollega account", "plugins.settings.custom.homebridge-gsh.message_about": "Il plugin Homebridge Google Smart Home permette di controllare gli accessori Homebridge da un altoparlante intelligente Google Home abilitato o dall'applicazione Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "L'attivazione di questa funzione richiede l'accesso con un account Google or GitHub; assicurarsi di usare lo stesso account quanto si aggiunge l'azione Homebridge nell'applicazione Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge deve essere riavviato affinché le modifiche abbiano effetto.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Apri l'editor della configurazione", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index b2382e369..3e6e4fbd5 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "インストールするプラグインを検索…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "アカウント連携済み", "plugins.settings.custom.homebridge-gsh.label_link_account": "アカウントと連携する", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "アカウントとの連携を解除する", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home プラグインを使用すると、Google Home対応小野スマートスピーカーやGoogle HomeモバイルアプリからHomebridgeアクセサリを制御することができます。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "この機能を有効にするには、GoogleまたはGitHubアカウントでログインする必要があります。Google HomeモバイルアプリにHomebridgeアクションを追加する際には、同じアカウントを使用してください。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "変更を反映するには、Homebridgeの再起動が必要です。", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "コンフィグエディタを開く", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 1b4a0ce7e..6b291a6d3 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "설치할 플러그인 검색…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "계정 연결됨", "plugins.settings.custom.homebridge-gsh.label_link_account": "계정 연결", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "계정 연결해제", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home 플러그인을 사용하면 Google Home 지원 스마트 스피커 또는 Google Home 모바일 앱에서 Homebridge 액세서리를 제어 할 수 있습니다.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "이 기능을 사용하려면 Google 또는 GitHub 계정으로 로그인해야합니다; Google Home 모바일 앱에 Homebridge 작업을 추가할 때 동일한 계정을 사용해야합니다.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "변경사항을 반영하려면 Homebridge를 다시 시작해야합니다.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "config.json에 잘못된 계정 연결 토큰이 있습니다.", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ 덤프 파일이 아직 존재하지 않습니다.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue 덤프 파일이 아직 존재하지 않습니다.", "plugins.settings.label_open_config_editor": "Config 에디터 열기", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 5aa111add..08ea584c1 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Барајте плагини достапни за инсталација…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Поврзана корисничка сметка", "plugins.settings.custom.homebridge-gsh.label_link_account": "Поврзи корисничка сметка", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Откажи поврзување на корисничка сметка", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home плагинот овозможува контрола на Homebridge уредите од Google Home smart speaker или од Google Home мобилната апликација.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "За да ја овозможите оваа функција мора да се најавите со Вашата Google или GitHub корисничка сметка; осигурајте се дека истата сметка ја користите при додавање на Homebridge акцијата во Google Home мобилната апликација.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge бара рестарт за промените да бидат рефлектирани.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Отвори уредник за конфигурација", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index f44356cc6..366f92727 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Zoeken naar plug-ins om te installeren…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Gekoppeld", "plugins.settings.custom.homebridge-gsh.label_link_account": "Koppel Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Verwijder account koppeling", "plugins.settings.custom.homebridge-gsh.message_about": "De Homebridge Google Smart Home plugin maakt het mogelijk om je Homebridge accessoires te besturen met een Google Home geschikte smart speaker of de Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Om deze functionaliteit te activeren moet je inloggen met je Google of GitHub account; zorg er voor dat je hetzelfde account gebruikt als je de Homebridge actie toevoegt in de Google Home mobiele app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge vereist een herstart om de wijzigingen te activeren.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Ongeldig account koppel token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump bestand bestaat nog niet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump bestand bestaat nog niet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 16c8eb96f..918c8bc6d 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Søk etter plugins å installere…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto tilknyttet", "plugins.settings.custom.homebridge-gsh.label_link_account": "Tilknytt konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Ta bort tilknytting til konto", "plugins.settings.custom.homebridge-gsh.message_about": "Med Homebridge Google Smart Home- plugin kan du kontrollere dine Homebridge-tilbehør fra en Google Home-aktivert smarthøytaler eller Google Home-mobilappen.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "For å aktivere denne funksjonen må du logge inn med din Google- eller GitHub-konto; pass på at du bruker samme konto når du legger til Homebridge-infoen i mobilappen Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge krever omstart for at endringene skal tre i kraft.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 82e1f8205..582276dfc 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Wyszukaj dostępne wtyczki…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto podłączone", "plugins.settings.custom.homebridge-gsh.label_link_account": "Podłącz konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Odłącz konto", "plugins.settings.custom.homebridge-gsh.message_about": "Wtyczka Homebridge Google Smart Home umożliwia kontrolę akcesoriów za pomocą głośników lub aplikacji mobilnej Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Aby włączyć tą funkcjonalność, musisz zalogować się swoim kontem Google lub GitHub - pamiętaj aby użyć tego samego konta dla Homebridge i aplikacji Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Serwer wymaga zrestartowania, aby zastosować zmiany.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Otwórz edytor konfiguracji", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 624209e65..e1f545649 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Procurar plugins para instalação…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Conta Vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular Conta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular Conta", "plugins.settings.custom.homebridge-gsh.message_about": "O plugin Homebridge Google Smart Home permite que faça o controle dos acessórios do Homebridge através de um coluna inteligente com Google Home ou com o app do Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para ativar esta funcionalidade é necessário iniciar sessão com a sua conta Google ou GitHub; utilize a mesma conta ao adicionar a ação do Homebridge no app do Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "É necessário reiniciar o Homebridge para que as mudanças surtam efeito.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Abrir editor de configurações", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 41f94dbfe..3761da5a8 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Procurar plugins para instalação…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Conta Vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular Conta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular Conta", "plugins.settings.custom.homebridge-gsh.message_about": "O plugin Homebridge Google Smart Home permite que faça o controlo dos acessórios do Homebridge através de um coluna inteligente com Google Home ou com a aplicação móvel do Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para ativar esta funcionalidade é necessário iniciar sessão com a sua conta Google ou GitHub; utilize a mesma conta ao adicionar a ação do Homebridge na aplicação móvel do Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "É necessário reiniciar o Homebridge para que as mudanças surtam efeito.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Abrir o Editor de Configuração", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index b8931aa22..cde319b07 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Поиск плагинов для установки…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Учётная запись связана", "plugins.settings.custom.homebridge-gsh.label_link_account": "Связать учётную запись", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Отвязать учётную запись", "plugins.settings.custom.homebridge-gsh.message_about": "Плагин Homebridge Google Smart Home позволяет управлять вашими аксессуарами Homebridge через колонки Google Home или мобильное приложение Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Чтобы включить эту функцию, необходимо войти с учётной записью Google или GitHub; убедитесь, что используете ту же учётную запись при добавлении действия Homebridge в мобильном приложении Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Необходимо перезапустить Homebridge для применения изменений.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Неверный токен привязки учётной записи в config.json", "plugins.settings.deconz.dump_no_exist": "Файл дампа Homebridge deCONZ ещё не существует.", "plugins.settings.hue.dump_no_exist": "Файл дампа Homebridge Hue ещё не существует.", "plugins.settings.label_open_config_editor": "Открыть редактор конфигурации", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index b00879247..22afb649e 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Poiščite vtičnike za namestitev …", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Račun povezan", "plugins.settings.custom.homebridge-gsh.label_link_account": "Povežite račun", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Prekini povezavo med računom", "plugins.settings.custom.homebridge-gsh.message_about": "Vtičnik Homebridge Google Smart Home omogoča upravljanje pripomočkov Homebridge iz pametnega zvočnika, ki podpira Google Home ali mobilne aplikacije Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Če želite omogočiti to funkcijo, se morate prijaviti s svojim računom za Google ali GitHub; pri dodajanju dejanja Homebridge v aplikacijo Google Home za mobilne naprave uporabite isti račun.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Za uveljavitev sprememb je treba znova zagnati Homebridge.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Odpri Config Urejevalec", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 054ddf811..413be376a 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Sök efter plugins att installera…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto länkat", "plugins.settings.custom.homebridge-gsh.label_link_account": "Länka konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Ta bort länkat konto", "plugins.settings.custom.homebridge-gsh.message_about": "Med pluginet Homebridge Google Smart Home kan du kontrollera dina Homebridge-tillbehör från en Google Home-aktiverad smarthögtalare eller Google Home-mobilappen.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "För att aktivera den här funktionen måste du logga in med ditt Google- eller GitHub-konto; se till att du använder samma konto när du lägger till Homebridge-åtgärden i mobilappen Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge kräver omstart för att ändringarna ska träda i kraft.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Öppna konfigurationsredigerare", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index fd07d9dbf..0601be07a 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "ค้นหาปลั๊กอินที่จะติดตั้ง…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "เชื่อมโยงบัญชีแล้ว", "plugins.settings.custom.homebridge-gsh.label_link_account": "เชื่อมโยงบัญชี", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "ยกเลิกการเชื่อมโยงบัญชี", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home ปลั๊กอินช่วยให้คุณควบคุมอุปกรณ์เสริม Homebridge จากลำโพงอัจฉริยะที่เปิดใช้งาน Google Home หรือแอป Google Home บนอุปกรณ์เคลื่อนที่", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "ในการเปิดใช้งานฟังก์ชันนี้คุณต้องลงชื่อเข้าใช้ด้วยบัญชี Google หรือ GitHub ของคุณ; ตรวจสอบให้แน่ใจว่าคุณใช้บัญชีเดียวกันเมื่อเพิ่มการดำเนินการ Homebridge ในแอป Google Home บนอุปกรณ์เคลื่อนที่", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge ต้องรีสตาร์ทเพื่อให้การเปลี่ยนแปลงมีผล", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "โทเค็นการเชื่อมโยงบัญชีไม่ถูกต้องใน config.json", "plugins.settings.deconz.dump_no_exist": "ไฟล์ดัมพ์ Homebridge deCONZ ยังไม่มีอยู่", "plugins.settings.hue.dump_no_exist": "ไฟล์ดัมพ์ Homebridge Hue ยังไม่มีอยู่", "plugins.settings.label_open_config_editor": "เปิด Config Editor", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 8cecf648d..d18230f13 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Yüklemek için eklentiler arayın…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Hesap Bağlandı", "plugins.settings.custom.homebridge-gsh.label_link_account": "Hesabı Bağla", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Hesabın Bağlantısını Kaldır", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home eklentisi Homebridge aksesuarlarınızı Google Home kullanan akıllı hoparlörlerinizden veya Google Home mobil uygulamasından kontrol etmenize olanak sağlar.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Bu özelliği etkinleştirmek için Google veya Github hesabınız ile giriş yapmanız gerekli; Google Home mobil uygulamasında Homebridge'i eklerken aynı hesabı kullandığınızdan emin olun.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Değişikliklerin yürürlüğe girmesi için Homebridge yeniden başlatılmaya ihtiyaç duyar.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Yapılandırma Düzenleyiciyi Aç", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index d9cc81777..1b5b3efc0 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Пошук плагінів для встановлення…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Аккаунт прив'язаний", "plugins.settings.custom.homebridge-gsh.label_link_account": "Прив'язати аккаунт", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Відв'язати аккаунт", "plugins.settings.custom.homebridge-gsh.message_about": "Плагін Homebridge Google Smart Home дозволяє курувати аксесуарами Homebridge за допомогою розумної колонки з підтримкою Google Home або мобільного додатка Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Щоб увімкнути цю функцію, Ви повинні увійти в свій аккаунт Google або GitHub; переконайтеся, що Ви використовуєте той же аккаунт при додаванні Homebridge action в мобильному додатку Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Потрібен перезапуск Homebridge, щоб зміни почали діяти.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Недійсний маркер зв’язування облікового запису в config.json", "plugins.settings.deconz.dump_no_exist": "Файл дампа Homebridge deCONZ ще не існує.", "plugins.settings.hue.dump_no_exist": "Файл дампа Homebridge Hue ще не існує.", "plugins.settings.label_open_config_editor": "Відкрийте редактор конфігурацій", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index a8b39b091..1965544cd 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "搜索插件…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "已绑定", "plugins.settings.custom.homebridge-gsh.label_link_account": "绑定账号", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "解绑账号", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge 谷歌智能家庭 插件将允许您通过支持谷歌家庭的智能音箱或者手机上的谷歌家庭软件上操作 Homebridge。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "若要使用该功能您需要使用您的谷歌账号或者 GitHub 账号登陆; 请确保您在设备间登陆的为同一账号。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge 需要重启以生效", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "打开配置编辑器", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index 86b53f9ac..d93c9a0bf 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "搜尋 Plugin 並且安裝…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "帳號已連結", "plugins.settings.custom.homebridge-gsh.label_link_account": "連結帳號", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "解除帳號連結", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home Plugin 可供透過 Google Home 智能音箱或 Google Home app 控制 Homebridge 配件。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "欲啟用此功能,必須先登入 Google 或 Github 帳號;確定於 Google Home app 中新增 Homebridge 時使用了相同的帳號。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge 需要重新啟動以期變更進行套用。", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "開啟 Config 編輯器", From 1b2d2532e9b71a91afef6a175db55112e7df7ba6 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:41:11 +0100 Subject: [PATCH 24/40] show lock management service info on lock mechanism info modal --- CHANGELOG.md | 1 + .../accessory-info.component.html | 24 +++++++++++++++++++ .../accessory-info.component.ts | 8 +++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1e544c4a..932529312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - improve wallpaper selection with new modal to upload a file - refactor HBv2 and UIv5 readiness modals - move backup settings from ui advanced settings to backup/restore modal +- show lock management service info on lock mechanism info modal ### Other Changes diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html index 22fb38203..d9eafa318 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html @@ -75,6 +75,30 @@
    {{ 'accessories.service_info' | translate }}
    } + @for (extraService of extraServices; track extraService) { +
      +
    • +
      {{ 'accessories.service_info' | translate }}
      +
    • +
    • + {{ 'accessories.service' | translate }} + {{ extraService.humanType }} +
    • +
    • + {{ 'accessories.name' | translate }} + {{ extraService.serviceName }} +
    • + @for (characteristic of extraService.serviceCharacteristics; track characteristic) { +
    • + {{ characteristic.description }} + + @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } +
    • + } +
    + }
    • {{ 'accessories.accessory_info' | translate }}
      diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts index ee7de7867..f7263a2d3 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts @@ -23,7 +23,9 @@ export class AccessoryInfoComponent implements OnInit { @Input() public service: ServiceTypeX @Input() private accessoryCache: any[] @Input() private pairingCache: any[] + public accessoryInformation: Array + public extraServices: ServiceTypeX[] = [] public matchedCachedAccessory: any = null constructor() {} @@ -31,6 +33,12 @@ export class AccessoryInfoComponent implements OnInit { ngOnInit() { this.accessoryInformation = Object.entries(this.service.accessoryInformation).map(([key, value]) => ({ key, value })) this.matchedCachedAccessory = this.matchToCachedAccessory() + + if (this.service.type === 'LockMechanism') { + Object.values(this.service.linkedServices) + .filter(service => service.type === 'LockManagement') + .forEach(service => this.extraServices.push(service)) + } } matchToCachedAccessory() { From fe8f16486ae9b4a296b8fb0702a6775c31cdffd7 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Thu, 19 Jun 2025 13:48:19 +0100 Subject: [PATCH 25/40] show characteristic descriptions in info modal when available --- CHANGELOG.md | 1 + .../accessory-info/accessory-info.component.html | 12 ++++++++---- .../accessory-info/accessory-info.component.ts | 4 ++++ ui/src/app/core/pipes/prettify.pipe.ts | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 ui/src/app/core/pipes/prettify.pipe.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 932529312..39a5d2789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - refactor HBv2 and UIv5 readiness modals - move backup settings from ui advanced settings to backup/restore modal - show lock management service info on lock mechanism info modal +- show characteristic descriptions in info modal when available ### Other Changes diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html index d9eafa318..1c4736b05 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html @@ -70,8 +70,10 @@
      {{ 'accessories.service_info' | translate }}
      {{ characteristic.description }} @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ - characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } @if + (enums[characteristic.type]?.[characteristic.value]) { ({{ enums[characteristic.type][characteristic.value] | + prettify }}) } +
    • }
    @@ -93,8 +95,10 @@
    {{ 'accessories.service_info' | translate }}
    {{ characteristic.description }} @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ - characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } @if + (enums[characteristic.type]?.[characteristic.value]) { ({{ enums[characteristic.type][characteristic.value] | + prettify }}) } + } diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts index f7263a2d3..6e3f0cce5 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts @@ -1,10 +1,12 @@ import { Component, inject, Input, OnInit } from '@angular/core' import { FormsModule } from '@angular/forms' +import { Enums } from '@homebridge/hap-client/dist/hap-types' import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe } from '@ngx-translate/core' import { ServiceTypeX } from '@/app/core/accessories/accessories.interfaces' import { ConvertTempPipe } from '@/app/core/pipes/convert-temp.pipe' +import { PrettifyPipe } from '@/app/core/pipes/prettify.pipe' import { RemoveIndividualAccessoriesComponent } from '@/app/modules/settings/remove-individual-accessories/remove-individual-accessories.component' @Component({ @@ -14,6 +16,7 @@ import { RemoveIndividualAccessoriesComponent } from '@/app/modules/settings/rem FormsModule, TranslatePipe, ConvertTempPipe, + PrettifyPipe, ], }) export class AccessoryInfoComponent implements OnInit { @@ -27,6 +30,7 @@ export class AccessoryInfoComponent implements OnInit { public accessoryInformation: Array public extraServices: ServiceTypeX[] = [] public matchedCachedAccessory: any = null + public enums = Enums constructor() {} diff --git a/ui/src/app/core/pipes/prettify.pipe.ts b/ui/src/app/core/pipes/prettify.pipe.ts new file mode 100644 index 000000000..8061fb182 --- /dev/null +++ b/ui/src/app/core/pipes/prettify.pipe.ts @@ -0,0 +1,16 @@ +import { Pipe, PipeTransform } from '@angular/core' + +@Pipe({ name: 'prettify' }) +export class PrettifyPipe implements PipeTransform { + transform(value: string): string { + if (typeof value !== 'string') { + return value + } + + return value + .replace(/_/g, ' ') // Replace underscores with spaces + .toLowerCase() + .replace(/\b\w/g, char => char.toUpperCase()) // Capitalize the first letter of each word + .replace(/([a-z])([A-Z])/g, '$1 $2') // Add space before uppercase letters that follow lowercase letters + } +} From 3318754db4551f39584710e25c8788d1e7a3266d Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 29 Jun 2025 10:12:59 +0100 Subject: [PATCH 26/40] add icon and tile for filter maintenance accessory --- CHANGELOG.md | 1 + .../accessory-tile.component.html | 2 ++ .../accessory-tile.component.ts | 2 ++ .../filtermaintenance.component.html | 18 +++++++++++++ .../filtermaintenance.component.ts | 22 ++++++++++++++++ ui/src/assets/hap-icons/filtermaintenance.svg | 26 +++++++++++++++++++ ui/src/i18n/bg.json | 1 + ui/src/i18n/ca.json | 1 + ui/src/i18n/cs.json | 1 + ui/src/i18n/de.json | 1 + ui/src/i18n/en.json | 1 + ui/src/i18n/es.json | 1 + ui/src/i18n/fi.json | 1 + ui/src/i18n/fr.json | 1 + ui/src/i18n/he.json | 1 + ui/src/i18n/hu.json | 1 + ui/src/i18n/id.json | 1 + ui/src/i18n/it.json | 1 + ui/src/i18n/ja.json | 1 + ui/src/i18n/ko.json | 1 + ui/src/i18n/mk.json | 1 + ui/src/i18n/nl.json | 1 + ui/src/i18n/no.json | 1 + ui/src/i18n/pl.json | 1 + ui/src/i18n/pt-BR.json | 1 + ui/src/i18n/pt.json | 1 + ui/src/i18n/ru.json | 1 + ui/src/i18n/sl.json | 1 + ui/src/i18n/sv.json | 1 + ui/src/i18n/th.json | 1 + ui/src/i18n/tr.json | 1 + ui/src/i18n/uk.json | 1 + ui/src/i18n/zh-CN.json | 1 + ui/src/i18n/zh-TW.json | 1 + 34 files changed, 99 insertions(+) create mode 100644 ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.html create mode 100644 ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.ts create mode 100644 ui/src/assets/hap-icons/filtermaintenance.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 39a5d2789..43f29efe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - add support for `uiSchema` within plugin configurations - add option to hide update notifications for specific plugins - improve plugin search and result ordering (@justjam2013) +- add icon and tile for filter maintenance accessory ### Other Changes diff --git a/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.html b/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.html index cc2309855..e2dfd64ec 100644 --- a/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.html +++ b/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.html @@ -71,6 +71,8 @@ Humidifier Dehumidifier } @case ('StatelessProgrammableSwitch') { Stateless Programmable Switch + } @case ('FilterMaintenance') { + Filter Maintenance } @default { {{ service.humanType }} } } diff --git a/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.ts b/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.ts index e963b0402..7b0a61f69 100644 --- a/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.ts +++ b/ui/src/app/core/accessories/accessory-tile/accessory-tile.component.ts @@ -11,6 +11,7 @@ import { ContactsensorComponent } from '@/app/core/accessories/types/contactsens import { DoorComponent } from '@/app/core/accessories/types/door/door.component' import { FanComponent } from '@/app/core/accessories/types/fan/fan.component' import { Fanv2Component } from '@/app/core/accessories/types/fanv2/fanv2.component' +import { FilterMaintenanceComponent } from '@/app/core/accessories/types/filtermaintenance/filtermaintenance.component' import { GaragedooropenerComponent } from '@/app/core/accessories/types/garagedooropener/garagedooropener.component' import { HeaterCoolerComponent } from '@/app/core/accessories/types/heatercooler/heatercooler.component' import { HumidifierDehumidifierComponent } from '@/app/core/accessories/types/humidifierdehumidifier/humidifierdehumidifier.component' @@ -73,6 +74,7 @@ import { WindowCoveringComponent } from '@/app/core/accessories/types/windowcove HeaterCoolerComponent, HumidifierDehumidifierComponent, StatelessprogrammableswitchComponent, + FilterMaintenanceComponent, UnknownComponent, ], }) diff --git a/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.html b/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.html new file mode 100644 index 000000000..7084d5e4a --- /dev/null +++ b/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.html @@ -0,0 +1,18 @@ +
    +
    +
    +
    {{ service.customName || service.serviceName }}
    +
    + + {{ service.values.FilterLifeLevel }}% + + @if (service.values.FilterChangeIndication === 1) { · + {{ 'accessories.control.replace' | translate }} + } +
    +
    +
    diff --git a/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.ts b/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.ts new file mode 100644 index 000000000..17c98fa83 --- /dev/null +++ b/ui/src/app/core/accessories/types/filtermaintenance/filtermaintenance.component.ts @@ -0,0 +1,22 @@ +import { NgClass } from '@angular/common' +import { Component, Input } from '@angular/core' +import { TranslatePipe } from '@ngx-translate/core' +import { InlineSVGModule } from 'ng-inline-svg-2' + +import { ServiceTypeX } from '@/app/core/accessories/accessories.interfaces' + +@Component({ + selector: 'app-filtermaintenance', + templateUrl: './filtermaintenance.component.html', + standalone: true, + imports: [ + InlineSVGModule, + NgClass, + TranslatePipe, + ], +}) +export class FilterMaintenanceComponent { + @Input() public service: ServiceTypeX + + constructor() {} +} diff --git a/ui/src/assets/hap-icons/filtermaintenance.svg b/ui/src/assets/hap-icons/filtermaintenance.svg new file mode 100644 index 000000000..b9ea8f234 --- /dev/null +++ b/ui/src/assets/hap-icons/filtermaintenance.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 53c66c6ba..d2f8c2610 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -48,6 +48,7 @@ "accessories.control.on": "Включено", "accessories.control.open": "Отворено", "accessories.control.opening": "Отваряне", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index c8d0d8e5a..728fb6182 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -48,6 +48,7 @@ "accessories.control.on": "Engegat", "accessories.control.open": "Obert", "accessories.control.opening": "Obrint", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 41a169965..921449fcb 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -48,6 +48,7 @@ "accessories.control.on": "Zapnuto", "accessories.control.open": "Otevřeno", "accessories.control.opening": "Otevírám", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index d0f1dba8d..1a9179ab8 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -48,6 +48,7 @@ "accessories.control.on": "An", "accessories.control.open": "Offen", "accessories.control.opening": "Beim Öffnen", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Gegen den Uhrzeigersinn", "accessories.control.rotation_clockwise": "Im Uhrzeigersinn", "accessories.control.rotation_direction": "Drehrichtung ", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 8e9909271..c187be3d8 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -48,6 +48,7 @@ "accessories.control.on": "On", "accessories.control.open": "Open", "accessories.control.opening": "Opening", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 7ff82ae8e..61133c61d 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -48,6 +48,7 @@ "accessories.control.on": "Encendido", "accessories.control.open": "Abierto", "accessories.control.opening": "Abriendo", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Contra las Manecillas del Reloj", "accessories.control.rotation_clockwise": "En el Sentido de las Manecillas del Reloj", "accessories.control.rotation_direction": "Dirección de Rotación", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 70dfe8e1c..80b134694 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -48,6 +48,7 @@ "accessories.control.on": "Päällä", "accessories.control.open": "Auki", "accessories.control.opening": "Avautuu", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index e2261b129..8c462f06c 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -48,6 +48,7 @@ "accessories.control.on": "On", "accessories.control.open": "Ouvert", "accessories.control.opening": "Ouverture", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 57ddd112f..17f38c7c9 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -48,6 +48,7 @@ "accessories.control.on": "פועל", "accessories.control.open": "פתח", "accessories.control.opening": "פותח", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index 6ea5f8f3c..623d20397 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -48,6 +48,7 @@ "accessories.control.on": "On", "accessories.control.open": "Open", "accessories.control.opening": "Opening", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 20fb551ee..3fa3705de 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -48,6 +48,7 @@ "accessories.control.on": "Hidup", "accessories.control.open": "Buka", "accessories.control.opening": "Membuka", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Berlawanan Arah Jarum Jam", "accessories.control.rotation_clockwise": "Searah Jarum Jam", "accessories.control.rotation_direction": "Arah Rotasi", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index c16bd35a7..d94e75db5 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -48,6 +48,7 @@ "accessories.control.on": "Acceso", "accessories.control.open": "Aperto", "accessories.control.opening": "In apertura", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 3e6e4fbd5..d45740939 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -48,6 +48,7 @@ "accessories.control.on": "オン", "accessories.control.open": "開放済み", "accessories.control.opening": "開放中", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 6b291a6d3..e5c348931 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -48,6 +48,7 @@ "accessories.control.on": "켜짐", "accessories.control.open": "열림", "accessories.control.opening": "여는 중", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 08ea584c1..0c5a36efe 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -48,6 +48,7 @@ "accessories.control.on": "Уклучено", "accessories.control.open": "Отворено", "accessories.control.opening": "Се отвора", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 366f92727..e7f918742 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -48,6 +48,7 @@ "accessories.control.on": "Aan", "accessories.control.open": "Open", "accessories.control.opening": "Aan het openen", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 918c8bc6d..49045028a 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -48,6 +48,7 @@ "accessories.control.on": "På", "accessories.control.open": "Åpen", "accessories.control.opening": "Åpner", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 582276dfc..c4bc55c31 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -48,6 +48,7 @@ "accessories.control.on": "Wł.", "accessories.control.open": "Otwarte", "accessories.control.opening": "Otwieranie", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index e1f545649..1acbf6b85 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -48,6 +48,7 @@ "accessories.control.on": "Ligado", "accessories.control.open": "Aberto", "accessories.control.opening": "Abrindo", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 3761da5a8..435404819 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -48,6 +48,7 @@ "accessories.control.on": "Ligado", "accessories.control.open": "Aberto", "accessories.control.opening": "A Abrir", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index cde319b07..1db68931e 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -48,6 +48,7 @@ "accessories.control.on": "Вкл.", "accessories.control.open": "Открыто", "accessories.control.opening": "Открывается", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Против часовой стрелки", "accessories.control.rotation_clockwise": "По часовой стрелке", "accessories.control.rotation_direction": "Направление вращения", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index 22afb649e..5ff20c1ad 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -48,6 +48,7 @@ "accessories.control.on": "Vključeno", "accessories.control.open": "Odpri", "accessories.control.opening": "Odpiranje", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 413be376a..3523a3bee 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -48,6 +48,7 @@ "accessories.control.on": "På", "accessories.control.open": "Öppen", "accessories.control.opening": "Öppnar", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 0601be07a..3d7fee480 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -48,6 +48,7 @@ "accessories.control.on": "เปิด", "accessories.control.open": "เปิด", "accessories.control.opening": "กำลังเปิด", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "ทวนเข็มนาฬิกา", "accessories.control.rotation_clockwise": "ตามเข็มนาฬิกา", "accessories.control.rotation_direction": "ทิศทางการหมุน", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index d18230f13..c4da84557 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -48,6 +48,7 @@ "accessories.control.on": "Açık", "accessories.control.open": "Açık", "accessories.control.opening": "Açılıyor", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 1b5b3efc0..dcc521a31 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -48,6 +48,7 @@ "accessories.control.on": "Увім.", "accessories.control.open": "Відкрито", "accessories.control.opening": "Відкривається", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Проти годинникової стрілки", "accessories.control.rotation_clockwise": "За годинниковою стрілкою", "accessories.control.rotation_direction": "Напрямок обертання", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 1965544cd..6f3d6bbd8 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -48,6 +48,7 @@ "accessories.control.on": "开启", "accessories.control.open": "打开", "accessories.control.opening": "正在打开", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index d93c9a0bf..606f70aab 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -48,6 +48,7 @@ "accessories.control.on": "開啟", "accessories.control.open": "開啟", "accessories.control.opening": "開啟中", + "accessories.control.replace": "Replace", "accessories.control.rotation_c_clockwise": "Counter Clockwise", "accessories.control.rotation_clockwise": "Clockwise", "accessories.control.rotation_direction": "Rotation Direction", From 2670df40167e32feab0315eff777ef987aa1b235 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:07:43 +0100 Subject: [PATCH 27/40] v4.77.0 --- .github/workflows/release.yml | 1 + .github/workflows/validate.yml | 1 + CHANGELOG.md | 11 +- package-lock.json | 1184 +++++++++-------- package.json | 34 +- ui/angular.json | 1 + ui/package-lock.json | 426 +++--- ui/package.json | 48 +- .../@ng-bootstrap+ng-bootstrap+18.0.0.patch | 56 - .../ui-v5-modal/ui-v5-modal.component.html | 2 +- 10 files changed, 911 insertions(+), 853 deletions(-) delete mode 100644 ui/patches/@ng-bootstrap+ng-bootstrap+18.0.0.patch diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4bd40b97..2a9be0981 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,6 +37,7 @@ jobs: with: enable_coverage: true install_cmd: npm ci && cd ui && npm ci + node_versions: '["20", "22"]' secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 32d82c7f5..5ebdb56b1 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -23,6 +23,7 @@ jobs: uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: enable_coverage: false + node_versions: '["20", "22"]' # # Code Coverage can only be used in a single run, not in a parallel run - Error: Bad response: 422 {"message":"Can't add a job to a build that is already closed. Build 6224987022 is closed. See docs.coveralls.io/parallel-builds","error":true} # # Coveralls only expects to create a report once per build runs_on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 43f29efe4..1e70a0b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,11 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.77.0 (Unreleased) +## v4.77.0 (2025-06-29) ### ⚠️ Upcoming Deprecations: -- A new version of Homebridge UI (v5) will be released around mid-June 2025. This will be compatible with both Homebridge v1 and v2 (in beta). +- A new version of Homebridge UI (v5) will be released in July 2025. This will be compatible with both Homebridge v1 and v2 (in beta). - Initially, there will be no significant differences between Homebridge UI v4 and v5. The major version increment primarily reflects the removal of support for outdated technologies and hardware. UI v5 will: - Be compatible with Homebridge `v1` and `v2` - Drop support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) @@ -14,6 +14,11 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - Drop support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) - Note that these are not requirements for UI `v4.77.0` +### ⚠️ Default Theme Change: + +- The default theme for Homebridge UI has been changed from `orange` to `deep-purple`. + - If you want to change the theme back to `orange`, you can do so in the settings page. + ### UI Changes - updates to the `th.json` language file (#2472) (@tomzt) @@ -33,7 +38,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. ### Homebridge Dependencies -- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/hap-client` @ `v3.1.0` - `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` - `@homebridge/plugin-ui-utils` @ `v2.1.0` diff --git a/package-lock.json b/package-lock.json index cc31816d3..29f0f00c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-config-ui-x", - "version": "4.76.0", + "version": "4.77.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebridge-config-ui-x", - "version": "4.76.0", + "version": "4.77.0", "funding": [ { "type": "github", @@ -22,18 +22,18 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", - "@nestjs/common": "10.4.18", - "@nestjs/core": "10.4.18", + "@nestjs/common": "10.4.19", + "@nestjs/core": "10.4.19", "@nestjs/jwt": "10.2.0", "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.18", - "@nestjs/platform-socket.io": "10.4.18", + "@nestjs/platform-fastify": "10.4.19", + "@nestjs/platform-socket.io": "10.4.19", "@nestjs/swagger": "8.1.1", - "@nestjs/websockets": "10.4.18", - "axios": "1.9.0", + "@nestjs/websockets": "10.4.19", + "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", @@ -53,7 +53,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.1", + "systeminformation": "5.27.7", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", @@ -64,20 +64,20 @@ "homebridge-config-ui-x": "dist/bin/standalone.js" }, "devDependencies": { - "@antfu/eslint-config": "^4.14.1", - "@nestjs/testing": "^10.4.18", + "@antfu/eslint-config": "^4.16.1", + "@nestjs/testing": "^10.4.19", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.17", - "@types/node": "^22.15.30", + "@types/lodash": "^4.17.19", + "@types/node": "^24.0.7", "@types/node-schedule": "^2.1.7", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", "@types/tail": "^2.2.3", "@types/tcp-port-used": "^1.0.4", "@types/unzipper": "^0.10.11", - "@vitest/coverage-v8": "^3.2.2", - "concurrently": "^9.1.2", + "@vitest/coverage-v8": "3.2.3", + "concurrently": "^9.2.0", "eslint-plugin-format": "^1.0.1", "form-data": "^4.0.3", "nodemon": "^3.1.10", @@ -86,8 +86,8 @@ "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.8.3", - "unplugin-swc": "^1.5.4", - "vitest": "^3.2.2" + "unplugin-swc": "^1.5.5", + "vitest": "3.2.3" }, "engines": { "homebridge": "^1.8.0 || ^2.0.0-beta.0", @@ -109,34 +109,35 @@ } }, "node_modules/@antfu/eslint-config": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.14.1.tgz", - "integrity": "sha512-SVGR33/jSUwMWvC8q3NGF/XEHWFJVfMg8yaQJDtRSGISXm23DVA/ANTADpRKhXpk7IjfnjzPpbT/+T6wFzOmUA==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.16.1.tgz", + "integrity": "sha512-20hA+bjnEmYnZChnQFM9ugPF+FR5N2yd6UNUjhZSmTeYpaKnkJ1EvZyEWxnmVGKC5O5HNDEJY3BXUQymdOoftQ==", "dev": true, "license": "MIT", "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^0.11.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", - "@eslint/markdown": "^6.5.0", - "@stylistic/eslint-plugin": "^5.0.0-beta.1", - "@typescript-eslint/eslint-plugin": "^8.33.1", - "@typescript-eslint/parser": "^8.33.1", - "@vitest/eslint-plugin": "^1.2.1", + "@eslint/markdown": "^6.6.0", + "@stylistic/eslint-plugin": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^8.34.1", + "@typescript-eslint/parser": "^8.34.1", + "@vitest/eslint-plugin": "^1.2.7", "ansis": "^4.1.0", "cac": "^6.7.14", "eslint-config-flat-gitignore": "^2.1.0", "eslint-flat-config-utils": "^2.1.0", "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.1.1", - "eslint-plugin-command": "^3.2.1", - "eslint-plugin-jsdoc": "^50.7.1", + "eslint-plugin-command": "^3.3.1", + "eslint-plugin-import-lite": "^0.3.0", + "eslint-plugin-jsdoc": "^51.2.1", "eslint-plugin-jsonc": "^2.20.1", - "eslint-plugin-n": "^17.19.0", + "eslint-plugin-n": "^17.20.0", "eslint-plugin-no-only-tests": "^3.3.0", - "eslint-plugin-perfectionist": "^4.14.0", + "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^0.3.1", - "eslint-plugin-regexp": "^2.8.0", + "eslint-plugin-regexp": "^2.9.0", "eslint-plugin-toml": "^0.12.0", "eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unused-imports": "^4.1.4", @@ -254,13 +255,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", - "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", + "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.27.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -270,9 +271,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", - "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", + "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", "dev": true, "license": "MIT", "dependencies": { @@ -866,16 +867,16 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", - "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.1.tgz", + "integrity": "sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": "^9.10.0" + "eslint": "^8.40 || 9" }, "peerDependenciesMeta": { "eslint": { @@ -884,9 +885,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -900,9 +901,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -926,9 +927,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -975,9 +976,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -1015,9 +1016,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.0.tgz", + "integrity": "sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==", "dev": true, "license": "MIT", "peer": true, @@ -1029,14 +1030,18 @@ } }, "node_modules/@eslint/markdown": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.5.0.tgz", - "integrity": "sha512-oSkF0p8X21vKEEAGTZASi7q3tbdTvlGduQ02Xz2A1AFncUP4RLVcNz27XurxVW4fs1JXuh0xBtvokXdtp/nN+Q==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.6.0.tgz", + "integrity": "sha512-IsWPy2jU3gaQDlioDC4sT4I4kG1hX1OMWs/q2sWwJrPoMASHW/Z4SDw+6Aql6EsHejGbagYuJbFq9Zvx+Y1b1Q==", "dev": true, "license": "MIT", + "workspaces": [ + "examples/*" + ], "dependencies": { "@eslint/core": "^0.14.0", "@eslint/plugin-kit": "^0.3.1", + "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.0.0", @@ -1059,19 +1064,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@fastify/accept-negotiator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz", @@ -1282,12 +1300,12 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", - "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-3.1.0.tgz", + "integrity": "sha512-8w2ciWvtNqBspFN/WVpkGEOqCEg1w3XPC/haU7pJbE/GIh4g/Nt8+2t5nOivunpsE+9TY44Ily3MBEsfxFru2A==", "license": "MIT", "dependencies": { - "axios": "1.9.0", + "axios": "1.10.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", @@ -1376,6 +1394,29 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1522,9 +1563,9 @@ } }, "node_modules/@nestjs/common": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.18.tgz", - "integrity": "sha512-9SrTth6YJJ9CjVnekw9WP8kaiwh+tSgR0KIrPYV/aWgF9D0175uDJUglzbiCfUbkPyHN8jcKXUXd3EVPDY6BNA==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.19.tgz", + "integrity": "sha512-0TZJ8H+7qtaqZt6YfZJkDRp0e+v6jjo5/pevPAjUy0WYxaTy16bNNQxFPRKLMe/v1hUr2oGV9imvL2477zNt5g==", "license": "MIT", "dependencies": { "file-type": "20.4.1", @@ -1552,9 +1593,9 @@ } }, "node_modules/@nestjs/core": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.18.tgz", - "integrity": "sha512-+cs96rnpHIfkn9o0DLZFKuE1RZ3FFQkpkzz+DY2U8C3Wn3VX5fQaO4YuabweLIhUKTLr9DMxPycA5qk5rAPFBw==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.19.tgz", + "integrity": "sha512-gahghu0y4Rn4gn/xPjTgNHFMpUM8TxfhdeMowVWTGVnYMZtGeEGbIXMFhJS0Dce3E4VKyqAglzgO9ecAZd4Ong==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -1633,9 +1674,9 @@ } }, "node_modules/@nestjs/platform-fastify": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.18.tgz", - "integrity": "sha512-2Ps17h3/snDjk9Vs4aXF+ZsEBXA2u02wPKxM+15ijM22r0aegpkqSqladP0Rv90MNubEblgHYD5NWXHKndQi1A==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.19.tgz", + "integrity": "sha512-Esl4ruphwh7sfa8JSpi1gSZS/qfD3kX7wBl6kMI2RRRj86sLWfAIbXoG0I0zm0hMQrpfboC06zPkOsnvFzIOPQ==", "license": "MIT", "dependencies": { "@fastify/cors": "9.0.1", @@ -1666,9 +1707,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.18.tgz", - "integrity": "sha512-+X/c4I5rYJU/X5ZRhrd3jJ/bL86zWWTc6FIdhNfTvVyLneYkIH9+snCyi4+7lu0auhDXqA90zNzmaUg9Iwno1Q==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.19.tgz", + "integrity": "sha512-Pfz9dBcXaoUFdVpA/I96NoOTiTQ7eYfDNhQ2sZdQzne3oISEvts5G2SWyQNouoyjqkUPt6X5r/CQ++M4AzSlEQ==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -1718,9 +1759,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.18.tgz", - "integrity": "sha512-oTeGjnh1qeSZMFqze1Rz5lEtAOBRDApulWDoLYSyzh+8/jFflhCYAGeOHncItkGq9wBRe1R1Ct2GyRFdTmpcjg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.19.tgz", + "integrity": "sha512-YfzkjTmwEcoWqo8xr8YiTZMC4FjBEOg4uRTAPI2p6iGLWu+27tYau1CtAKFHY0uSAK3FzgtsAuYoxBSlfr9mWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1746,9 +1787,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.18.tgz", - "integrity": "sha512-FnwRiUGReMo8guM6fVoDotwAxOzV0Y2bLC+avz1kPfCUT7LAvivMQ0xs+rJy/nmdHb2TDxwFOK6gyQSznUdOzQ==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.19.tgz", + "integrity": "sha512-3HhNZU40/ozB64ZZJ1W1bOOYSbxGuJwmM5Ui8y1uPwbzpL1Uov3wOG3eRp1IflSBK4Ia0wb8Iv3ChpFSTzrNiA==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -1908,9 +1949,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -1931,9 +1972,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", - "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", + "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", "cpu": [ "arm" ], @@ -1945,9 +1986,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", - "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", + "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", "cpu": [ "arm64" ], @@ -1959,9 +2000,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", - "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", + "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", "cpu": [ "arm64" ], @@ -1973,9 +2014,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", - "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", + "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", "cpu": [ "x64" ], @@ -1987,9 +2028,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", - "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", + "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", "cpu": [ "arm64" ], @@ -2001,9 +2042,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", - "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", + "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", "cpu": [ "x64" ], @@ -2015,9 +2056,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", - "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", + "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", "cpu": [ "arm" ], @@ -2029,9 +2070,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", - "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", + "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", "cpu": [ "arm" ], @@ -2043,9 +2084,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", - "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", + "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", "cpu": [ "arm64" ], @@ -2057,9 +2098,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", - "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", + "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", "cpu": [ "arm64" ], @@ -2071,9 +2112,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", - "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", + "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", "cpu": [ "loong64" ], @@ -2085,9 +2126,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", - "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", + "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", "cpu": [ "ppc64" ], @@ -2099,9 +2140,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", - "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", + "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", "cpu": [ "riscv64" ], @@ -2113,9 +2154,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", - "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", + "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", "cpu": [ "riscv64" ], @@ -2127,9 +2168,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", - "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", + "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", "cpu": [ "s390x" ], @@ -2141,9 +2182,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", - "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", + "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", "cpu": [ "x64" ], @@ -2155,9 +2196,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", - "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", + "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", "cpu": [ "x64" ], @@ -2169,9 +2210,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", - "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", + "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", "cpu": [ "arm64" ], @@ -2183,9 +2224,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", - "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", + "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", "cpu": [ "ia32" ], @@ -2197,9 +2238,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", - "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", + "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", "cpu": [ "x64" ], @@ -2224,15 +2265,16 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.0.0-beta.3.tgz", - "integrity": "sha512-ItDjyhRyc5hx4W/IBy4/EhgPLbTrjeVPgcYG65pZApTg8Prf1nsWz0j7AY/nYd7OqzBAuRSmzrYFlab86ybePw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz", + "integrity": "sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.32.1", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.1", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -2244,16 +2286,16 @@ } }, "node_modules/@swc/core": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.31.tgz", - "integrity": "sha512-mAby9aUnKRjMEA7v8cVZS9Ah4duoRBnX7X6r5qrhTxErx+68MoY1TPrVwj/66/SWN3Bl+jijqAqoB8Qx0QE34A==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.7.tgz", + "integrity": "sha512-bcpllEihyUSnqp0UtXTvXc19CT4wp3tGWLENhWnjr4B5iEOkzqMu+xHGz1FI5IBatjfqOQb29tgIfv6IL05QaA==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "peer": true, "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.21" + "@swc/types": "^0.1.23" }, "engines": { "node": ">=10" @@ -2263,16 +2305,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.11.31", - "@swc/core-darwin-x64": "1.11.31", - "@swc/core-linux-arm-gnueabihf": "1.11.31", - "@swc/core-linux-arm64-gnu": "1.11.31", - "@swc/core-linux-arm64-musl": "1.11.31", - "@swc/core-linux-x64-gnu": "1.11.31", - "@swc/core-linux-x64-musl": "1.11.31", - "@swc/core-win32-arm64-msvc": "1.11.31", - "@swc/core-win32-ia32-msvc": "1.11.31", - "@swc/core-win32-x64-msvc": "1.11.31" + "@swc/core-darwin-arm64": "1.12.7", + "@swc/core-darwin-x64": "1.12.7", + "@swc/core-linux-arm-gnueabihf": "1.12.7", + "@swc/core-linux-arm64-gnu": "1.12.7", + "@swc/core-linux-arm64-musl": "1.12.7", + "@swc/core-linux-x64-gnu": "1.12.7", + "@swc/core-linux-x64-musl": "1.12.7", + "@swc/core-win32-arm64-msvc": "1.12.7", + "@swc/core-win32-ia32-msvc": "1.12.7", + "@swc/core-win32-x64-msvc": "1.12.7" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -2284,9 +2326,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.31.tgz", - "integrity": "sha512-NTEaYOts0OGSbJZc0O74xsji+64JrF1stmBii6D5EevWEtrY4wlZhm8SiP/qPrOB+HqtAihxWIukWkP2aSdGSQ==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.7.tgz", + "integrity": "sha512-w6BBT0hBRS56yS+LbReVym0h+iB7/PpCddqrn1ha94ra4rZ4R/A91A/rkv+LnQlPqU/+fhqdlXtCJU9mrhCBtA==", "cpu": [ "arm64" ], @@ -2302,9 +2344,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.31.tgz", - "integrity": "sha512-THSGaSwT96JwXDwuXQ6yFBbn+xDMdyw7OmBpnweAWsh5DhZmQkALEm1DgdQO3+rrE99MkmzwAfclc0UmYro/OA==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.12.7.tgz", + "integrity": "sha512-jN6LhFfGOpm4DY2mXPgwH4aa9GLOwublwMVFFZ/bGnHYYCRitLZs9+JWBbyWs7MyGcA246Ew+EREx36KVEAxjA==", "cpu": [ "x64" ], @@ -2320,9 +2362,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.31.tgz", - "integrity": "sha512-laKtQFnW7KHgE57Hx32os2SNAogcuIDxYE+3DYIOmDMqD7/1DCfJe6Rln2N9WcOw6HuDbDpyQavIwZNfSAa8vQ==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.12.7.tgz", + "integrity": "sha512-rHn8XXi7G2StEtZRAeJ6c7nhJPDnqsHXmeNrAaYwk8Tvpa6ZYG2nT9E1OQNXj1/dfbSFTjdiA8M8ZvGYBlpBoA==", "cpu": [ "arm" ], @@ -2338,9 +2380,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.31.tgz", - "integrity": "sha512-T+vGw9aPE1YVyRxRr1n7NAdkbgzBzrXCCJ95xAZc/0+WUwmL77Z+js0J5v1KKTRxw4FvrslNCOXzMWrSLdwPSA==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.7.tgz", + "integrity": "sha512-N15hKizSSh+hkZ2x3TDVrxq0TDcbvDbkQJi2ZrLb9fK+NdFUV/x+XF16ZDPlbxtrGXl1CT7VD439SNaMN9F7qw==", "cpu": [ "arm64" ], @@ -2356,9 +2398,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.31.tgz", - "integrity": "sha512-Mztp5NZkyd5MrOAG+kl+QSn0lL4Uawd4CK4J7wm97Hs44N9DHGIG5nOz7Qve1KZo407Y25lTxi/PqzPKHo61zQ==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.12.7.tgz", + "integrity": "sha512-jxyINtBezpxd3eIUDiDXv7UQ87YWlPsM9KumOwJk09FkFSO4oYxV2RT+Wu+Nt5tVWue4N0MdXT/p7SQsDEk4YA==", "cpu": [ "arm64" ], @@ -2374,9 +2416,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.31.tgz", - "integrity": "sha512-DDVE0LZcXOWwOqFU1Xi7gdtiUg3FHA0vbGb3trjWCuI1ZtDZHEQYL4M3/2FjqKZtIwASrDvO96w91okZbXhvMg==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.7.tgz", + "integrity": "sha512-PR4tPVwU1BQBfFDk2XfzXxsEIjF3x/bOV1BzZpYvrlkU0TKUDbR4t2wzvsYwD/coW7/yoQmlL70/qnuPtTp1Zw==", "cpu": [ "x64" ], @@ -2392,9 +2434,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.31.tgz", - "integrity": "sha512-mJA1MzPPRIfaBUHZi0xJQ4vwL09MNWDeFtxXb0r4Yzpf0v5Lue9ymumcBPmw/h6TKWms+Non4+TDquAsweuKSw==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.12.7.tgz", + "integrity": "sha512-zy7JWfQtQItgMfUjSbbcS3DZqQUn2d9VuV0LSGpJxtTXwgzhRpF1S2Sj7cU9hGpbM27Y8RJ4DeFb3qbAufjbrw==", "cpu": [ "x64" ], @@ -2410,9 +2452,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.31.tgz", - "integrity": "sha512-RdtakUkNVAb/FFIMw3LnfNdlH1/ep6KgiPDRlmyUfd0WdIQ3OACmeBegEFNFTzi7gEuzy2Yxg4LWf4IUVk8/bg==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.12.7.tgz", + "integrity": "sha512-52PeF0tyX04ZFD8nibNhy/GjMFOZWTEWPmIB3wpD1vIJ1po+smtBnEdRRll5WIXITKoiND8AeHlBNBPqcsdcwA==", "cpu": [ "arm64" ], @@ -2428,9 +2470,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.31.tgz", - "integrity": "sha512-hErXdCGsg7swWdG1fossuL8542I59xV+all751mYlBoZ8kOghLSKObGQTkBbuNvc0sUKWfWg1X0iBuIhAYar+w==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.12.7.tgz", + "integrity": "sha512-WzQwkNMuhB1qQShT9uUgz/mX2j7NIEPExEtzvGsBT7TlZ9j1kGZ8NJcZH/fwOFcSJL4W7DnkL7nAhx6DBlSPaA==", "cpu": [ "ia32" ], @@ -2446,9 +2488,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.31.tgz", - "integrity": "sha512-5t7SGjUBMMhF9b5j17ml/f/498kiBJNf4vZFNM421UGUEETdtjPN9jZIuQrowBkoFGJTCVL/ECM4YRtTH30u/A==", + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.12.7.tgz", + "integrity": "sha512-R52ivBi2lgjl+Bd3XCPum0YfgbZq/W1AUExITysddP9ErsNSwnreYyNB3exEijiazWGcqHEas2ChiuMOP7NYrA==", "cpu": [ "x64" ], @@ -2472,9 +2514,9 @@ "peer": true }, "node_modules/@swc/types": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.22.tgz", - "integrity": "sha512-D13mY/ZA4PPEFSy6acki9eBT/3WgjMoRqNcdpIvjaYLQ44Xk5BdaL7UkDxAh6Z9UOe7tCCp67BVmZCojYp9owg==", + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", + "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -2692,9 +2734,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ==", "dev": true, "license": "MIT" }, @@ -2723,12 +2765,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.7.tgz", + "integrity": "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/node-schedule": { @@ -2849,23 +2891,23 @@ } }, "node_modules/@types/validator": { - "version": "13.15.1", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.1.tgz", - "integrity": "sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==", + "version": "13.15.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", + "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", - "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", + "integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/type-utils": "8.33.1", - "@typescript-eslint/utils": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/type-utils": "8.35.0", + "@typescript-eslint/utils": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2879,7 +2921,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.1", + "@typescript-eslint/parser": "^8.35.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2895,16 +2937,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", - "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz", + "integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2920,14 +2962,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", - "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", + "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.1", - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/tsconfig-utils": "^8.35.0", + "@typescript-eslint/types": "^8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2942,14 +2984,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", - "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", + "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1" + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2960,9 +3002,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", - "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", + "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", "dev": true, "license": "MIT", "engines": { @@ -2977,14 +3019,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz", - "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz", + "integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/utils": "8.33.1", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/utils": "8.35.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3001,9 +3043,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", - "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", + "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", "dev": true, "license": "MIT", "engines": { @@ -3015,16 +3057,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", - "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", + "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.1", - "@typescript-eslint/tsconfig-utils": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/project-service": "8.35.0", + "@typescript-eslint/tsconfig-utils": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3044,16 +3086,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", - "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", + "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1" + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3068,14 +3110,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", - "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", + "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.35.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3086,9 +3128,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.2.tgz", - "integrity": "sha512-RVAi5xnqedSKvaoQyCTWvncMk8eYZcTTOsLK7XmnfOEvdGP/O/upA0/MA8Ss+Qs++mj0GcSRi/whR0S5iBPpTQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.3.tgz", + "integrity": "sha512-D1QKzngg8PcDoCE8FHSZhREDuEy+zcKmMiMafYse41RZpBE5EDJyKOTdqK3RQfsV2S2nyKor5KCs8PyPRFqKPg==", "dev": true, "license": "MIT", "dependencies": { @@ -3110,8 +3152,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.2.2", - "vitest": "3.2.2" + "@vitest/browser": "3.2.3", + "vitest": "3.2.3" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3120,13 +3162,13 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.1.tgz", - "integrity": "sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.3.3.tgz", + "integrity": "sha512-zOB4T5f80JXfP5DC2yQl7azRYq8PmGqYle3uxh3a0NnbKc+EaSYSpEcrVAh2r5W97pi3BVv7oRb5NdEQy0cCXA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.24.0" + "@typescript-eslint/utils": "^8.24.1" }, "peerDependencies": { "eslint": ">= 8.57.0", @@ -3143,15 +3185,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", - "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz", + "integrity": "sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3160,13 +3202,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.3.tgz", + "integrity": "sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.2", + "@vitest/spy": "3.2.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3197,9 +3239,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", - "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -3210,27 +3252,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", - "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.3.tgz", + "integrity": "sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.2", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.3", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", - "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.3.tgz", + "integrity": "sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3238,10 +3281,23 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", + "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vitest/spy": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", - "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.3.tgz", + "integrity": "sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==", "dev": true, "license": "MIT", "dependencies": { @@ -3252,13 +3308,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", - "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.3.tgz", + "integrity": "sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -3266,68 +3322,81 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", + "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@vue/compiler-core": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.16.tgz", - "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/shared": "3.5.16", + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz", - "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-core": "3.5.16", - "@vue/shared": "3.5.16" + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz", - "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/compiler-core": "3.5.16", - "@vue/compiler-dom": "3.5.16", - "@vue/compiler-ssr": "3.5.16", - "@vue/shared": "3.5.16", + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", - "postcss": "^8.5.3", + "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz", - "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.16", - "@vue/shared": "3.5.16" + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/shared": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.16.tgz", - "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", "dev": true, "license": "MIT", "peer": true @@ -3554,9 +3623,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3813,9 +3882,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3912,9 +3981,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -3934,9 +4003,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -3954,8 +4023,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -4050,9 +4119,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "dev": true, "funding": [ { @@ -4427,9 +4496,9 @@ "license": "MIT" }, "node_modules/concurrently": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", - "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.0.tgz", + "integrity": "sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4503,13 +4572,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -4617,9 +4686,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4833,9 +4902,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.177", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", + "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", "dev": true, "license": "ISC" }, @@ -4846,9 +4915,9 @@ "license": "MIT" }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -4910,9 +4979,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5060,20 +5129,20 @@ } }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.0.tgz", + "integrity": "sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", + "@eslint/js": "9.30.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5085,9 +5154,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5238,9 +5307,9 @@ } }, "node_modules/eslint-plugin-command": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-3.2.1.tgz", - "integrity": "sha512-PcpzWe8dvAPaBobxE9zgz1w94fO4JYvzciDzw6thlUb9Uqf5e2/gJz97itOGxvdq+mFeudi71m1OGFgvWmb93w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-3.3.1.tgz", + "integrity": "sha512-fBVTXQ2y48TVLT0+4A6PFINp7GcdIailHAXbvPBixE7x+YpYnNQhFZxTdvnb+aWk+COgNebQKen/7m4dmgyWAw==", "dev": true, "license": "MIT", "dependencies": { @@ -5313,31 +5382,71 @@ "eslint": "^8.40.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-import-lite": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-lite/-/eslint-plugin-import-lite-0.3.0.tgz", + "integrity": "sha512-dkNBAL6jcoCsXZsQ/Tt2yXmMDoNt5NaBh/U7yvccjiK8cai6Ay+MK77bMykmqQA2bTF6lngaLCDij6MTO3KkvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.7.1.tgz", - "integrity": "sha512-XBnVA5g2kUVokTNUiE1McEPse5n9/mNUmuJcx52psT6zBs2eVcXSmQBvjfa7NZdfLVSy3u1pEDDUxoxpwy89WA==", + "version": "51.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.2.3.tgz", + "integrity": "sha512-pagzxFubOih+O6XSB1D8BkDkJjF4G4/v8s9pRg4FkXQJLu0e3QJg621ayhmnhyc5mNBpp3cYCNiUyeLQs7oz7w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.50.2", + "@es-joy/jsdoccomment": "~0.52.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", - "espree": "^10.3.0", + "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=20.11.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/@es-joy/jsdoccomment": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", + "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.34.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/eslint-plugin-jsonc": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.20.1.tgz", @@ -5394,9 +5503,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.19.0.tgz", - "integrity": "sha512-qxn1NaDHtizbhVAPpbMT8wWFaLtPnwhfN/e+chdu2i6Vgzmo/tGM62tcJ1Hf7J5Ie4dhse3DOPMmDxduzfifzw==", + "version": "17.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.20.0.tgz", + "integrity": "sha512-IRSoatgB/NQJZG5EeTbv/iAx1byOGdbbyhQrNvWdCfTnmPxUT0ao9/eGOeG7ljD8wJBsxwE8f6tES5Db0FRKEw==", "dev": true, "license": "MIT", "dependencies": { @@ -5445,14 +5554,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.14.0.tgz", - "integrity": "sha512-BkhiOqzdum8vQSFgj1/q5+6UUWPMn4GELdxuX7uIsGegmAeH/+LnWsiVxgMrxalD0p68sYfMeKaHF1NfrpI/mg==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.33.1", - "@typescript-eslint/utils": "^8.33.1", + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "engines": { @@ -5491,9 +5600,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.8.0.tgz", - "integrity": "sha512-xme90IvkMgdyS+NJC21FM0H6ek4urGsdlIFTXpZRqH2BKJKVSd8hRbyrCpbcqfGBi2jth3eQoLiO3RC1gxZHiw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz", + "integrity": "sha512-9WqJMnOq8VlE/cK+YAo9C9YHhkOtcEtEk9d12a+H7OSZFwlpI6stiHmYPGa2VE0QhTzodJyhlyprUaXDZLgHBw==", "dev": true, "license": "MIT", "dependencies": { @@ -5672,9 +5781,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5689,9 +5798,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5702,9 +5811,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -5728,15 +5837,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5830,9 +5939,9 @@ } }, "node_modules/exsolve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", "dev": true, "license": "MIT" }, @@ -6097,9 +6206,9 @@ } }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6410,6 +6519,13 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true, + "license": "ISC" + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -7328,9 +7444,9 @@ } }, "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", "dev": true, "license": "MIT" }, @@ -8668,9 +8784,9 @@ } }, "node_modules/nodemon/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -9040,9 +9156,9 @@ "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -9054,19 +9170,6 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, - "node_modules/peek-readable": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", - "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -9141,14 +9244,14 @@ "license": "MIT" }, "node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.1.tgz", + "integrity": "sha512-eY0QFb6eSwc9+0d/5D2lFFUq+A3n3QNGSy/X2Nvp+6MfzGw2u6EbA7S80actgjY1lkvvI0pqB+a4hioMh443Ew==", "dev": true, "license": "MIT", "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", + "confbox": "^0.2.2", + "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, @@ -9183,9 +9286,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -9262,9 +9365,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -9329,9 +9432,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -9658,15 +9761,15 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", - "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -9708,13 +9811,13 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { "node": "20 || >=22" @@ -9741,13 +9844,13 @@ } }, "node_modules/rollup": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", - "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", + "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -9757,36 +9860,29 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.42.0", - "@rollup/rollup-android-arm64": "4.42.0", - "@rollup/rollup-darwin-arm64": "4.42.0", - "@rollup/rollup-darwin-x64": "4.42.0", - "@rollup/rollup-freebsd-arm64": "4.42.0", - "@rollup/rollup-freebsd-x64": "4.42.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", - "@rollup/rollup-linux-arm-musleabihf": "4.42.0", - "@rollup/rollup-linux-arm64-gnu": "4.42.0", - "@rollup/rollup-linux-arm64-musl": "4.42.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-musl": "4.42.0", - "@rollup/rollup-linux-s390x-gnu": "4.42.0", - "@rollup/rollup-linux-x64-gnu": "4.42.0", - "@rollup/rollup-linux-x64-musl": "4.42.0", - "@rollup/rollup-win32-arm64-msvc": "4.42.0", - "@rollup/rollup-win32-ia32-msvc": "4.42.0", - "@rollup/rollup-win32-x64-msvc": "4.42.0", + "@rollup/rollup-android-arm-eabi": "4.44.1", + "@rollup/rollup-android-arm64": "4.44.1", + "@rollup/rollup-darwin-arm64": "4.44.1", + "@rollup/rollup-darwin-x64": "4.44.1", + "@rollup/rollup-freebsd-arm64": "4.44.1", + "@rollup/rollup-freebsd-x64": "4.44.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", + "@rollup/rollup-linux-arm-musleabihf": "4.44.1", + "@rollup/rollup-linux-arm64-gnu": "4.44.1", + "@rollup/rollup-linux-arm64-musl": "4.44.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-musl": "4.44.1", + "@rollup/rollup-linux-s390x-gnu": "4.44.1", + "@rollup/rollup-linux-x64-gnu": "4.44.1", + "@rollup/rollup-linux-x64-musl": "4.44.1", + "@rollup/rollup-win32-arm64-msvc": "4.44.1", + "@rollup/rollup-win32-ia32-msvc": "4.44.1", + "@rollup/rollup-win32-x64-msvc": "4.44.1", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10458,14 +10554,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/strtok3": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.2.2.tgz", - "integrity": "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.1.tgz", + "integrity": "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw==", "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^7.0.0" + "@tokenizer/token": "^0.3.0" }, "engines": { "node": ">=18" @@ -10514,9 +10622,9 @@ } }, "node_modules/systeminformation": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.1.tgz", - "integrity": "sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==", + "version": "5.27.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.7.tgz", + "integrity": "sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg==", "license": "MIT", "os": [ "darwin", @@ -10643,9 +10751,9 @@ "license": "MIT" }, "node_modules/terser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz", - "integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==", + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -10776,9 +10884,9 @@ } }, "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -10837,9 +10945,9 @@ } }, "node_modules/token-types": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", - "integrity": "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.3.tgz", + "integrity": "sha512-IKJ6EzuPPWtKtEIEPpIdXv9j5j2LGJEYk0CKY2efgKoYKLBiZdh6iQkLVBow/CB3phyWAWCyk+bZeaimJn6uRQ==", "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0", @@ -11118,9 +11226,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/unist-util-is": { @@ -11207,13 +11315,13 @@ } }, "node_modules/unplugin-swc": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.4.tgz", - "integrity": "sha512-NYa0rEUI8+Ckr+azVyAWIBWOrqnoWsDeHPLCMAsEWXJzkNwG1GtYf/Fe872ulOPKRmQsY1VEd20d5Y3fLiiZQQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.5.tgz", + "integrity": "sha512-BahYtYvQ/KSgOqHoy5FfQgp/oZNAB7jwERxNeFVeN/PtJhg4fpK/ybj9OwKtqGPseOadS7+TGbq6tH2DmDAYvA==", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.1.4", + "@rollup/pluginutils": "^5.2.0", "load-tsconfig": "^0.2.5", "unplugin": "^2.3.5" }, @@ -11392,9 +11500,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.2.tgz", - "integrity": "sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz", + "integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11415,20 +11523,20 @@ } }, "node_modules/vitest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz", - "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.3.tgz", + "integrity": "sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.2", - "@vitest/mocker": "3.2.2", - "@vitest/pretty-format": "^3.2.2", - "@vitest/runner": "3.2.2", - "@vitest/snapshot": "3.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/expect": "3.2.3", + "@vitest/mocker": "3.2.3", + "@vitest/pretty-format": "^3.2.3", + "@vitest/runner": "3.2.3", + "@vitest/snapshot": "3.2.3", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -11442,7 +11550,7 @@ "tinypool": "^1.1.0", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.2", + "vite-node": "3.2.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -11458,8 +11566,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.2", - "@vitest/ui": "3.2.2", + "@vitest/browser": "3.2.3", + "@vitest/ui": "3.2.3", "happy-dom": "*", "jsdom": "*" }, @@ -11495,9 +11603,9 @@ "license": "MIT" }, "node_modules/vue-eslint-parser": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz", - "integrity": "sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.4.tgz", + "integrity": "sha512-EIZvCukIEMHEb3mxOKemtvWR1fcUAdWWAgkfyjmRHzvyhrZvBvH9oz69+thDIWhGiIQjZnPkCn8yHqvjM+a9eg==", "dev": true, "license": "MIT", "dependencies": { @@ -11599,9 +11707,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz", - "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", "peer": true, diff --git a/package.json b/package.json index 626f9b241..839d8182a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "homebridge-config-ui-x", "displayName": "Homebridge UI", - "version": "4.76.0", + "version": "4.77.0", "description": "A web based management, configuration and control platform for Homebridge.", "author": "oznu ", "license": "MIT", @@ -82,18 +82,18 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", - "@nestjs/common": "10.4.18", - "@nestjs/core": "10.4.18", + "@nestjs/common": "10.4.19", + "@nestjs/core": "10.4.19", "@nestjs/jwt": "10.2.0", "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.18", - "@nestjs/platform-socket.io": "10.4.18", + "@nestjs/platform-fastify": "10.4.19", + "@nestjs/platform-socket.io": "10.4.19", "@nestjs/swagger": "8.1.1", - "@nestjs/websockets": "10.4.18", - "axios": "1.9.0", + "@nestjs/websockets": "10.4.19", + "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", @@ -113,27 +113,27 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.1", + "systeminformation": "5.27.7", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", "unzipper": "0.12.3" }, "devDependencies": { - "@antfu/eslint-config": "^4.14.1", - "@nestjs/testing": "^10.4.18", + "@antfu/eslint-config": "^4.16.1", + "@nestjs/testing": "^10.4.19", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.17", - "@types/node": "^22.15.30", + "@types/lodash": "^4.17.19", + "@types/node": "^24.0.7", "@types/node-schedule": "^2.1.7", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", "@types/tail": "^2.2.3", "@types/tcp-port-used": "^1.0.4", "@types/unzipper": "^0.10.11", - "@vitest/coverage-v8": "^3.2.2", - "concurrently": "^9.1.2", + "@vitest/coverage-v8": "3.2.3", + "concurrently": "^9.2.0", "eslint-plugin-format": "^1.0.1", "form-data": "^4.0.3", "nodemon": "^3.1.10", @@ -142,8 +142,8 @@ "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.8.3", - "unplugin-swc": "^1.5.4", - "vitest": "^3.2.2" + "unplugin-swc": "^1.5.5", + "vitest": "3.2.3" }, "overrides": { "@nestjs/platform-fastify": { diff --git a/ui/angular.json b/ui/angular.json index f387c4e2b..b98f88363 100644 --- a/ui/angular.json +++ b/ui/angular.json @@ -35,6 +35,7 @@ ], "allowedCommonJsDependencies": [ "@/app/modules/status/status.component", + "@homebridge/hap-client/dist/hap-types", "ajv", "ajv-keywords", "dayjs", diff --git a/ui/package-lock.json b/ui/package-lock.json index 2897aad1a..338ed2cbe 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -10,25 +10,25 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2", - "@angular/platform-browser": "20.0.2", - "@angular/platform-browser-dynamic": "20.0.2", - "@angular/router": "20.0.2", + "@angular/animations": "20.0.5", + "@angular/common": "20.0.5", + "@angular/compiler": "20.0.5", + "@angular/core": "20.0.5", + "@angular/forms": "20.0.5", + "@angular/localize": "20.0.5", + "@angular/platform-browser": "20.0.5", + "@angular/platform-browser-dynamic": "20.0.5", + "@angular/router": "20.0.5", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.2.0", - "@ng-bootstrap/ng-bootstrap": "18.0.0", + "@homebridge/hap-client": "3.1.0", + "@ng-bootstrap/ng-bootstrap": "19.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", "@ngx-translate/core": "16.0.4", - "ajv-keywords": "^5.1.0", - "angular-gridster2": "19.0.0", - "bootstrap": "5.3.6", - "chart.js": "4.4.9", + "ajv-keywords": "5.1.0", + "angular-gridster2": "20.0.0", + "bootstrap": "5.3.7", + "chart.js": "4.5.0", "dayjs": "1.11.13", "emoji-js": "3.8.1", "file-saver": "2.0.5", @@ -55,16 +55,16 @@ "zone.js": "0.15.1" }, "devDependencies": { - "@angular/build": "^20.0.1", - "@angular/cli": "^20.0.1", - "@angular/compiler-cli": "^20.0.1", - "@angular/language-service": "^20.0.1", + "@angular/build": "^20.0.4", + "@angular/cli": "^20.0.4", + "@angular/compiler-cli": "^20.0.5", + "@angular/language-service": "^20.0.5", "@fortawesome/fontawesome-free": "^6.7.2", "@homebridge/plugin-ui-utils": "^2.1.0", "@types/emoji-js": "^3.5.2", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.15.30", + "@types/node": "^24.0.7", "@types/qrcode": "^1.5.5", "@types/semver": "^7.7.0", "he": "^1.2.0", @@ -87,13 +87,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2000.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2000.1.tgz", - "integrity": "sha512-EcOGU1xEhARYpDF391VaeUg/+YRym9OxzJMcc0rSHl3YLK8/m+24ap2YAQY5N7n9+mmEqHVu/q31ldFpOoMCTw==", + "version": "0.2000.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2000.4.tgz", + "integrity": "sha512-pg+EPv/j17ybCoYiKjeRCebkE5CeD009xC6XJfugBmui6CcCQ5UAN82ibBhL869PXR7xCboylcRxlFfcBmvCpA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", + "@angular-devkit/core": "20.0.4", "rxjs": "7.8.2" }, "engines": { @@ -103,9 +103,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.0.1.tgz", - "integrity": "sha512-Ilafyj8JVwq3NZsaiGw5UDkP4EAkGKiEvZ4TC3WVidZbM4EpKt9/Jd7ZpsTRGDLG429U+fGhay+ZQeCFGqy5rA==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.0.4.tgz", + "integrity": "sha512-GmHBOEhdZn0Xh8JAdmnbSXtEMoAEqakEFy1JZmwuUo5e6uuuEp5xQY4O3MO0UQBVjYT+Wz8KNfonTvY91t/lNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -131,13 +131,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.0.1.tgz", - "integrity": "sha512-bSr/5YIdjtwKYqylkYrlOVP+tuFz+tfOldmLfWHAsDGnJUznb5t4ckx6yyROp+iDQfu2Aez09p+l4KfUBq+H9A==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.0.4.tgz", + "integrity": "sha512-NADJed7h4KYSqbbw91AKFvFp+CsDuPUBzuMrck38R0ql0ZeaLKJtwT+IQFs7Hb6bmE4xn1i0+Z/p7v8q6ZRrKw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", + "@angular-devkit/core": "20.0.4", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "8.2.0", @@ -150,9 +150,9 @@ } }, "node_modules/@angular/animations": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.0.2.tgz", - "integrity": "sha512-p9TqZdVOFWMF75lfxk++5GZOBGO3K7qVdAXiQw89VLac8yqsu9iXFlcq34x256McHxONTjrrKBeP5oU1T8rxCw==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.0.5.tgz", + "integrity": "sha512-v8dzr2tnju7Sa7XUhMY6yTJpRV3isMqP3mnOjrul2kkEY870a1tZ7VI7xp0qTx36086/+nzXAvOvOItmRkUaaQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -161,19 +161,19 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2" + "@angular/common": "20.0.5", + "@angular/core": "20.0.5" } }, "node_modules/@angular/build": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.0.1.tgz", - "integrity": "sha512-m/0jtXIeOaoU/WXtMLRuvq7UaGRxNHpoRKVVoJrifvZuNBYGM4e2lzxlIlo8kiQhPpZQc0zcAMoosbmzKKdkUQ==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.0.4.tgz", + "integrity": "sha512-SIYLg2st05Q5hgFrxwj6L4i9j2j2JNWYoYgacXp+mw9YVhFiC02Ymbakc9fq+3+sWlm0XTX5JgrupV2ac1ytNQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2000.1", + "@angular-devkit/architect": "0.2000.4", "@babel/core": "7.27.1", "@babel/helper-annotate-as-pure": "7.27.1", "@babel/helper-split-export-declaration": "7.24.7", @@ -190,7 +190,7 @@ "mrmime": "2.0.1", "parse5-html-rewriting-stream": "7.1.0", "picomatch": "4.0.2", - "piscina": "5.0.0", + "piscina": "5.1.1", "rollup": "4.40.2", "sass": "1.88.0", "semver": "7.7.2", @@ -215,7 +215,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.0.1", + "@angular/ssr": "^20.0.4", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^20.0.0", @@ -265,9 +265,9 @@ } }, "node_modules/@angular/cdk": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.2.tgz", - "integrity": "sha512-gRQcpTNhnwBxXSmpnrljODUHQmB2Hnxc6L2Ad6mSMV+c3opd9KIFxL5eG2WOOPHGAaPrV4gNFw+t1i01U4grTg==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.4.tgz", + "integrity": "sha512-NCUuw0qQXwawLsT14JHApNB9or3XGs7D1pWXlOIix/fKqzHVfi4un9xHmpjH2Q1uCiwonuak7fDof8B+IXhbug==", "license": "MIT", "peer": true, "dependencies": { @@ -281,18 +281,18 @@ } }, "node_modules/@angular/cli": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.0.1.tgz", - "integrity": "sha512-OU91byvG/WsDDUVmXIJr3/sU89U6g8G8IXrqgVRVPgjXKEQMnUNBlmygD2rMUR5C02g2lGc6s2j0hnOJ/dDNOw==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.0.4.tgz", + "integrity": "sha512-WG0TxDODciNU93AjENph4v7nBowMTGRI8VwIPitPstthez7oViugnXbsPoti5wfSjPweGawMSf6fgqOTx1+yKQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2000.1", - "@angular-devkit/core": "20.0.1", - "@angular-devkit/schematics": "20.0.1", + "@angular-devkit/architect": "0.2000.4", + "@angular-devkit/core": "20.0.4", + "@angular-devkit/schematics": "20.0.4", "@inquirer/prompts": "7.5.1", "@listr2/prompt-adapter-inquirer": "2.0.22", - "@schematics/angular": "20.0.1", + "@schematics/angular": "20.0.4", "@yarnpkg/lockfile": "1.1.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", @@ -314,9 +314,9 @@ } }, "node_modules/@angular/common": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.2.tgz", - "integrity": "sha512-dqzKFL2MgPpQiaY9ZyDhGZYWEXblsqofW6czH/+HkmlNgSmDCBaY/UhNQShxNQ0KQbR1o08OWuQr29zxkY1CMA==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.5.tgz", + "integrity": "sha512-R7SQaOVYjVnrGHOq2RnuPn0pGofGVTDgy5EoHzF8ulb5MG/d7GFwCaMgfAbp3/Cw1CJzP2ZB54O8x9SMuqExyg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -325,14 +325,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "20.0.2", + "@angular/core": "20.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.2.tgz", - "integrity": "sha512-BJYXGUZaY9awYvgt0w9TDq73A1+m8W5eMRn/krWeQcfWakwTgs27BSxmhfJhD45KrMrky5yxAvGgqSfMKrLeng==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.5.tgz", + "integrity": "sha512-eHHnh+wIUC+8mfmlPnkzVfonQCA3LAbPWgYpvEQtBh0/R3cZBN6tmOxWQB8IuLu+cZ0eXS/a14mqHJp3c3u7Hg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -342,9 +342,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.0.2.tgz", - "integrity": "sha512-kVKHS5ZRadTR+rRuBl3Dsccsv/jiHXdJJYlDQwQW87afd4RtAu75P3RsSd8jaUj+7P9O4Ve4vwCZVtgOh0yxbw==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.0.5.tgz", + "integrity": "sha512-v0DSeUU7cid7jqfK9RTkyhbZGNIiOyxRYeaqZMsu4UiYGwABIanM7lOcX++OYapfWj/TEPky+5wtbV8ScqAxiw==", "license": "MIT", "dependencies": { "@babel/core": "7.27.4", @@ -364,7 +364,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", + "@angular/compiler": "20.0.5", "typescript": ">=5.8 <5.9" }, "peerDependenciesMeta": { @@ -476,9 +476,9 @@ } }, "node_modules/@angular/core": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.2.tgz", - "integrity": "sha512-z9L8WPrHTkfupHtpO6aW4KqcqigIhxcQwCaEMgXWc5WJkoiMJSfo/dk+cyiGjCfTkc5Y6DO6f6ERi0IWYWWbPA==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.5.tgz", + "integrity": "sha512-r7YQXZvKPAMUXeo3psKTZxyYJrwidTwDPrzxMX3EGqZxv0eDnMPWCxH2y0O2X4BT0Nm1iAqx3zhGrSFc0vD60Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -487,7 +487,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", + "@angular/compiler": "20.0.5", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" }, @@ -501,9 +501,9 @@ } }, "node_modules/@angular/forms": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.0.2.tgz", - "integrity": "sha512-RrQKwzFZsEDXsvesNXS4XxndEKZHC+VexIdRr1vlxx7isfvpl4htOxceW0D+Gvku1mnaS99eB/AWS50HxW3B3Q==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.0.5.tgz", + "integrity": "sha512-zoS0SaNUZBPtDfmr/edd3cHa9Z+vvPs8UXKMo9/i4YezWCskkZmW5qIJwISYJt4DHnHWoznlGBB9BQX8HgmQRw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -512,16 +512,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2", + "@angular/common": "20.0.5", + "@angular/core": "20.0.5", + "@angular/platform-browser": "20.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.0.2.tgz", - "integrity": "sha512-CUkKyuMUvRqJR5BeSDQ4gGX8z5vxRkQ0mqIq4uMXrFs/rMn7cYqfzr3rjxp0S69wsOKF4G/6pgN5xpUhnqhdgw==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.0.5.tgz", + "integrity": "sha512-ZFH1sT9+P0FmOhuMGF3qywlDaV594sHoYMetmLAqq+l0a91hJ9qYWoc5lhiaQ1/+MdHXlns/67zGeEUeSP8ssQ==", "dev": true, "license": "MIT", "engines": { @@ -529,9 +529,9 @@ } }, "node_modules/@angular/localize": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.0.2.tgz", - "integrity": "sha512-k872tsni1WhrxZNEreCrPatcs35le1LZiLYXg6iGvDmwr8K125DiI2cC6l0dSoD6b3qwP2g+BtRT5lR8V6ROrg==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.0.5.tgz", + "integrity": "sha512-3EpePYklIal1n948iAY04dUfwCKPyuvDriMBdwAzfY0Se9/wwUZrVA4R8e5kmqazfgtpAuGasgy6zoPWejzJbw==", "license": "MIT", "dependencies": { "@babel/core": "7.27.4", @@ -548,8 +548,8 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", - "@angular/compiler-cli": "20.0.2" + "@angular/compiler": "20.0.5", + "@angular/compiler-cli": "20.0.5" } }, "node_modules/@angular/localize/node_modules/@babel/core": { @@ -655,9 +655,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.2.tgz", - "integrity": "sha512-4adMQSVlwxjY9z/LEk3Q5hr4/qbM9UD9FcqbyZOt3+BL+F2GwGdKzwg6Dj4Dv0Tv8/dudNSVgHc8lIdQ4C7K1w==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.5.tgz", + "integrity": "sha512-gE3C5/ZAXdAlBFvvX/crboIy5skbV5mtxRoEULwf7xF9WJLlYzY3w+PCRHV6/Z21UJ3ikCcbaaowBx378FYhQg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -666,9 +666,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/core": "20.0.2" + "@angular/animations": "20.0.5", + "@angular/common": "20.0.5", + "@angular/core": "20.0.5" }, "peerDependenciesMeta": { "@angular/animations": { @@ -677,9 +677,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.0.2.tgz", - "integrity": "sha512-8MDGsgcxUxSldcX6HRGB5dj+xOCQ8qmx8Vog9unEBNkuPH0vqvOepqn3prdV6dM31jYfJ9JAEKeEfNZFjuWSkA==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.0.5.tgz", + "integrity": "sha512-uGkHndCWqQyhjcDziC93R5CwQBKa+Xvk0s02ia8LJwVz7iIu/bLO34vos0HM9d250W4TNZbuVFmMhJDJWCq3uQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -688,16 +688,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2" + "@angular/common": "20.0.5", + "@angular/compiler": "20.0.5", + "@angular/core": "20.0.5", + "@angular/platform-browser": "20.0.5" } }, "node_modules/@angular/router": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.0.2.tgz", - "integrity": "sha512-UyuTeoXkkZw1eFFNwrTfb1JXow6HKVdLNb3n9MhqDz+3ekdiqDH8EBaKhxYZxlcpNoa6cNbECZJYtaHy1lw38g==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.0.5.tgz", + "integrity": "sha512-GqBxrjov6p6riqDmn+hD2FWk5JSXR638/UhWCZe+XORoOmV/gWgND1HaHPa7f/UvM422yrPEkIsFNMr7bwLmkA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -706,9 +706,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2", + "@angular/common": "20.0.5", + "@angular/core": "20.0.5", + "@angular/platform-browser": "20.0.5", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -739,9 +739,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", - "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", + "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -930,12 +930,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", - "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", + "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.3" + "@babel/types": "^7.27.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -959,16 +959,16 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", - "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", + "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/parser": "^7.27.7", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", + "@babel/types": "^7.27.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -977,9 +977,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", - "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", + "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -1449,12 +1449,12 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", - "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-3.1.0.tgz", + "integrity": "sha512-8w2ciWvtNqBspFN/WVpkGEOqCEg1w3XPC/haU7pJbE/GIh4g/Nt8+2t5nOivunpsE+9TY44Ily3MBEsfxFru2A==", "license": "MIT", "dependencies": { - "axios": "1.9.0", + "axios": "1.10.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", @@ -2457,18 +2457,18 @@ } }, "node_modules/@ng-bootstrap/ng-bootstrap": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-18.0.0.tgz", - "integrity": "sha512-GeSAz4yiGq49psdte8kcf+Y562wB3jK/qKRAkh6iA32lcXmy2sfQXVAmlHdjZ3AyP+E8lf3yMwuPdSKiYcDgSg==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-19.0.0.tgz", + "integrity": "sha512-Ryd7L3VdT0zQ5+Y9uA5Kze+4FylUQ7FS04DCiFAjU3eCLxrGirhXiwpE2poMSciZi0nqXodKgKKdUSynZEYY+Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/localize": "^19.0.0", + "@angular/common": "^20.0.0", + "@angular/core": "^20.0.0", + "@angular/forms": "^20.0.0", + "@angular/localize": "^20.0.0", "@popperjs/core": "^2.11.8", "rxjs": "^6.5.3 || ^7.4.0" } @@ -3322,14 +3322,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.0.1.tgz", - "integrity": "sha512-29T9vUAjZnbXM+vImIQcdqG/ibdcfj5+pybo5cbiMSwVPVyerXgnD0HKC4dyZ34V2RFZa8cmyCLe/5bYoPQ+0g==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.0.4.tgz", + "integrity": "sha512-cQw0ATQW/GTcYo5wmzMJrKlQsafNKeL3vduV6q0rILfp8P3OnJk7CtlWf9sfZnpEo0PNu28viMts3/p7ZUS8nQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", - "@angular-devkit/schematics": "20.0.1", + "@angular-devkit/core": "20.0.4", + "@angular-devkit/schematics": "20.0.4", "jsonc-parser": "3.3.1" }, "engines": { @@ -3362,9 +3362,9 @@ } }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.4.2.tgz", - "integrity": "sha512-F2ye+n1INNhqT0MW+LfUEvTUPc/nS70vICJcxorKl7/gV9CO39+EDCw+qHNKEqvsDWk++yGVKCbzK1qLPvmC8g==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.4.3.tgz", + "integrity": "sha512-fk2zjD9117RL9BjqEwF7fwv7Q/P9yGsMV4MUJZ/DocaQJ6+3pKr+syBq1owU5Q5qGw5CUbXzm+4yJ2JVRDQeSA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3546,9 +3546,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ==", "dev": true, "license": "MIT" }, @@ -3563,13 +3563,13 @@ } }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.7.tgz", + "integrity": "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/qrcode": { @@ -3620,9 +3620,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3702,16 +3702,16 @@ } }, "node_modules/angular-gridster2": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-19.0.0.tgz", - "integrity": "sha512-82SHZzwOmGRvR77VtbpV5Eh7CoTtxLslwOVzTYB3qNQIGGFaOsS8nRAuYpZOlZpVc+n6fBz1HU0yP0icnQ9ppg==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-20.0.0.tgz", + "integrity": "sha512-c2YL0AeOV3Ca4xwmjjGl7UqL/HZBmOdj+Z7k3aAXbtarhQbWsEhu8Nh6IQIsoHeOcmrhPK0ilFlXh08xart43w==", "license": "MIT", "dependencies": { "tslib": "^2.4.0" }, "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0", + "@angular/common": "^20.0.0", + "@angular/core": "^20.0.0", "rxjs": "^7.0.0" } }, @@ -3786,9 +3786,9 @@ "peer": true }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3841,9 +3841,9 @@ "license": "ISC" }, "node_modules/bootstrap": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz", - "integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", "funding": [ { "type": "github", @@ -3860,9 +3860,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3883,9 +3883,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "funding": [ { "type": "opencollective", @@ -3902,8 +3902,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -4064,9 +4064,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", "funding": [ { "type": "opencollective", @@ -4104,9 +4104,9 @@ "license": "MIT" }, "node_modules/chart.js": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", - "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", + "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" @@ -4433,9 +4433,9 @@ } }, "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4450,9 +4450,9 @@ } }, "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4662,9 +4662,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.177", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", + "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", "license": "ISC" }, "node_modules/emoji-datasource": { @@ -4942,9 +4942,9 @@ "license": "BSD-3-Clause" }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -5346,9 +5346,9 @@ } }, "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -5420,9 +5420,9 @@ } }, "node_modules/immutable": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", - "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", "dev": true, "license": "MIT" }, @@ -6888,9 +6888,9 @@ } }, "node_modules/ordered-binary": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", - "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.0.tgz", + "integrity": "sha512-IQh2aMfMIDbPjI/8a3Edr+PiOpcsB7yo8NdW7aHWVaoR/pcDldunMvnnwbk/auPGqmKeAdxtZl7MHX/QmPwhvQ==", "dev": true, "license": "MIT", "optional": true @@ -7021,9 +7021,9 @@ } }, "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -7047,9 +7047,9 @@ } }, "node_modules/parse5/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -7201,13 +7201,13 @@ } }, "node_modules/piscina": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.0.0.tgz", - "integrity": "sha512-R+arufwL7sZvGjAhSMK3TfH55YdGOqhpKXkcwQJr432AAnJX/xxX19PA4QisrmJ+BTTfZVggaz6HexbkQq1l1Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.1.tgz", + "integrity": "sha512-9rPDIPsCwOivatEZGM8+apgM7AiTDLSnpwMmLaSmdm2PeND8bFJzZLZZxyrJjLH8Xx/MpKoVaKf+vZOWALNHbw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.x" + "node": ">=20.x" }, "optionalDependencies": { "@napi-rs/nice": "^1.0.1" @@ -7223,9 +7223,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -7538,9 +7538,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7851,9 +7851,9 @@ } }, "node_modules/socks": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", - "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", "dev": true, "license": "MIT", "dependencies": { @@ -8368,9 +8368,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true, "license": "MIT" }, diff --git a/ui/package.json b/ui/package.json index 253a3f135..67ce0b8ad 100644 --- a/ui/package.json +++ b/ui/package.json @@ -12,25 +12,25 @@ "postinstall": "patch-package" }, "dependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2", - "@angular/platform-browser": "20.0.2", - "@angular/platform-browser-dynamic": "20.0.2", - "@angular/router": "20.0.2", + "@angular/animations": "20.0.5", + "@angular/common": "20.0.5", + "@angular/compiler": "20.0.5", + "@angular/core": "20.0.5", + "@angular/forms": "20.0.5", + "@angular/localize": "20.0.5", + "@angular/platform-browser": "20.0.5", + "@angular/platform-browser-dynamic": "20.0.5", + "@angular/router": "20.0.5", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.2.0", - "@ng-bootstrap/ng-bootstrap": "18.0.0", + "@homebridge/hap-client": "3.1.0", + "@ng-bootstrap/ng-bootstrap": "19.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", "@ngx-translate/core": "16.0.4", - "ajv-keywords": "^5.1.0", - "angular-gridster2": "19.0.0", - "bootstrap": "5.3.6", - "chart.js": "4.4.9", + "ajv-keywords": "5.1.0", + "angular-gridster2": "20.0.0", + "bootstrap": "5.3.7", + "chart.js": "4.5.0", "dayjs": "1.11.13", "emoji-js": "3.8.1", "file-saver": "2.0.5", @@ -57,16 +57,16 @@ "zone.js": "0.15.1" }, "devDependencies": { - "@angular/build": "^20.0.1", - "@angular/cli": "^20.0.1", - "@angular/compiler-cli": "^20.0.1", - "@angular/language-service": "^20.0.1", + "@angular/build": "^20.0.4", + "@angular/cli": "^20.0.4", + "@angular/compiler-cli": "^20.0.5", + "@angular/language-service": "^20.0.5", "@fortawesome/fontawesome-free": "^6.7.2", "@homebridge/plugin-ui-utils": "^2.1.0", "@types/emoji-js": "^3.5.2", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.15.30", + "@types/node": "^24.0.7", "@types/qrcode": "^1.5.5", "@types/semver": "^7.7.0", "he": "^1.2.0", @@ -75,10 +75,8 @@ "typescript": "^5.8.3" }, "overrides": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2" + "@angular/animations": "20.0.5", + "@angular/common": "20.0.5", + "@angular/core": "20.0.5" } } diff --git a/ui/patches/@ng-bootstrap+ng-bootstrap+18.0.0.patch b/ui/patches/@ng-bootstrap+ng-bootstrap+18.0.0.patch deleted file mode 100644 index d552b463c..000000000 --- a/ui/patches/@ng-bootstrap+ng-bootstrap+18.0.0.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff --git a/node_modules/@ng-bootstrap/ng-bootstrap/fesm2022/ng-bootstrap.mjs b/node_modules/@ng-bootstrap/ng-bootstrap/fesm2022/ng-bootstrap.mjs -index d65de64..9a864b3 100644 ---- a/node_modules/@ng-bootstrap/ng-bootstrap/fesm2022/ng-bootstrap.mjs -+++ b/node_modules/@ng-bootstrap/ng-bootstrap/fesm2022/ng-bootstrap.mjs -@@ -1,5 +1,5 @@ - import * as i0 from '@angular/core'; --import { Injectable, inject, ElementRef, NgZone, EventEmitter, Directive, Input, Output, TemplateRef, ViewContainerRef, Component, ViewChild, ContentChild, ChangeDetectorRef, DestroyRef, ContentChildren, NgModule, ChangeDetectionStrategy, ViewEncapsulation, PLATFORM_ID, Injector, afterNextRender, LOCALE_ID, forwardRef, afterRender, ApplicationRef, EnvironmentInjector, createComponent, Attribute, ViewChildren, InjectionToken } from '@angular/core'; -+import { Injectable, inject, ElementRef, NgZone, EventEmitter, Directive, Input, Output, TemplateRef, ViewContainerRef, Component, ViewChild, ContentChild, ChangeDetectorRef, DestroyRef, ContentChildren, NgModule, ChangeDetectionStrategy, ViewEncapsulation, PLATFORM_ID, Injector, afterNextRender, LOCALE_ID, forwardRef, afterEveryRender, ApplicationRef, EnvironmentInjector, createComponent, Attribute, ViewChildren, InjectionToken } from '@angular/core'; - import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; - import { Observable, EMPTY, of, Subject, fromEvent, timer, race, BehaviorSubject, combineLatest, NEVER, zip, merge } from 'rxjs'; - import { endWith, takeUntil, filter, map, startWith, distinctUntilChanged, switchMap, take, tap, withLatestFrom, delay, mergeMap, skip, finalize } from 'rxjs/operators'; -@@ -4133,7 +4133,7 @@ class NgbInputDatepicker { - placement: this.placement, - updatePopperOptions: (options) => this.popperOptions(addPopperOffset([0, 2])(options)), - }); -- this._afterRenderRef = afterRender({ -+ this._afterRenderRef = afterEveryRender({ - mixedReadWrite: () => { - this._positioning.update(); - }, -@@ -6449,7 +6449,7 @@ class NgbDropdown { - updatePopperOptions: (options) => this.popperOptions(addPopperOffset([0, 2])(options)), - }); - this._applyPlacementClasses(); -- this._afterRenderRef = afterRender({ -+ this._afterRenderRef = afterEveryRender({ - write: () => { - this._positionMenu(); - }, -@@ -9252,7 +9252,7 @@ class NgbPopover { - // This update is required for correct arrow placement - this._positioning.update(); - }); -- this._afterRenderRef = afterRender({ -+ this._afterRenderRef = afterEveryRender({ - mixedReadWrite: () => { - this._positioning.update(); - }, -@@ -11644,7 +11644,7 @@ class NgbTooltip { - // This update is required for correct arrow placement - this._positioning.update(); - }); -- this._afterRenderRef = afterRender({ -+ this._afterRenderRef = afterEveryRender({ - mixedReadWrite: () => { - this._positioning.update(); - }, -@@ -12237,7 +12237,7 @@ class NgbTypeahead { - placement: this.placement, - updatePopperOptions: (options) => this.popperOptions(addPopperOffset([0, 2])(options)), - }); -- this._afterRenderRef = afterRender({ -+ this._afterRenderRef = afterEveryRender({ - mixedReadWrite: () => { - this._positioning.update(); - }, diff --git a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html b/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html index e80365cc1..7637d25ab 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html +++ b/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html @@ -12,7 +12,7 @@ + + @if (showFields.security) { +
      +
    • + + {{ 'settings.security.auth' | translate }}
      + {{ 'settings.security.auth_desc' | translate }} +
      +
      +
      + + +
      + @if (uiAuthIsSaving) { + + } +
      +
    • + @if (uiAuthFormControl.value) { +
    • + + {{ 'settings.startup.session' | translate }}
      + {{ 'settings.startup.session_desc' | translate }} +
      +
      + + @if (uiSessionTimeoutIsSaving) { + + } +
      +
    • + } +
    • + + {{ 'settings.security.https' | translate }}
      + {{ 'settings.security.https_desc' | translate }} +
      +
      + +
      +
    • + @if (this.uiSslTypeFormControl.value === 'keycert') { +
    • + {{ 'settings.security.key' | translate }} +
      + + @if (uiSslKeyIsSaving) { + + } +
      +
    • +
    • + {{ 'settings.security.cert' | translate }} +
      + + @if (uiSslCertIsSaving) { + + } +
      +
    • + } @if (this.uiSslTypeFormControl.value === 'pfx') { +
    • + {{ 'settings.security.pfx' | translate }} +
      + + @if (uiSslPfxIsSaving) { + + } +
      +
    • +
    • + {{ 'settings.security.pass' | translate }} +
      + + @if (uiSslPassphraseIsSaving) { + + } +
      +
    • + } +
    • + + {{ 'settings.security.ui_control' | translate }}
      + {{ 'settings.security.ui_control_desc' | translate }} +
      + +
    • +
    } -
  • - - {{ 'settings.security.ui_control' | translate }}
    - {{ 'settings.security.ui_control_desc' | translate }} -
    - -
  • - -} + @if ($settings.env.serviceMode) { diff --git a/ui/src/app/modules/settings/settings.component.ts b/ui/src/app/modules/settings/settings.component.ts index 3004318ee..b447fdf0a 100644 --- a/ui/src/app/modules/settings/settings.component.ts +++ b/ui/src/app/modules/settings/settings.component.ts @@ -10,6 +10,7 @@ import { firstValueFrom } from 'rxjs' import { debounceTime } from 'rxjs/operators' import { ApiService } from '@/app/core/api.service' +import { SpinnerComponent } from '@/app/core/components/spinner/spinner.component' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' @@ -65,6 +66,7 @@ interface NetworkAdapterSelected { ReactiveFormsModule, TitleCasePipe, TranslatePipe, + SpinnerComponent, ], animations: [ trigger('fadeInOut', [ @@ -99,6 +101,7 @@ export class SettingsComponent implements OnInit { cache: true, } + public loading = true public isHbV2 = false public showAvahiMdnsOption = false public showResolvedMdnsOption = false @@ -346,6 +349,8 @@ export class SettingsComponent implements OnInit { this.hbLinuxRestartFormControl.valueChanges .pipe(debounceTime(1500)) .subscribe((value: string) => this.hbLinuxRestartSave(value)) + + this.loading = false } async initServiceModeForm() { From 1dbee4cd6c72c6ce6a1927f1a8bfe775a1b11ef9 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Tue, 1 Jul 2025 22:09:04 +0100 Subject: [PATCH 34/40] bring runner list for actions up-to-date with github availability --- .github/workflows/beta-release.yml | 2 +- .github/workflows/validate.yml | 5 ++--- CHANGELOG.md | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/beta-release.yml b/.github/workflows/beta-release.yml index 6e154bdcc..0df3bd798 100644 --- a/.github/workflows/beta-release.yml +++ b/.github/workflows/beta-release.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] + os: [ubuntu-24.04, ubuntu-22.04, macos-15, macos-14, macos-13, windows-2025, windows-2022] uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 5ebdb56b1..65e691bd5 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] + os: [ubuntu-24.04, ubuntu-22.04, macos-15, macos-14, macos-13, windows-2025, windows-2022] uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: @@ -38,8 +38,7 @@ jobs: strategy: fail-fast: false matrix: - os: - [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] + os: [ubuntu-24.04, ubuntu-22.04, macos-15, macos-14, macos-13, windows-2025, windows-2022] node-version: [18.x, 20.x, 22.x] runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 02f4f3213..a7eb0e0de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - remove bridge id from control blacklist when removing a bridge - fix regex for blacklist in config schema file +- bring runner list for actions up-to-date with github availability ### Homebridge Dependencies From fe090cdde2762310ca1e895ef63c3831f93c3901 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 2 Jul 2025 08:20:06 +0100 Subject: [PATCH 35/40] show both version notes and full changelog beforehand on plugin update --- CHANGELOG.md | 1 + src/modules/plugins/plugins.service.ts | 67 +++++----- test/e2e/plugins.e2e-spec.ts | 25 +++- test/e2e/status.e2e-spec.ts | 2 +- ui/package-lock.json | 16 +-- .../manage-plugin.component.html | 88 ++++++++++---- .../manage-plugin.component.scss | 36 ++++-- .../manage-plugin/manage-plugin.component.ts | 115 ++++++++++++------ .../manage-plugins/manage-plugins.service.ts | 6 +- .../manage-version.component.html | 4 - .../plugin-card/plugin-card.component.html | 2 +- .../update-info-widget.component.html | 4 +- ui/src/i18n/bg.json | 9 +- ui/src/i18n/ca.json | 9 +- ui/src/i18n/cs.json | 9 +- ui/src/i18n/de.json | 9 +- ui/src/i18n/en.json | 9 +- ui/src/i18n/es.json | 9 +- ui/src/i18n/fi.json | 9 +- ui/src/i18n/fr.json | 9 +- ui/src/i18n/he.json | 9 +- ui/src/i18n/hu.json | 9 +- ui/src/i18n/id.json | 9 +- ui/src/i18n/it.json | 9 +- ui/src/i18n/ja.json | 9 +- ui/src/i18n/ko.json | 9 +- ui/src/i18n/mk.json | 9 +- ui/src/i18n/nl.json | 9 +- ui/src/i18n/no.json | 9 +- ui/src/i18n/pl.json | 9 +- ui/src/i18n/pt-BR.json | 9 +- ui/src/i18n/pt.json | 9 +- ui/src/i18n/ru.json | 9 +- ui/src/i18n/sl.json | 9 +- ui/src/i18n/sv.json | 9 +- ui/src/i18n/th.json | 9 +- ui/src/i18n/tr.json | 9 +- ui/src/i18n/uk.json | 9 +- ui/src/i18n/zh-CN.json | 9 +- ui/src/i18n/zh-TW.json | 9 +- ui/src/scss/themes/themes-dark.scss | 10 ++ ui/src/scss/themes/themes-light.scss | 14 +++ 42 files changed, 488 insertions(+), 154 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7eb0e0de..f19ccbe86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - small tweaks to various accessory status tiles - revert display of triggered state in security control modal - show spinner on settings page until all settings are loaded +- show both version notes and full changelog beforehand on plugin update ### Other Changes diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index 3058d5e44..801a6fbe3 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -1060,6 +1060,34 @@ export class PluginsService { * @param pluginName */ public async getPluginChangeLog(pluginName: string) { + let latestVersion: string | null = null + try { + const pkg: INpmRegistryModule = (await firstValueFrom(( + this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(pluginName).replace(/%40/g, '@')}`)), + )).data + + latestVersion = pkg['dist-tags'] ? pkg['dist-tags'].latest : null + } catch (e) { + throw new NotFoundException() + } + + if (pluginName === 'homebridge') { + // Different flow for homebridge itself + try { + const data = await firstValueFrom(this.httpService.get('https://raw.githubusercontent.com/homebridge/homebridge/refs/heads/latest/CHANGELOG.md')) + + return { + changelog: data.data, + latestVersion, + } + } catch { + return { + changelog: null, + latestVersion, + } + } + } + await this.getInstalledPlugins() const plugin = this.installedPlugins.find(x => x.name === pluginName) if (!plugin) { @@ -1068,12 +1096,9 @@ export class PluginsService { const changeLog = resolve(plugin.installPath, plugin.name, 'CHANGELOG.md') - if (await pathExists(changeLog)) { - return { - changelog: await readFile(changeLog, 'utf8'), - } - } else { - throw new NotFoundException() + return { + changelog: (await pathExists(changeLog)) ? await readFile(changeLog, 'utf8') : null, + latestVersion, } } @@ -1107,36 +1132,6 @@ export class PluginsService { match = bugsMatch } - // Special case for beta npm tags for homebridge, homebridge ui and all plugins - const version = parse(plugin.latestVersion) - const tag = version.prerelease[0]?.toString() - - if (tag) { - let branch: string | undefined - - if (['homebridge-config-ui-x', 'homebridge'].includes(plugin.name)) { - // If loading a homebridge/ui beta returned pre-defined help text - // Query the list of branches for the repo, if the request doesn't work it doesn't matter too much - try { - // Find the first branch that starts with "beta" - branch = (await firstValueFrom(this.httpService.get(`https://api.github.com/repos/homebridge/${plugin.name}/branches`))) - .data - .find((b: any) => b.name.startsWith(`${tag}-`)) - ?.name - } catch (e) { - this.logger.error(`Failed to get list of branches from GitHub as ${e.message}.`) - } - } - - return { - name: `v${plugin.latestVersion}`, - changelog: `Thank you for helping improve ${plugin.displayName || `\`${plugin.name}\``} by testing a beta version.\n\n` - + 'You can use the Homebridge UI at any time to revert back to the stable version.\n\n' - + `Please remember this **${tag}** version is a pre-release, and report any issues to the GitHub repository page:\n` - + `- https://github.com/${repoMatch[1]}/${repoMatch[2]}/issues${branch ? `\n\nSee the commit history for recent changes:\n- https://github.com/${repoMatch[1]}/${repoMatch[2]}/commits/${branch}` : ''}`, - } - } - try { const release = (await firstValueFrom(this.httpService.get(`https://api.github.com/repos/${match[1]}/${match[2]}/releases/latest`))).data return { diff --git a/test/e2e/plugins.e2e-spec.ts b/test/e2e/plugins.e2e-spec.ts index 4f50c83a2..57ecf541e 100644 --- a/test/e2e/plugins.e2e-spec.ts +++ b/test/e2e/plugins.e2e-spec.ts @@ -10,7 +10,9 @@ import { HttpService } from '@nestjs/axios' import { ValidationPipe } from '@nestjs/common' import { FastifyAdapter } from '@nestjs/platform-fastify' import { Test } from '@nestjs/testing' +import { AxiosResponse, InternalAxiosRequestConfig } from 'axios' import { copy, remove } from 'fs-extra' +import { of } from 'rxjs' import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import { AuthModule } from '../../src/core/auth/auth.module' @@ -277,6 +279,25 @@ describe('PluginController (e2e)', () => { }) it('GET /plugins/changelog/:plugin-name', async () => { + // Mock NPM registry response to return a valid latest version + const data = { + '_id': 'homebridge-mock-plugin', + 'name': 'homebridge-mock-plugin', + 'dist-tags': { + latest: '1.0.0', + }, + } + + const response: AxiosResponse = { + data, + headers: {}, + config: { url: 'https://registry.npmjs.org/homebridge-mock-plugin' } as InternalAxiosRequestConfig, + status: 200, + statusText: 'OK', + } + + vi.spyOn(httpService, 'get').mockImplementationOnce(() => of(response) as any) + const res = await app.inject({ method: 'GET', path: '/plugins/changelog/homebridge-mock-plugin', @@ -285,8 +306,10 @@ describe('PluginController (e2e)', () => { }, }) + const json = res.json() expect(res.statusCode).toBe(200) - expect(res.json()).toHaveProperty('changelog') + expect(json).toHaveProperty('changelog') + expect(json.latestVersion).toBe('1.0.0') }) it('GET /plugins/changelog/:plugin-name (changelog missing)', async () => { diff --git a/test/e2e/status.e2e-spec.ts b/test/e2e/status.e2e-spec.ts index cc4467113..2640bb08f 100644 --- a/test/e2e/status.e2e-spec.ts +++ b/test/e2e/status.e2e-spec.ts @@ -165,7 +165,7 @@ describe('StatusController (e2e)', () => { } vi.spyOn(httpService, 'get') - .mockImplementationOnce(() => throwError(response)) + .mockImplementationOnce(() => throwError(() => response)) const res = await app.inject({ method: 'GET', diff --git a/ui/package-lock.json b/ui/package-lock.json index cf03446fb..227f14eba 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -265,9 +265,9 @@ } }, "node_modules/@angular/cdk": { - "version": "20.0.4", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.4.tgz", - "integrity": "sha512-NCUuw0qQXwawLsT14JHApNB9or3XGs7D1pWXlOIix/fKqzHVfi4un9xHmpjH2Q1uCiwonuak7fDof8B+IXhbug==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.5.tgz", + "integrity": "sha512-WhJ1I/ib/Za0qjWkSzMYV0gM8NOWrtOcZ2TYZ4aYFsjd8E13rGhxOez0DWt2sN3vfjAc1iWMmGGbNZrkp98adg==", "license": "MIT", "peer": true, "dependencies": { @@ -8313,15 +8313,15 @@ "license": "0BSD" }, "node_modules/tuf-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", - "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.1.0.tgz", + "integrity": "sha512-3T3T04WzowbwV2FDiGXBbr81t64g1MUGGJRgT4x5o97N+8ArdhVCAF9IxFrxuSJmM3E5Asn7nKHkao0ibcZXAg==", "dev": true, "license": "MIT", "dependencies": { "@tufjs/models": "3.0.1", - "debug": "^4.3.6", - "make-fetch-happen": "^14.0.1" + "debug": "^4.4.1", + "make-fetch-happen": "^14.0.3" }, "engines": { "node": "^18.17.0 || >=20.5.0" diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html index a571de6da..89ffe48a9 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html @@ -9,16 +9,14 @@ (click)="$activeModal.dismiss('Dismiss')" > - + @if (actionComplete) { } @if (!onlineUpdateOk) { - } @if (showReleaseNotes && !actionComplete && onlineUpdateOk) { + } @if (releaseNotesShow && !actionComplete && onlineUpdateOk) {