Skip to content

Commit 9444c00

Browse files
Merge branch 'main' into billing/pm-26682/milestone-2d-Display-discount-on-subscription-page
2 parents e7944cb + f2e485e commit 9444c00

File tree

17 files changed

+196
-44
lines changed

17 files changed

+196
-44
lines changed

.github/CODEOWNERS

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ bitwarden_license/bit-web/src/app/dirt @bitwarden/team-data-insights-and-reporti
4747
libs/dirt @bitwarden/team-data-insights-and-reporting-dev
4848
libs/common/src/dirt @bitwarden/team-data-insights-and-reporting-dev
4949

50-
## Localization/Crowdin (Platform and Tools team)
51-
apps/browser/src/_locales @bitwarden/team-tools-dev @bitwarden/team-platform-dev
52-
apps/browser/store/locales @bitwarden/team-tools-dev @bitwarden/team-platform-dev
53-
apps/cli/src/locales @bitwarden/team-tools-dev @bitwarden/team-platform-dev
54-
apps/desktop/src/locales @bitwarden/team-tools-dev @bitwarden/team-platform-dev
55-
apps/web/src/locales @bitwarden/team-tools-dev @bitwarden/team-platform-dev
50+
## Localization/Crowdin (Platform team)
51+
apps/browser/src/_locales @bitwarden/team-platform-dev
52+
apps/browser/store/locales @bitwarden/team-platform-dev
53+
apps/cli/src/locales @bitwarden/team-platform-dev
54+
apps/desktop/src/locales @bitwarden/team-platform-dev
55+
apps/web/src/locales @bitwarden/team-platform-dev
5656

5757
## Vault team files ##
5858
apps/browser/src/vault @bitwarden/team-vault-dev

apps/browser/src/_locales/en/messages.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5806,6 +5806,12 @@
58065806
"upgradeToPremium": {
58075807
"message": "Upgrade to Premium"
58085808
},
5809+
"loadingVault": {
5810+
"message": "Loading vault"
5811+
},
5812+
"vaultLoaded": {
5813+
"message": "Vault loaded"
5814+
},
58095815
"settingDisabledByPolicy": {
58105816
"message": "This setting is disabled by your organization's policy.",
58115817
"description": "This hint text is displayed when a user setting is disabled due to an organization policy."

apps/browser/src/platform/popup/layout/popup-page.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
data-testid="popup-layout-scroll-region"
2828
(scroll)="handleScroll($event)"
2929
[ngClass]="{
30-
'tw-overflow-hidden': hideOverflow(),
30+
'!tw-overflow-hidden': hideOverflow(),
3131
'tw-overflow-y-auto': !hideOverflow(),
3232
'tw-invisible': loading(),
33-
'tw-py-3 bit-compact:tw-py-2 tw-px-[max(0.75rem,calc((100%-(var(--tw-sm-breakpoint)))/2))] bit-compact:tw-px-[max(0.5rem,calc((100%-(var(--tw-sm-breakpoint)))/2))]':
33+
'tw-relative tw-py-3 bit-compact:tw-py-2 tw-px-[max(0.75rem,calc((100%-(var(--tw-sm-breakpoint)))/2))] bit-compact:tw-px-[max(0.5rem,calc((100%-(var(--tw-sm-breakpoint)))/2))]':
3434
!disablePadding(),
3535
}"
3636
bitScrollLayoutHost
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!-- tw-p-3 matches the padding of the popup-page -->
2+
<div
3+
class="tw-absolute tw-left-0 tw-top-0 tw-size-full tw-p-3 tw-overflow-hidden tw-bg-background-alt"
4+
>
5+
<ng-content></ng-content>
6+
</div>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { animate, style, transition, trigger } from "@angular/animations";
2+
import { ChangeDetectionStrategy, Component, HostBinding } from "@angular/core";
3+
4+
@Component({
5+
selector: "vault-fade-in-out-skeleton",
6+
templateUrl: "./vault-fade-in-out-skeleton.component.html",
7+
animations: [
8+
trigger("fadeInOut", [
9+
transition(":enter", [
10+
style({ opacity: 0 }),
11+
animate("100ms ease-in", style({ opacity: 1 })),
12+
]),
13+
transition(":leave", [animate("300ms ease-out", style({ opacity: 0 }))]),
14+
]),
15+
],
16+
changeDetection: ChangeDetectionStrategy.OnPush,
17+
})
18+
export class VaultFadeInOutSkeletonComponent {
19+
@HostBinding("@fadeInOut") fadeInOut = true;
20+
}

apps/browser/src/vault/popup/components/vault-v2/vault-header/vault-header-v2.component.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
PopupListFilter,
2929
VaultPopupListFiltersService,
3030
} from "../../../../../vault/popup/services/vault-popup-list-filters.service";
31+
import { VaultPopupLoadingService } from "../../../services/vault-popup-loading.service";
3132

3233
import { VaultHeaderV2Component } from "./vault-header-v2.component";
3334

@@ -99,6 +100,10 @@ describe("VaultHeaderV2Component", () => {
99100
provide: StateProvider,
100101
useValue: { getGlobal: () => ({ state$, update }) },
101102
},
103+
{
104+
provide: VaultPopupLoadingService,
105+
useValue: { loading$: new BehaviorSubject(false) },
106+
},
102107
],
103108
}).compileComponents();
104109

apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
[(ngModel)]="searchText"
55
(ngModelChange)="onSearchTextChanged()"
66
appAutofocus
7+
[disabled]="loading$ | async"
78
>
89
</bit-search>

apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { SearchTextDebounceInterval } from "@bitwarden/common/vault/services/sea
99
import { SearchModule } from "@bitwarden/components";
1010

1111
import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
12+
import { VaultPopupLoadingService } from "../../../services/vault-popup-loading.service";
1213

1314
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
1415
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@@ -22,8 +23,10 @@ export class VaultV2SearchComponent {
2223

2324
private searchText$ = new Subject<string>();
2425

26+
protected loading$ = this.vaultPopupLoadingService.loading$;
2527
constructor(
2628
private vaultPopupItemsService: VaultPopupItemsService,
29+
private vaultPopupLoadingService: VaultPopupLoadingService,
2730
private ngZone: NgZone,
2831
) {
2932
this.subscribeToLatestSearchText();

apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<popup-page [loading]="loading$ | async">
1+
<popup-page [loading]="showSpinnerLoaders$ | async" [hideOverflow]="showSkeletonsLoaders$ | async">
22
<popup-header slot="header" [pageTitle]="'vault' | i18n">
33
<ng-container slot="end">
44
<app-new-item-dropdown [initialValues]="newItemItemValues$ | async"></app-new-item-dropdown>
@@ -103,4 +103,10 @@
103103
></app-vault-list-items-container>
104104
</ng-container>
105105
</ng-container>
106+
107+
@if (showSkeletonsLoaders$ | async) {
108+
<vault-fade-in-out-skeleton>
109+
<vault-loading-skeleton></vault-loading-skeleton>
110+
</vault-fade-in-out-skeleton>
111+
}
106112
</popup-page>

apps/browser/src/vault/popup/components/vault-v2/vault-v2.component.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1+
import { LiveAnnouncer } from "@angular/cdk/a11y";
12
import { CdkVirtualScrollableElement, ScrollingModule } from "@angular/cdk/scrolling";
23
import { CommonModule } from "@angular/common";
34
import { AfterViewInit, Component, DestroyRef, OnDestroy, OnInit, ViewChild } from "@angular/core";
45
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
56
import { Router, RouterModule } from "@angular/router";
67
import {
78
combineLatest,
9+
distinctUntilChanged,
810
filter,
911
firstValueFrom,
1012
map,
1113
Observable,
1214
shareReplay,
13-
startWith,
1415
switchMap,
1516
take,
17+
tap,
1618
} from "rxjs";
1719

1820
import { JslibModule } from "@bitwarden/angular/jslib.module";
@@ -22,6 +24,8 @@ import { DeactivatedOrg, NoResults, VaultOpen } from "@bitwarden/assets/svg";
2224
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
2325
import { getUserId } from "@bitwarden/common/auth/services/account.service";
2426
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
27+
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
28+
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
2529
import { CipherId, CollectionId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
2630
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
2731
import { CipherType } from "@bitwarden/common/vault/enums";
@@ -41,11 +45,13 @@ import { PopOutComponent } from "../../../../platform/popup/components/pop-out.c
4145
import { PopupHeaderComponent } from "../../../../platform/popup/layout/popup-header.component";
4246
import { PopupPageComponent } from "../../../../platform/popup/layout/popup-page.component";
4347
import { IntroCarouselService } from "../../services/intro-carousel.service";
44-
import { VaultPopupCopyButtonsService } from "../../services/vault-popup-copy-buttons.service";
4548
import { VaultPopupItemsService } from "../../services/vault-popup-items.service";
4649
import { VaultPopupListFiltersService } from "../../services/vault-popup-list-filters.service";
50+
import { VaultPopupLoadingService } from "../../services/vault-popup-loading.service";
4751
import { VaultPopupScrollPositionService } from "../../services/vault-popup-scroll-position.service";
4852
import { AtRiskPasswordCalloutComponent } from "../at-risk-callout/at-risk-password-callout.component";
53+
import { VaultFadeInOutSkeletonComponent } from "../vault-fade-in-out-skeleton/vault-fade-in-out-skeleton.component";
54+
import { VaultLoadingSkeletonComponent } from "../vault-loading-skeleton/vault-loading-skeleton.component";
4955

5056
import { BlockedInjectionBanner } from "./blocked-injection-banner/blocked-injection-banner.component";
5157
import {
@@ -88,6 +94,8 @@ type VaultState = UnionOfValues<typeof VaultState>;
8894
SpotlightComponent,
8995
RouterModule,
9096
TypographyModule,
97+
VaultLoadingSkeletonComponent,
98+
VaultFadeInOutSkeletonComponent,
9199
],
92100
})
93101
export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
@@ -108,19 +116,30 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
108116
);
109117

110118
activeUserId: UserId | null = null;
119+
120+
private loading$ = this.vaultPopupLoadingService.loading$.pipe(
121+
distinctUntilChanged(),
122+
tap((loading) => {
123+
const key = loading ? "loadingVault" : "vaultLoaded";
124+
void this.liveAnnouncer.announce(this.i18nService.translate(key), "polite");
125+
}),
126+
);
127+
private skeletonFeatureFlag$ = this.configService.getFeatureFlag$(
128+
FeatureFlag.VaultLoadingSkeletons,
129+
);
130+
111131
protected favoriteCiphers$ = this.vaultPopupItemsService.favoriteCiphers$;
112132
protected remainingCiphers$ = this.vaultPopupItemsService.remainingCiphers$;
113133
protected allFilters$ = this.vaultPopupListFiltersService.allFilters$;
114134

115-
protected loading$ = combineLatest([
116-
this.vaultPopupItemsService.loading$,
117-
this.allFilters$,
118-
// Added as a dependency to avoid flashing the copyActions on slower devices
119-
this.vaultCopyButtonsService.showQuickCopyActions$,
120-
]).pipe(
121-
map(([itemsLoading, filters]) => itemsLoading || !filters),
122-
shareReplay({ bufferSize: 1, refCount: true }),
123-
startWith(true),
135+
/** When true, show spinner loading state */
136+
protected showSpinnerLoaders$ = combineLatest([this.loading$, this.skeletonFeatureFlag$]).pipe(
137+
map(([loading, skeletonsEnabled]) => loading && !skeletonsEnabled),
138+
);
139+
140+
/** When true, show skeleton loading state */
141+
protected showSkeletonsLoaders$ = combineLatest([this.loading$, this.skeletonFeatureFlag$]).pipe(
142+
map(([loading, skeletonsEnabled]) => loading && skeletonsEnabled),
124143
);
125144

126145
protected newItemItemValues$: Observable<NewItemInitialValues> =
@@ -150,14 +169,17 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
150169
private vaultPopupItemsService: VaultPopupItemsService,
151170
private vaultPopupListFiltersService: VaultPopupListFiltersService,
152171
private vaultScrollPositionService: VaultPopupScrollPositionService,
172+
private vaultPopupLoadingService: VaultPopupLoadingService,
153173
private accountService: AccountService,
154174
private destroyRef: DestroyRef,
155175
private cipherService: CipherService,
156176
private dialogService: DialogService,
157-
private vaultCopyButtonsService: VaultPopupCopyButtonsService,
158177
private introCarouselService: IntroCarouselService,
159178
private nudgesService: NudgesService,
160179
private router: Router,
180+
private liveAnnouncer: LiveAnnouncer,
181+
private i18nService: I18nService,
182+
private configService: ConfigService,
161183
) {
162184
combineLatest([
163185
this.vaultPopupItemsService.emptyVault$,

0 commit comments

Comments
 (0)