diff --git a/CHANGELOG.md b/CHANGELOG.md index 786ca6264..87f8d1238 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. ## BETA +### UI Changes + +- add plugin list modal for updating to hb v2.0 + ### Other Changes - relocate `disable-plugin` component to `core/plugins` module diff --git a/package-lock.json b/package-lock.json index f77d9d631..3bf9d9754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5102,9 +5102,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.1.tgz", - "integrity": "sha512-SY9oUuTMr6aWoJggUS40LtMjsRzJPB5ZT7F432xZIHK3EfHF+8i48GbUBpwanrtlL9l1gILNTHK9o8gEhYLcKA==", + "version": "50.3.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.2.tgz", + "integrity": "sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/ui/package-lock.json b/ui/package-lock.json index 61b9ae9d2..531c9518b 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -6431,13 +6431,13 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", "devOptional": true, "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" diff --git a/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.html b/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.html new file mode 100644 index 000000000..677cb8a76 --- /dev/null +++ b/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.html @@ -0,0 +1,84 @@ + diff --git a/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.ts b/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.ts new file mode 100644 index 000000000..1d2ac39ab --- /dev/null +++ b/ui/src/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component.ts @@ -0,0 +1,56 @@ +import { ApiService } from '@/app/core/api.service' +import { SettingsService } from '@/app/core/settings.service' +import { Component, OnInit } from '@angular/core' +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { TranslateService } from '@ngx-translate/core' +import { ToastrService } from 'ngx-toastr' +import { firstValueFrom } from 'rxjs' + +@Component({ + templateUrl: './hb-update-confirm.component.html', +}) +export class HbUpdateConfirmComponent implements OnInit { + public loading = true + public installedPlugins: any = [] + public allPluginsSupported = true + + constructor( + public $activeModal: NgbActiveModal, + private $api: ApiService, + public $settings: SettingsService, + private $toastr: ToastrService, + private $translate: TranslateService, + ) {} + + ngOnInit() { + this.loadInstalledPlugins() + } + + async loadInstalledPlugins() { + this.installedPlugins = [] + this.loading = true + const homebridgeVersion = this.$settings.env.homebridgeVersion.split('.')[0] + + try { + const installedPlugins = await firstValueFrom(this.$api.get('/plugins')) + this.installedPlugins = installedPlugins + .filter((x: any) => x.name !== 'homebridge-config-ui-x') + .map((x: any) => { + const hbEngines = x.engines?.homebridge?.split('||').map((x: string) => x.trim()) || [] + const hb2Ready = homebridgeVersion === '2' ? 'hide' : hbEngines.some((x: string) => (x.startsWith('^2') || x.startsWith('>=2'))) ? 'supported' : 'unknown' + if (hb2Ready === 'unknown') { + this.allPluginsSupported = false + } + return { + ...x, + hb2Ready, + } + }) + + this.loading = false + } catch (error) { + console.error(error) + this.$toastr.error(this.$translate.instant('plugins.toast_failed_to_load_plugins'), this.$translate.instant('toast.title_error')) + } + } +} 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 682340940..3531ed106 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,5 +1,6 @@ import { ApiService } from '@/app/core/api.service' import { RestartHomebridgeComponent } from '@/app/core/components/restart-homebridge/restart-homebridge.component' +import { HbUpdateConfirmComponent } from '@/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component' import { PluginLogsComponent } from '@/app/core/manage-plugins/plugin-logs/plugin-logs.component' import { SettingsService } from '@/app/core/settings.service' import { IoNamespace, WsService } from '@/app/core/ws.service' @@ -199,25 +200,47 @@ export class ManagePluginComponent implements OnInit, OnDestroy { }) } - upgradeHomebridge() { - this.io.request('homebridge-update', { - version: this.targetVersion, - termCols: this.term.cols, - termRows: this.term.rows, - }).subscribe({ - next: () => { - this.$activeModal.close() - this.$modal.open(RestartHomebridgeComponent, { - size: 'lg', - backdrop: 'static', - }) - }, - error: (error) => { - this.actionFailed = true - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) + async upgradeHomebridge() { + let res = 'update' + + // Only want to show this modal updating from existing version <2 to 2 + // This is just some temporary not-so-great logic to determine if the user is updating from <2 to 2 + if ( + Number(this.installedVersion.split('.')[0]) < 2 + && ['2', 'alpha', 'beta'].includes(this.targetVersion.split('.')[0]) + ) { + const ref = this.$modal.open(HbUpdateConfirmComponent, { + size: 'lg', + backdrop: 'static', + }) + res = await ref.result + } + + if (res === 'update') { + // Continue selected, so update homebridge + this.io.request('homebridge-update', { + version: this.targetVersion, + termCols: this.term.cols, + termRows: this.term.rows, + }).subscribe({ + next: () => { + this.$activeModal.close() + this.$modal.open(RestartHomebridgeComponent, { + size: 'lg', + backdrop: 'static', + }) + }, + error: (error) => { + this.actionFailed = true + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.$activeModal.close() + }, + }) + } else { + // Modal dismissed, also close the update modal + this.$activeModal.close() + } } async getChangeLog(): Promise { diff --git a/ui/src/app/core/manage-plugins/manage-plugins.module.ts b/ui/src/app/core/manage-plugins/manage-plugins.module.ts index df7d3707b..3668408b7 100644 --- a/ui/src/app/core/manage-plugins/manage-plugins.module.ts +++ b/ui/src/app/core/manage-plugins/manage-plugins.module.ts @@ -2,6 +2,7 @@ import { CoreModule } from '@/app/core/core.module' import { CustomPluginsModule } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.module' import { DisablePluginComponent } from '@/app/core/manage-plugins/disable-plugin/disable-plugin.component' import { DonateComponent } from '@/app/core/manage-plugins/donate/donate.component' +import { HbUpdateConfirmComponent } from '@/app/core/manage-plugins/hb-update-confirm/hb-update-confirm.component' import { InterpolateMdPipe } from '@/app/core/manage-plugins/interpolate-md.pipe' import { ManagePluginComponent } from '@/app/core/manage-plugins/manage-plugin/manage-plugin.component' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' @@ -35,6 +36,7 @@ import { MonacoEditorModule } from 'ngx-monaco-editor-v2' DonateComponent, ResetAccessoriesComponent, DisablePluginComponent, + HbUpdateConfirmComponent, ], imports: [ CommonModule, diff --git a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.html b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.html index 5f3f2e7f2..c900666a9 100644 --- a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.html +++ b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.html @@ -20,7 +20,7 @@ > @@ -112,7 +112,7 @@
{{ prettyDisplayName }}
class="fas fa-fw fa-lg ms-3" *ngIf="plugin.installedVersion && !plugin.updateAvailable && plugin.isConfigured && plugin.hasChildBridges && !childBridgeRestartInProgress && !hasUnpairedChildBridges && childBridgeStatus !== 'ok' && !plugin.disabled" [ngClass]="{ - 'fa-bridge-circle-exclamation orange-text': childBridgeStatus === 'pending', + 'fa-bridge-circle-exclamation yellow-text': childBridgeStatus === 'pending', 'fa-bridge-circle-xmark red-text': childBridgeStatus === 'down' }" > diff --git a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts index 854760a56..7be1c2c61 100644 --- a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts +++ b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts @@ -242,7 +242,7 @@ export class PluginCardComponent implements OnInit { } else { ref.componentInstance.subtitle = `${this.plugin.displayName || this.plugin.name} might not be ready for Homebridge v2.0` ref.componentInstance.message = 'The developer has not specifically marked your installed version of the plugin as compatible with Homebridge v2.0, but it may still work.' - ref.componentInstance.faIconClass = 'fa-question-circle orange-text' + ref.componentInstance.faIconClass = 'fa-question-circle yellow-text' } ref.componentInstance.ctaButtonLabel = this.$translate.instant('form.button_more_info') ref.componentInstance.ctaButtonLink = 'https://github.com/homebridge/homebridge/wiki/Updating-To-Homebridge-v2.0' diff --git a/ui/src/scss/base/layout.scss b/ui/src/scss/base/layout.scss index 0e36c3eae..ad2177788 100644 --- a/ui/src/scss/base/layout.scss +++ b/ui/src/scss/base/layout.scss @@ -29,17 +29,17 @@ a:focus { .green-text, .green-text a { - color: #00c128 !important; + color: #4caf50 !important; } .red-text, .red-text a { - color: #ff0000 !important; + color: #f44336 !important; } .yellow-text, .yellow-text a { - color: #ffa000 !important; + color: #ff9800 !important; } .cyan-text,