diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 74c4ceed948..fe5ae09deaa 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -275,6 +275,7 @@ "webpack-node-externals", "widestring", "windows", + "windows-future", "windows-registry", "zbus", "zbus_polkit", diff --git a/.github/workflows/build-browser-target.yml b/.github/workflows/build-browser-target.yml index 3334326920c..b2e90605d60 100644 --- a/.github/workflows/build-browser-target.yml +++ b/.github/workflows/build-browser-target.yml @@ -1,3 +1,9 @@ +# This workflow is intended to be run when we need to build the client and produce artifacts that require secrets +# when the PR source branch does not have access to secrets (e.g. a fork). +# This workflow will run in the context of the target of the PR and have access to secrets. +# This should only be done after reviewing the PR to ensure that no malicious code has been introduced, +# as it could allow the code on the forked branch to have access to workflow secrets. + name: Build Browser on PR Target on: @@ -25,7 +31,7 @@ jobs: uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main run-workflow: - name: Run Build Browser on PR Target + name: Build Browser needs: check-run if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} uses: ./.github/workflows/build-browser.yml diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 4748a6a9f15..f7b8eeabefe 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -1,3 +1,7 @@ +# This workflow will run in the context of the source of the PR. +# On a PR from a fork, the workflow will not have access to secrets, and so any parts of the build that require secrets will not run. +# If additional artifacts are needed, the failed "build-browser-target.yml" workflow held up by the check-run should be re-run. + name: Build Browser on: diff --git a/.github/workflows/build-cli-target.yml b/.github/workflows/build-cli-target.yml index 81ec4178681..589b0cc1667 100644 --- a/.github/workflows/build-cli-target.yml +++ b/.github/workflows/build-cli-target.yml @@ -1,3 +1,9 @@ +# This workflow is intended to be run when we need to build the client and produce artifacts that require secrets +# when the PR source branch does not have access to secrets (e.g. a fork). +# This workflow will run in the context of the target of the PR and have access to secrets. +# This should only be done after reviewing the PR to ensure that no malicious code has been introduced, +# as it could allow the code on the forked branch to have access to workflow secrets. + name: Build CLI on PR Target on: @@ -25,7 +31,7 @@ jobs: uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main run-workflow: - name: Run Build CLI on PR Target + name: Build CLI needs: check-run if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} uses: ./.github/workflows/build-cli.yml diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 8599a699d9d..a78d3bda5ad 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -1,3 +1,7 @@ +# This workflow will run in the context of the source of the PR. +# On a PR from a fork, the workflow will not have access to secrets, and so any parts of the build that require secrets will not run. +# If additional artifacts are needed, the failed "build-cli-target.yml" workflow held up by the check-run should be re-run. + name: Build CLI on: diff --git a/.github/workflows/build-desktop-target.yml b/.github/workflows/build-desktop-target.yml index 8c26f991174..42ca2be1370 100644 --- a/.github/workflows/build-desktop-target.yml +++ b/.github/workflows/build-desktop-target.yml @@ -1,3 +1,10 @@ + +# This workflow is intended to be run when we need to build the client and produce artifacts that require secrets +# when the PR source branch does not have access to secrets (e.g. a fork). +# This workflow will run in the context of the target of the PR and have access to secrets. +# This should only be done after reviewing the PR to ensure that no malicious code has been introduced, +# as it could allow the code on the forked branch to have access to workflow secrets. + name: Build Desktop on PR Target on: @@ -24,7 +31,7 @@ jobs: uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main run-workflow: - name: Run Build Desktop on PR Target + name: Build Desktop needs: check-run if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} uses: ./.github/workflows/build-desktop.yml diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index 72b60da97a1..4c35eb4c42f 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -1,3 +1,7 @@ +# This workflow will run in the context of the source of the PR. +# On a PR from a fork, the workflow will not have access to secrets, and so any parts of the build that require secrets will not run. +# If additional artifacts are needed, the failed "build-desktop-target.yml" workflow held up by the check-run should be re-run. + name: Build Desktop on: diff --git a/.github/workflows/build-web-target.yml b/.github/workflows/build-web-target.yml index fb7074292b5..390b3c1c578 100644 --- a/.github/workflows/build-web-target.yml +++ b/.github/workflows/build-web-target.yml @@ -1,3 +1,9 @@ +# This workflow is intended to be run when we need to build the client and produce artifacts that require secrets +# when the PR source branch does not have access to secrets (e.g. a fork). +# This workflow will run in the context of the target of the PR and have access to secrets. +# This should only be done after reviewing the PR to ensure that no malicious code has been introduced, +# as it could allow the code on the forked branch to have access to workflow secrets. + name: Build Web on PR Target on: @@ -24,7 +30,7 @@ jobs: uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main run-workflow: - name: Run Build Web on PR Target + name: Build Web needs: check-run if: ${{ github.event.pull_request.head.repo.full_name != github.repository }} uses: ./.github/workflows/build-web.yml diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index a0d9026e471..f706bba610d 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -1,3 +1,7 @@ +# This workflow will run in the context of the source of the PR. +# On a PR from a fork, the workflow will not have access to secrets, and so any parts of the build that require secrets will not run. +# If additional artifacts are needed, the failed "build-web-target.yml" workflow held up by the check-run should be re-run. + name: Build Web on: diff --git a/apps/browser/package.json b/apps/browser/package.json index 6ef35d88c10..b311b837e78 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -19,10 +19,10 @@ "build:prod:firefox": "cross-env NODE_ENV=production npm run build:firefox", "build:prod:opera": "cross-env NODE_ENV=production npm run build:opera", "build:prod:safari": "cross-env NODE_ENV=production npm run build:safari", - "dist:chrome": "npm run build:prod:chrome && mkdir -p dist && ./scripts/compress.ps1 dist-chrome.zip", - "dist:edge": "npm run build:prod:edge && mkdir -p dist && ./scripts/compress.ps1 dist-edge.zip", - "dist:firefox": "npm run build:prod:firefox && mkdir -p dist && ./scripts/compress.ps1 dist-firefox.zip", - "dist:opera": "npm run build:prod:opera && mkdir -p dist && ./scripts/compress.ps1 dist-opera.zip", + "dist:chrome": "npm run build:prod:chrome && mkdir -p dist && ./scripts/compress.sh dist-chrome.zip", + "dist:edge": "npm run build:prod:edge && mkdir -p dist && ./scripts/compress.sh dist-edge.zip", + "dist:firefox": "npm run build:prod:firefox && mkdir -p dist && ./scripts/compress.sh dist-firefox.zip", + "dist:opera": "npm run build:prod:opera && mkdir -p dist && ./scripts/compress.sh dist-opera.zip", "dist:safari": "npm run build:prod:safari && ./scripts/package-safari.ps1", "dist:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:firefox", "dist:opera:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:opera", diff --git a/apps/browser/scripts/compress.sh b/apps/browser/scripts/compress.sh new file mode 100755 index 00000000000..319ab08fbec --- /dev/null +++ b/apps/browser/scripts/compress.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +#### +# Compress the build directory into a zip file. +#### + +set -e +set -u +set -x +set -o pipefail + +FILENAME=$1 + +SCRIPT_ROOT="$(dirname "$0")" +BUILD_DIR="$SCRIPT_ROOT/../build" + +# Check if build directory exists +if [ -d "$BUILD_DIR" ]; then + cd $BUILD_DIR + + # Create dist directory if it doesn't exist + DIST_DIR="../dist" + mkdir -p $DIST_DIR + + # Remove existing dist zip file + DIST_PATH="$DIST_DIR/$FILENAME" + rm -f $DIST_PATH + + # Compress build directory + zip -r $DIST_PATH ./ + echo "Zipped $BUILD_DIR into $DIST_PATH" +fi diff --git a/apps/browser/src/auth/popup/settings/account-security.component.ts b/apps/browser/src/auth/popup/settings/account-security.component.ts index 66e5b0bb214..32b32dc6022 100644 --- a/apps/browser/src/auth/popup/settings/account-security.component.ts +++ b/apps/browser/src/auth/popup/settings/account-security.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DialogRef } from "@angular/cdk/dialog"; import { CommonModule } from "@angular/common"; import { ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder, FormsModule, ReactiveFormsModule } from "@angular/forms"; @@ -46,6 +45,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { + DialogRef, CardComponent, CheckboxModule, DialogService, diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index 454b12cdcea..fa0ae9b9b3e 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -2100,6 +2100,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { } this.closeInlineMenu(sender); + await this.openViewVaultItemPopout(sender.tab, { cipherId: cipher.id, action: SHOW_AUTOFILL_BUTTON, diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index 56df1db9133..dba1235d3a2 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -858,6 +858,7 @@ export default class MainBackground { this.configService, this.stateProvider, this.accountService, + this.logService, ); this.folderService = new FolderService( this.keyService, diff --git a/apps/browser/src/platform/notifications/foreground-notifications.service.ts b/apps/browser/src/platform/notifications/foreground-notifications.service.ts new file mode 100644 index 00000000000..e7685d3fe50 --- /dev/null +++ b/apps/browser/src/platform/notifications/foreground-notifications.service.ts @@ -0,0 +1,31 @@ +import { Observable, Subscription } from "rxjs"; + +import { NotificationResponse } from "@bitwarden/common/models/response/notification.response"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { NotificationsService } from "@bitwarden/common/platform/notifications"; +import { UserId } from "@bitwarden/common/types/guid"; + +// Eventually if we want to support listening to notifications from browser foreground we +// will only ever create a single SignalR connection, likely messaging to the background to reuse its connection. +export class ForegroundNotificationsService implements NotificationsService { + notifications$: Observable; + + constructor(private readonly logService: LogService) { + this.notifications$ = new Observable((subscriber) => { + this.logService.warning( + "Notifications will never emit from browser foreground, you will need to listen to messages from `DefaultNotificationsService.processNotification`", + ); + subscriber.complete(); + }); + } + + startListening(): Subscription { + throw new Error("startListening should never be called from browser foreground."); + } + reconnectFromActivity(): void { + throw new Error("Activity should not be managed from browser foreground."); + } + disconnectFromInactivity(): void { + throw new Error("Activity should not be managed from browser foreground."); + } +} diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts index 71e310ad335..0d392afa63b 100644 --- a/apps/browser/src/popup/app.module.ts +++ b/apps/browser/src/popup/app.module.ts @@ -1,5 +1,4 @@ import { A11yModule } from "@angular/cdk/a11y"; -import { DialogModule } from "@angular/cdk/dialog"; import { DragDropModule } from "@angular/cdk/drag-drop"; import { LayoutModule } from "@angular/cdk/layout"; import { OverlayModule } from "@angular/cdk/overlay"; @@ -15,7 +14,13 @@ import { JslibModule } from "@bitwarden/angular/jslib.module"; import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe"; import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe"; import { UserVerificationDialogComponent } from "@bitwarden/auth/angular"; -import { AvatarModule, ButtonModule, FormFieldModule, ToastModule } from "@bitwarden/components"; +import { + DialogModule, + AvatarModule, + ButtonModule, + FormFieldModule, + ToastModule, +} from "@bitwarden/components"; import { AccountComponent } from "../auth/popup/account-switching/account.component"; import { CurrentAccountComponent } from "../auth/popup/account-switching/current-account.component"; diff --git a/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts index 2a5a56e7dfc..5003bbdc936 100644 --- a/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts +++ b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts @@ -1,10 +1,15 @@ -import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { filter, Subject, takeUntil } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { MessageListener } from "@bitwarden/common/platform/messaging"; -import { ButtonModule, DialogModule, DialogService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogRef, + ButtonModule, + DialogModule, + DialogService, +} from "@bitwarden/components"; export type DesktopSyncVerificationDialogParams = { fingerprint: string[]; diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts index 02ecdb8acc2..09675779584 100644 --- a/apps/browser/src/popup/services/services.module.ts +++ b/apps/browser/src/popup/services/services.module.ts @@ -95,6 +95,7 @@ import { Message, MessageListener, MessageSender } from "@bitwarden/common/platf // eslint-disable-next-line no-restricted-imports -- Used for dependency injection import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal"; import { flagEnabled } from "@bitwarden/common/platform/misc/flags"; +import { NotificationsService } from "@bitwarden/common/platform/notifications"; import { TaskSchedulerService } from "@bitwarden/common/platform/scheduling"; import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; import { ContainerService } from "@bitwarden/common/platform/services/container.service"; @@ -159,6 +160,7 @@ import { runInsideAngular } from "../../platform/browser/run-inside-angular.oper import { ZonedMessageListenerService } from "../../platform/browser/zoned-message-listener.service"; import { ChromeMessageSender } from "../../platform/messaging/chrome-message.sender"; /* eslint-enable no-restricted-imports */ +import { ForegroundNotificationsService } from "../../platform/notifications/foreground-notifications.service"; import { OffscreenDocumentService } from "../../platform/offscreen-document/abstractions/offscreen-document"; import { DefaultOffscreenDocumentService } from "../../platform/offscreen-document/offscreen-document.service"; import { PopupCompactModeService } from "../../platform/popup/layout/popup-compact-mode.service"; @@ -667,6 +669,11 @@ const safeProviders: SafeProvider[] = [ useClass: DefaultSshImportPromptService, deps: [DialogService, ToastService, PlatformUtilsService, I18nServiceAbstraction], }), + safeProvider({ + provide: NotificationsService, + useClass: ForegroundNotificationsService, + deps: [LogService], + }), ]; @NgModule({ diff --git a/apps/browser/src/tools/popup/settings/about-dialog/about-dialog.component.ts b/apps/browser/src/tools/popup/settings/about-dialog/about-dialog.component.ts index 1e5bdee09b9..6f1c1162eb4 100644 --- a/apps/browser/src/tools/popup/settings/about-dialog/about-dialog.component.ts +++ b/apps/browser/src/tools/popup/settings/about-dialog/about-dialog.component.ts @@ -1,4 +1,3 @@ -import { DialogRef } from "@angular/cdk/dialog"; import { CommonModule } from "@angular/common"; import { Component, ElementRef, ViewChild } from "@angular/core"; import { Observable, combineLatest, defer, map } from "rxjs"; @@ -9,7 +8,13 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service"; -import { ButtonModule, DialogModule, ToastService, TypographyModule } from "@bitwarden/components"; +import { + DialogRef, + ButtonModule, + DialogModule, + ToastService, + TypographyModule, +} from "@bitwarden/components"; @Component({ templateUrl: "about-dialog.component.html", diff --git a/apps/browser/src/vault/popup/components/at-risk-carousel-dialog/at-risk-carousel-dialog.component.ts b/apps/browser/src/vault/popup/components/at-risk-carousel-dialog/at-risk-carousel-dialog.component.ts index 9af9f0aeda3..fcca125c2b6 100644 --- a/apps/browser/src/vault/popup/components/at-risk-carousel-dialog/at-risk-carousel-dialog.component.ts +++ b/apps/browser/src/vault/popup/components/at-risk-carousel-dialog/at-risk-carousel-dialog.component.ts @@ -1,7 +1,12 @@ -import { DialogRef } from "@angular/cdk/dialog"; import { Component, inject, signal } from "@angular/core"; -import { ButtonModule, DialogModule, DialogService, TypographyModule } from "@bitwarden/components"; +import { + DialogRef, + ButtonModule, + DialogModule, + DialogService, + TypographyModule, +} from "@bitwarden/components"; import { I18nPipe } from "@bitwarden/ui-common"; import { DarkImageSourceDirective, VaultCarouselModule } from "@bitwarden/vault"; diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts index 9c94f8fc63f..dd5f55a66ee 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.spec.ts @@ -1,4 +1,3 @@ -import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog"; import { Component, EventEmitter, Input, Output } from "@angular/core"; import { ComponentFixture, TestBed } from "@angular/core/testing"; import { By } from "@angular/platform-browser"; @@ -6,6 +5,7 @@ import { NoopAnimationsModule } from "@angular/platform-browser/animations"; import { mock, MockProxy } from "jest-mock-extended"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { DIALOG_DATA, DialogRef } from "@bitwarden/components"; import { AlgorithmInfo } from "@bitwarden/generator-core"; import { CipherFormGeneratorComponent } from "@bitwarden/vault"; diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.ts index 0eeb2e95a29..137f2a9dac3 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/vault-generator-dialog/vault-generator-dialog.component.ts @@ -1,12 +1,17 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Overlay } from "@angular/cdk/overlay"; import { CommonModule } from "@angular/common"; import { Component, Inject } from "@angular/core"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { ButtonModule, DialogService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + ButtonModule, + DialogService, +} from "@bitwarden/components"; import { AlgorithmInfo } from "@bitwarden/generator-core"; import { I18nPipe } from "@bitwarden/ui-common"; import { CipherFormGeneratorComponent } from "@bitwarden/vault"; diff --git a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.html b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.html index c2645f15ea8..b7ffeb89cc1 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/view-v2/view-v2.component.html @@ -5,7 +5,7 @@ - + - + diff --git a/apps/desktop/src/vault/app/vault/view.component.ts b/apps/desktop/src/vault/app/vault/view.component.ts index aee1f34437b..9ddf18fff93 100644 --- a/apps/desktop/src/vault/app/vault/view.component.ts +++ b/apps/desktop/src/vault/app/vault/view.component.ts @@ -17,8 +17,10 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service"; +import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; +import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; @@ -70,6 +72,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro accountService: AccountService, toastService: ToastService, cipherAuthorizationService: CipherAuthorizationService, + private configService: ConfigService, ) { super( cipherService, @@ -99,6 +102,9 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro cipherAuthorizationService, ); } + + protected limitItemDeletion$ = this.configService.getFeatureFlag$(FeatureFlag.LimitItemDeletion); + ngOnInit() { super.ngOnInit(); diff --git a/apps/web/src/app/admin-console/organizations/collections/bulk-collections-dialog/bulk-collections-dialog.component.ts b/apps/web/src/app/admin-console/organizations/collections/bulk-collections-dialog/bulk-collections-dialog.component.ts index dc08b32ce36..dd19c66f21e 100644 --- a/apps/web/src/app/admin-console/organizations/collections/bulk-collections-dialog/bulk-collections-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/collections/bulk-collections-dialog/bulk-collections-dialog.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, OnDestroy } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { combineLatest, of, Subject, switchMap, takeUntil } from "rxjs"; @@ -18,7 +17,13 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { DialogService, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + DialogService, + ToastService, +} from "@bitwarden/components"; import { SharedModule } from "../../../../shared"; import { GroupApiService, GroupView } from "../../core"; diff --git a/apps/web/src/app/admin-console/organizations/collections/vault.component.ts b/apps/web/src/app/admin-console/organizations/collections/vault.component.ts index 8dfebea5229..97193bf1b1f 100644 --- a/apps/web/src/app/admin-console/organizations/collections/vault.component.ts +++ b/apps/web/src/app/admin-console/organizations/collections/vault.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DialogRef } from "@angular/cdk/dialog"; import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute, Params, Router } from "@angular/router"; import { @@ -62,6 +61,7 @@ import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { ServiceUtils } from "@bitwarden/common/vault/service-utils"; import { + DialogRef, BannerModule, DialogService, Icons, @@ -1226,6 +1226,7 @@ export class VaultComponent implements OnInit, OnDestroy { organizationId: this.organization?.id, parentCollectionId: this.selectedCollection?.node.id, limitNestedCollections: !this.organization.canEditAnyCollection, + isAdminConsoleActive: true, }, }); @@ -1251,6 +1252,7 @@ export class VaultComponent implements OnInit, OnDestroy { readonly: readonly, isAddAccessCollection: c.unmanaged, limitNestedCollections: !this.organization.canEditAnyCollection, + isAdminConsoleActive: true, }, }); diff --git a/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts b/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts index 68ba5830c35..4eab2969fff 100644 --- a/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/entity-events.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; import { Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; @@ -15,7 +14,13 @@ import { EventView } from "@bitwarden/common/models/view/event.view"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; -import { DialogService, TableDataSource, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogService, + TableDataSource, + ToastService, +} from "@bitwarden/components"; import { EventService } from "../../../core"; import { SharedModule } from "../../../shared"; diff --git a/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts b/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts index d1a9d4919e5..2a5af32ecc2 100644 --- a/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/group-add-edit.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { @@ -36,7 +35,13 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { UserId } from "@bitwarden/common/types/guid"; -import { DialogService, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + DialogService, + ToastService, +} from "@bitwarden/components"; import { InternalGroupApiService as GroupService } from "../core"; import { diff --git a/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts b/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts index 780dd45cda5..b5068ba55a6 100644 --- a/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts +++ b/apps/web/src/app/admin-console/organizations/manage/user-confirm.component.ts @@ -1,12 +1,11 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, OnInit } from "@angular/core"; import { FormControl, FormGroup } from "@angular/forms"; import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogConfig, DialogRef, DialogService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; export type UserConfirmDialogData = { diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm-dialog.component.ts index d3a8b8a2e71..c19984f980d 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-confirm-dialog.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { firstValueFrom, map, Observable, switchMap } from "rxjs"; @@ -21,7 +20,7 @@ import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/sym import { StateProvider } from "@bitwarden/common/platform/state"; import { OrganizationId } from "@bitwarden/common/types/guid"; import { OrgKey } from "@bitwarden/common/types/key"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogConfig, DialogService } from "@bitwarden/components"; import { KeyService } from "@bitwarden/key-management"; import { BaseBulkConfirmComponent } from "./base-bulk-confirm.component"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts index 9d7752cde84..27caea3ebd3 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-delete-dialog.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { firstValueFrom } from "rxjs"; @@ -9,7 +8,7 @@ import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enum import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogConfig, DialogService } from "@bitwarden/components"; import { DeleteManagedMemberWarningService } from "../../services/delete-managed-member/delete-managed-member-warning.service"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-enable-sm-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-enable-sm-dialog.component.ts index 0a9c7612c66..e01809789f3 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-enable-sm-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-enable-sm-dialog.component.ts @@ -1,12 +1,17 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject, OnInit } from "@angular/core"; import { OrganizationUserApiService } from "@bitwarden/admin-console/common"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; -import { DialogService, TableDataSource, ToastService } from "@bitwarden/components"; +import { + DialogRef, + DIALOG_DATA, + DialogService, + TableDataSource, + ToastService, +} from "@bitwarden/components"; import { OrganizationUserView } from "../../../core"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-remove-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-remove-dialog.component.ts index c088916adfd..00711e355cb 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-remove-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-remove-dialog.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { @@ -10,7 +9,7 @@ import { import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums"; import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogConfig, DialogService } from "@bitwarden/components"; import { BaseBulkRemoveComponent } from "./base-bulk-remove.component"; import { BulkUserDetails } from "./bulk-status.component"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-restore-revoke.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-restore-revoke.component.ts index 8edb3c8b481..66c03ad4564 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-restore-revoke.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-restore-revoke.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA } from "@angular/cdk/dialog"; import { Component, Inject } from "@angular/core"; import { Observable } from "rxjs"; @@ -9,7 +8,7 @@ import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enum import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogService } from "@bitwarden/components"; import { BulkUserDetails } from "./bulk-status.component"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-status.component.ts b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-status.component.ts index 8f7718a0f75..b8a2f45053b 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-status.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/bulk/bulk-status.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig } from "@angular/cdk/dialog"; import { Component, Inject, OnInit } from "@angular/core"; import { OrganizationUserBulkResponse } from "@bitwarden/admin-console/common"; @@ -13,7 +12,7 @@ import { ProviderUserUserDetailsResponse } from "@bitwarden/common/admin-console import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; -import { DialogService } from "@bitwarden/components"; +import { DIALOG_DATA, DialogConfig, DialogService } from "@bitwarden/components"; import { OrganizationUserView } from "../../../core/views/organization-user.view"; diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts index ef7c76b3727..fac5d606946 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, OnDestroy } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { @@ -37,7 +36,13 @@ import { ProductTierType } from "@bitwarden/common/billing/enums"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DialogService, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + DialogService, + ToastService, +} from "@bitwarden/components"; import { GroupApiService, diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts index 84cb541e9f4..f08cb0b7d7c 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { FormBuilder, Validators } from "@angular/forms"; import { Subject, switchMap, takeUntil } from "rxjs"; @@ -14,7 +13,13 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { DialogService, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + DialogService, + ToastService, +} from "@bitwarden/components"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { OrganizationUserResetPasswordService } from "../services/organization-user-reset-password/organization-user-reset-password.service"; diff --git a/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts b/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts index c15ab4ce9e4..f33460e8c16 100644 --- a/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts +++ b/apps/web/src/app/admin-console/organizations/policies/policy-edit.component.ts @@ -1,6 +1,5 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { AfterViewInit, ChangeDetectorRef, @@ -17,7 +16,13 @@ import { PolicyType } from "@bitwarden/common/admin-console/enums"; import { PolicyRequest } from "@bitwarden/common/admin-console/models/request/policy.request"; import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; -import { DialogService, ToastService } from "@bitwarden/components"; +import { + DIALOG_DATA, + DialogConfig, + DialogRef, + DialogService, + ToastService, +} from "@bitwarden/components"; import { BasePolicy, BasePolicyComponent } from "../policies"; diff --git a/apps/web/src/app/admin-console/organizations/settings/account.component.html b/apps/web/src/app/admin-console/organizations/settings/account.component.html index 8e3d63a337d..8ae94b08f57 100644 --- a/apps/web/src/app/admin-console/organizations/settings/account.component.html +++ b/apps/web/src/app/admin-console/organizations/settings/account.component.html @@ -71,7 +71,7 @@ - {{ "limitItemDeletionDesc" | i18n }} + {{ "limitItemDeletionDescription" | i18n }} + + + + + + diff --git a/libs/vault/src/components/spotlight/spotlight.component.ts b/libs/vault/src/components/spotlight/spotlight.component.ts new file mode 100644 index 00000000000..e52669cc404 --- /dev/null +++ b/libs/vault/src/components/spotlight/spotlight.component.ts @@ -0,0 +1,32 @@ +import { CommonModule } from "@angular/common"; +import { Component, EventEmitter, Input, Output } from "@angular/core"; + +import { ButtonModule, IconButtonModule, TypographyModule } from "@bitwarden/components"; +import { I18nPipe } from "@bitwarden/ui-common"; + +@Component({ + selector: "bit-spotlight", + templateUrl: "spotlight.component.html", + standalone: true, + imports: [ButtonModule, CommonModule, IconButtonModule, I18nPipe, TypographyModule], +}) +export class SpotlightComponent { + // The title of the component + @Input({ required: true }) title: string | null = null; + // The subtitle of the component + @Input({ required: true }) subtitle: string | null = null; + // The text to display on the button + @Input() buttonText?: string; + // Wheter the component can be dismissed, if true, the component will not show a close button + @Input() persistent = false; + @Output() onDismiss = new EventEmitter(); + @Output() onButtonClick = new EventEmitter(); + + handleButtonClick(): void { + this.onButtonClick.emit(); + } + + handleDismiss(): void { + this.onDismiss.emit(); + } +} diff --git a/libs/vault/src/components/spotlight/spotlight.stories.ts b/libs/vault/src/components/spotlight/spotlight.stories.ts new file mode 100644 index 00000000000..9f7757e4528 --- /dev/null +++ b/libs/vault/src/components/spotlight/spotlight.stories.ts @@ -0,0 +1,80 @@ +import { moduleMetadata, Meta, StoryObj } from "@storybook/angular"; + +import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { + ButtonModule, + I18nMockService, + IconButtonModule, + TypographyModule, +} from "@bitwarden/components"; + +import { SpotlightComponent } from "./spotlight.component"; + +const meta: Meta = { + title: "Vault/Spotlight", + component: SpotlightComponent, + decorators: [ + moduleMetadata({ + imports: [ButtonModule, IconButtonModule, TypographyModule], + providers: [ + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + close: "Close", + }); + }, + }, + ], + }), + ], + args: { + title: "Primary", + subtitle: "Callout Text", + buttonText: "Button", + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const WithoutButton: Story = { + args: { + buttonText: undefined, + }, +}; + +export const Persistent: Story = { + args: { + persistent: true, + }, +}; + +export const WithCustomButton: Story = { + args: { + buttonText: "Custom Button", + }, + render: (args) => ({ + props: args, + template: ` + + + + `, + }), +}; diff --git a/libs/vault/src/directives/readonly-textarea.directive.spec.ts b/libs/vault/src/directives/readonly-textarea.directive.spec.ts new file mode 100644 index 00000000000..ec2e3ce112f --- /dev/null +++ b/libs/vault/src/directives/readonly-textarea.directive.spec.ts @@ -0,0 +1,34 @@ +import { CdkTextareaAutosize } from "@angular/cdk/text-field"; +import { EventEmitter, NgZone } from "@angular/core"; + +import { VaultAutosizeReadOnlyTextArea } from "./readonly-textarea.directive"; + +describe("VaultAutosizeReadOnlyTextArea", () => { + let directive: VaultAutosizeReadOnlyTextArea; + let onStable: EventEmitter; + + beforeEach(async () => { + onStable = new EventEmitter(); + + directive = new VaultAutosizeReadOnlyTextArea( + { enabled: undefined } as unknown as CdkTextareaAutosize, + { onStable } as NgZone, + ); + }); + + it("disables CdkTextareaAutosize by default", () => { + expect(directive["autosize"].enabled).toBe(false); + }); + + it("enables CdkTextareaAutosize after view init", async () => { + expect(directive["autosize"].enabled).toBe(false); + + const viewInitPromise = directive.ngAfterViewInit(); + + onStable.emit(); + + await viewInitPromise; + + expect(directive["autosize"].enabled).toBe(true); + }); +}); diff --git a/libs/vault/src/directives/readonly-textarea.directive.ts b/libs/vault/src/directives/readonly-textarea.directive.ts new file mode 100644 index 00000000000..65bd9d6e353 --- /dev/null +++ b/libs/vault/src/directives/readonly-textarea.directive.ts @@ -0,0 +1,29 @@ +import { CdkTextareaAutosize, TextFieldModule } from "@angular/cdk/text-field"; +import { AfterViewInit, Directive, Host, NgZone } from "@angular/core"; +import { firstValueFrom } from "rxjs"; + +@Directive({ + standalone: true, + selector: "textarea[vaultAutosizeReadOnlyTextArea]", + providers: [TextFieldModule], + hostDirectives: [CdkTextareaAutosize], +}) +export class VaultAutosizeReadOnlyTextArea implements AfterViewInit { + constructor( + @Host() private autosize: CdkTextareaAutosize, + private ngZone: NgZone, + ) { + // initially disable autosize + this.autosize.enabled = false; + } + + //