From 76271b1fa081ab9015eb125b154ff0d1d88549e6 Mon Sep 17 00:00:00 2001 From: Miles Robinson Date: Tue, 28 Jan 2025 15:26:24 -0500 Subject: [PATCH] Use new component in Excluded domains settings. Changing to new component necessitates modifying form to use ReactiveForms conventions. To handle this change, the deletable/uneditable domain state and new form control state are managed separately, including clearing the form state on save. Fields which compute vaules from the former state should now compute both values (see domain count); [formGroup], formArrayName, formControlName all necessary directives/properties on form and children. --- .../settings/excluded-domains.component.html | 62 ++++++++++--------- .../settings/excluded-domains.component.ts | 37 ++++++++--- 2 files changed, 64 insertions(+), 35 deletions(-) diff --git a/apps/browser/src/autofill/popup/settings/excluded-domains.component.html b/apps/browser/src/autofill/popup/settings/excluded-domains.component.html index e3b6bf5f802..dd18fd59cfd 100644 --- a/apps/browser/src/autofill/popup/settings/excluded-domains.component.html +++ b/apps/browser/src/autofill/popup/settings/excluded-domains.component.html @@ -14,19 +14,36 @@

{{ "domainsTitle" | i18n }}

- {{ excludedDomainsState?.length || 0 }} + {{ + excludedDomainsState?.length + domainForms?.value?.length + }}
- - - + +
{{ domain }}
+
+ +
+
+ - - {{ - "websiteItemLabel" | i18n: i + 1 - }} + + {{ "websiteItemLabel" | i18n: i + fieldsEditThreshold + 1 }} {{ "domainsTitle" | i18n }} name="excludedDomain{{ i }}" type="text" (change)="fieldChange()" - [(ngModel)]="excludedDomainsState[i]" + formControlName="{{ i }}" /> -
{{ domain }}
-
- - - - + +
+ +
diff --git a/apps/browser/src/autofill/popup/settings/excluded-domains.component.ts b/apps/browser/src/autofill/popup/settings/excluded-domains.component.ts index 7d429bfe4f0..77d1712d3db 100644 --- a/apps/browser/src/autofill/popup/settings/excluded-domains.component.ts +++ b/apps/browser/src/autofill/popup/settings/excluded-domains.component.ts @@ -5,9 +5,15 @@ import { ElementRef, OnDestroy, AfterViewInit, - ViewChildren, + ViewChildren, OnInit, } from "@angular/core"; -import { FormsModule } from "@angular/forms"; +import { + FormsModule, + ReactiveFormsModule, + FormBuilder, + FormGroup, + FormArray, +} from "@angular/forms"; import { RouterModule } from "@angular/router"; import { Subject, takeUntil } from "rxjs"; @@ -45,6 +51,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co CommonModule, FormFieldModule, FormsModule, + ReactiveFormsModule, IconButtonModule, ItemModule, JslibModule, @@ -59,7 +66,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co TypographyModule, ], }) -export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { +export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy, OnInit { @ViewChildren("uriInput") uriInputElements: QueryList> = new QueryList(); @@ -68,6 +75,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { isLoading = false; excludedDomainsState: string[] = []; storedExcludedDomains: string[] = []; + domainListForm: FormGroup; // How many fields should be non-editable before editable fields fieldsEditThreshold: number = 0; @@ -77,10 +85,21 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { private domainSettingsService: DomainSettingsService, private i18nService: I18nService, private toastService: ToastService, + private formBuilder: FormBuilder, ) { this.accountSwitcherEnabled = enableAccountSwitching(); } + ngOnInit() { + this.domainListForm = this.formBuilder.group({ + domains: this.formBuilder.array([]), + }); + } + + get domainForms() { + return this.domainListForm.get("domains") as FormArray; + } + async ngAfterViewInit() { this.domainSettingsService.neverDomains$ .pipe(takeUntil(this.destroy$)) @@ -117,8 +136,7 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { } async addNewDomain() { - // add empty field to the Domains list interface - this.excludedDomainsState.push(""); + this.domainForms.push(this.formBuilder.control(null)); await this.fieldChange(); } @@ -148,7 +166,11 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { this.isLoading = true; const newExcludedDomainsSaveState: NeverDomains = {}; - const uniqueExcludedDomains = new Set(this.excludedDomainsState); + + const uniqueExcludedDomains = new Set([ + ...this.excludedDomainsState, + ...this.domainForms.value, + ]); for (const uri of uniqueExcludedDomains) { if (uri && uri !== "") { @@ -194,13 +216,14 @@ export class ExcludedDomainsComponent implements AfterViewInit, OnDestroy { title: "", variant: "success", }); + + this.domainForms.clear(); } catch { this.toastService.showToast({ message: this.i18nService.t("unexpectedError"), title: "", variant: "error", }); - // Don't reset via `handleStateUpdate` to preserve input values this.isLoading = false; }