1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-27 18:13:29 +00:00

Deprecated JslibModule (#19186)

Deprecates the JslibModule and removes unused pipes and directives.
This commit is contained in:
Oscar Hinton
2026-02-26 17:08:22 +01:00
committed by GitHub
parent aa918c3163
commit 3092b4bcf7
7 changed files with 8 additions and 237 deletions

View File

@@ -1,32 +0,0 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Directive, ElementRef, OnDestroy, OnInit } from "@angular/core";
import { NgControl } from "@angular/forms";
import { Subscription } from "rxjs";
@Directive({
selector: "[appA11yInvalid]",
standalone: false,
})
export class A11yInvalidDirective implements OnDestroy, OnInit {
private sub: Subscription;
constructor(
private el: ElementRef<HTMLInputElement>,
private formControlDirective: NgControl,
) {}
ngOnInit() {
this.sub = this.formControlDirective.control.statusChanges.subscribe((status) => {
if (status === "INVALID") {
this.el.nativeElement.setAttribute("aria-invalid", "true");
} else if (status === "VALID") {
this.el.nativeElement.setAttribute("aria-invalid", "false");
}
});
}
ngOnDestroy() {
this.sub?.unsubscribe();
}
}

View File

@@ -1,32 +0,0 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Directive, ElementRef, HostListener, Input } from "@angular/core";
import { ClientType } from "@bitwarden/common/enums";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@Directive({
selector: "[appCopyText]",
standalone: false,
})
export class CopyTextDirective {
constructor(
private el: ElementRef,
private platformUtilsService: PlatformUtilsService,
) {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input("appCopyText") copyText: string;
@HostListener("copy") onCopy() {
if (window == null) {
return;
}
const timeout = this.platformUtilsService.getClientType() === ClientType.Desktop ? 100 : 0;
setTimeout(() => {
this.platformUtilsService.copyToClipboard(this.copyText, { window: window });
}, timeout);
}
}

View File

@@ -1,25 +0,0 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Directive, ElementRef, HostListener, Input } from "@angular/core";
@Directive({
selector: "[appFallbackSrc]",
standalone: false,
})
export class FallbackSrcDirective {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input("appFallbackSrc") appFallbackSrc: string;
/** Only try setting the fallback once. This prevents an infinite loop if the fallback itself is missing. */
private tryFallback = true;
constructor(private el: ElementRef) {}
@HostListener("error") onError() {
if (this.tryFallback) {
this.el.nativeElement.src = this.appFallbackSrc;
this.tryFallback = false;
}
}
}

View File

@@ -1,57 +0,0 @@
import { Directive, ElementRef, forwardRef, HostListener, Input, Renderer2 } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
// ref: https://juristr.com/blog/2018/02/ng-true-value-directive/
@Directive({
selector: "input[type=checkbox][appTrueFalseValue]",
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrueFalseValueDirective),
multi: true,
},
],
standalone: false,
})
export class TrueFalseValueDirective implements ControlValueAccessor {
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() trueValue: boolean | string = true;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() falseValue: boolean | string = false;
constructor(
private elementRef: ElementRef,
private renderer: Renderer2,
) {}
@HostListener("change", ["$event"])
onHostChange(ev: any) {
this.propagateChange(ev.target.checked ? this.trueValue : this.falseValue);
}
writeValue(obj: any): void {
if (obj === this.trueValue) {
this.renderer.setProperty(this.elementRef.nativeElement, "checked", true);
} else {
this.renderer.setProperty(this.elementRef.nativeElement, "checked", false);
}
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
/* nothing */
}
setDisabledState?(isDisabled: boolean): void {
/* nothing */
}
private propagateChange = (_: any) => {
/* nothing */
};
}

View File

@@ -26,11 +26,8 @@ import {
import { TwoFactorIconComponent } from "./auth/components/two-factor-icon.component";
import { NotPremiumDirective } from "./billing/directives/not-premium.directive";
import { A11yInvalidDirective } from "./directives/a11y-invalid.directive";
import { ApiActionDirective } from "./directives/api-action.directive";
import { BoxRowDirective } from "./directives/box-row.directive";
import { CopyTextDirective } from "./directives/copy-text.directive";
import { FallbackSrcDirective } from "./directives/fallback-src.directive";
import { IfFeatureDirective } from "./directives/if-feature.directive";
import { InputStripSpacesDirective } from "./directives/input-strip-spaces.directive";
import { InputVerbatimDirective } from "./directives/input-verbatim.directive";
@@ -38,18 +35,23 @@ import { LaunchClickDirective } from "./directives/launch-click.directive";
import { StopClickDirective } from "./directives/stop-click.directive";
import { StopPropDirective } from "./directives/stop-prop.directive";
import { TextDragDirective } from "./directives/text-drag.directive";
import { TrueFalseValueDirective } from "./directives/true-false-value.directive";
import { CreditCardNumberPipe } from "./pipes/credit-card-number.pipe";
import { PluralizePipe } from "./pipes/pluralize.pipe";
import { SearchCiphersPipe } from "./pipes/search-ciphers.pipe";
import { SearchPipe } from "./pipes/search.pipe";
import { UserNamePipe } from "./pipes/user-name.pipe";
import { UserTypePipe } from "./pipes/user-type.pipe";
import { EllipsisPipe } from "./platform/pipes/ellipsis.pipe";
import { FingerprintPipe } from "./platform/pipes/fingerprint.pipe";
import { I18nPipe } from "./platform/pipes/i18n.pipe";
import { IconComponent } from "./vault/components/icon.component";
/**
* @deprecated In 95% of cases you want I18nPipe from `@bitwarden/ui-common`. In the other 5%
* directly import the relevant directive/pipe/component. If you need one of the non standalone
* pipes/directives/components, make it standalone and import directly.
*
* This module is overly large and adds many unrelated modules to your dependency tree.
* https://angular.dev/guide/ngmodules/overview recommends not using `NgModule`s for new code.
*/
@NgModule({
imports: [
ToastModule.forRoot({
@@ -82,57 +84,45 @@ import { IconComponent } from "./vault/components/icon.component";
AutofocusDirective,
],
declarations: [
A11yInvalidDirective,
ApiActionDirective,
BoxRowDirective,
CopyTextDirective,
CreditCardNumberPipe,
EllipsisPipe,
FallbackSrcDirective,
I18nPipe,
IconComponent,
InputStripSpacesDirective,
InputVerbatimDirective,
NotPremiumDirective,
SearchCiphersPipe,
SearchPipe,
StopClickDirective,
StopPropDirective,
TrueFalseValueDirective,
LaunchClickDirective,
UserNamePipe,
UserTypePipe,
IfFeatureDirective,
FingerprintPipe,
TwoFactorIconComponent,
],
exports: [
A11yInvalidDirective,
A11yTitleDirective,
ApiActionDirective,
AutofocusDirective,
ToastModule,
BoxRowDirective,
CopyTextDirective,
CreditCardNumberPipe,
EllipsisPipe,
FallbackSrcDirective,
I18nPipe,
IconComponent,
InputStripSpacesDirective,
InputVerbatimDirective,
NotPremiumDirective,
SearchCiphersPipe,
SearchPipe,
StopClickDirective,
StopPropDirective,
TrueFalseValueDirective,
CopyClickDirective,
LaunchClickDirective,
UserNamePipe,
UserTypePipe,
IfFeatureDirective,
FingerprintPipe,
TwoFactorIconComponent,
TextDragDirective,
],
@@ -143,7 +133,6 @@ import { IconComponent } from "./vault/components/icon.component";
SearchPipe,
UserNamePipe,
UserTypePipe,
FingerprintPipe,
PluralizePipe,
],
})

View File

@@ -1,42 +0,0 @@
import { Pipe, PipeTransform } from "@angular/core";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@Pipe({
name: "searchCiphers",
standalone: false,
})
export class SearchCiphersPipe implements PipeTransform {
transform(ciphers: CipherView[], searchText: string, deleted = false): CipherView[] {
if (ciphers == null || ciphers.length === 0) {
return [];
}
if (searchText == null || searchText.length < 2) {
return ciphers.filter((c) => {
return deleted !== c.isDeleted;
});
}
searchText = searchText.trim().toLowerCase();
return ciphers.filter((c) => {
if (deleted !== c.isDeleted) {
return false;
}
if (c.name != null && c.name.toLowerCase().indexOf(searchText) > -1) {
return true;
}
if (searchText.length >= 8 && c.id.startsWith(searchText)) {
return true;
}
if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(searchText) > -1) {
return true;
}
if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(searchText) > -1) {
return true;
}
return false;
});
}
}

View File

@@ -1,30 +0,0 @@
import { Pipe } from "@angular/core";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { KeyService } from "@bitwarden/key-management";
@Pipe({
name: "fingerprint",
standalone: false,
})
export class FingerprintPipe {
constructor(private keyService: KeyService) {}
async transform(publicKey: string | Uint8Array, fingerprintMaterial: string): Promise<string> {
try {
if (typeof publicKey === "string") {
publicKey = Utils.fromB64ToArray(publicKey);
}
const fingerprint = await this.keyService.getFingerprint(fingerprintMaterial, publicKey);
if (fingerprint != null) {
return fingerprint.join("-");
}
return "";
} catch {
return "";
}
}
}