Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@
}
<th
bitCell
class="tw-text-right"
[ngClass]="
((showCopyAndLaunchActions$ | async)
? 'tw-w-28'
: batchBarService?.enabled()
? 'tw-w-24'
: 'tw-w-12') + ' tw-text-right'
optionsColumnWidthClass(
(showCopyAndLaunchActions$ | async) ?? false,
(showQuickCopyActions$ | async) ?? false
)
"
>
@if (!batchBarService?.enabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/res
import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils";
import { MenuModule, TableModule } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { RoutedVaultFilterService, RoutedVaultFilterModel, VaultItem } from "@bitwarden/vault";
import {
RoutedVaultFilterService,
RoutedVaultFilterModel,
VaultCopyButtonsService,
VaultItem,
} from "@bitwarden/vault";

import { VaultItemsComponent } from "./vault-items.component";

Expand Down Expand Up @@ -70,13 +75,33 @@ describe("VaultItemsComponent", () => {
getFeatureFlag$: jest.fn().mockReturnValue(of(false)),
},
},
{
provide: VaultCopyButtonsService,
useValue: {
showQuickCopyActions$: of(false),
},
},
],
});

const fixture = TestBed.createComponent(VaultItemsComponent);
component = fixture.componentInstance;
});

describe("optionsColumnWidthClass", () => {
it("reserves room for the quick copy icons when they are shown", () => {
expect(component["optionsColumnWidthClass"](true, true)).toBe("tw-w-48");
});

it("reserves room for the combined copy and launch actions", () => {
expect(component["optionsColumnWidthClass"](true, false)).toBe("tw-w-32");
});

it("only fits the options menu when there are no copy or launch actions", () => {
expect(component["optionsColumnWidthClass"](false, false)).toBe("tw-w-12");
});
});

describe("bulkArchiveAllowed", () => {
it("returns false when no items are selected", () => {
component.userCanArchive = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
compareVaultItems,
RoutedVaultFilterService,
VaultBatchBarService,
VaultCopyButtonsService,
VaultItem,
} from "@bitwarden/vault";

Expand Down Expand Up @@ -175,8 +176,11 @@ export class VaultItemsComponent<C extends CipherViewLike> {
protected canRestoreSelected$: Observable<boolean>;
protected disableMenu$: Observable<boolean>;
protected showCopyAndLaunchActions$: Observable<boolean>;
protected showQuickCopyActions$: Observable<boolean>;
private restrictedTypes: RestrictedCipherType[] = [];

private readonly vaultCopyButtonsService = inject(VaultCopyButtonsService);

constructor(
protected cipherAuthorizationService: CipherAuthorizationService,
protected restrictedItemTypesService: RestrictedItemTypesService,
Expand All @@ -186,6 +190,11 @@ export class VaultItemsComponent<C extends CipherViewLike> {
this.showCopyAndLaunchActions$ = this.configService.getFeatureFlag$(
FeatureFlag.PM28091_AddCopyAndQuickLaunchActions,
);

this.showQuickCopyActions$ = combineLatest([
this.configService.getFeatureFlag$(FeatureFlag.PM40435_QuickCopyIconSetting),
this.vaultCopyButtonsService.showQuickCopyActions$,
]).pipe(map(([flagEnabled, settingEnabled]) => flagEnabled && settingEnabled));
this.canDeleteSelected$ = this.selection.changed.pipe(
startWith(null),
switchMap(() => {
Expand Down Expand Up @@ -280,6 +289,23 @@ export class VaultItemsComponent<C extends CipherViewLike> {
return this.showCollections || this.showGroups || this.showOwner;
}

/**
* Width of the options column. A row's copy and launch actions are absolutely positioned to the
* left of its options menu, so the column has to be wide enough to hold them all. Otherwise they
* render on top of the preceding columns, e.g. the owner badge.
*/
protected optionsColumnWidthClass(
showCopyAndLaunchActions: boolean,
showQuickCopyActions: boolean,
): string {
if (showCopyAndLaunchActions) {
// Quick copy shows an icon per copyable field rather than a single combined copy menu
return showQuickCopyActions ? "tw-w-48" : "tw-w-32";
}

return this.batchBarService?.enabled() ? "tw-w-24" : "tw-w-12";
}

get isAllSelected() {
// Check selection against sorted items to match toggleAll() behavior
const sortedItems = this.getSortedEditableItems();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {
RoutedVaultFilterBridgeService,
RoutedVaultFilterService,
VaultBatchBarService,
VaultCopyButtonsService,
VaultFilter,
VaultFilterServiceAbstraction,
VaultItem,
Expand Down Expand Up @@ -302,6 +303,10 @@ describe("VaultComponent", () => {
provide: VaultItemsTransferService,
useValue: mock<VaultItemsTransferService>(),
},
{
provide: VaultCopyButtonsService,
useValue: { showQuickCopyActions$: of(false) },
},
{
provide: VaultBatchBarService,
useValue: {
Expand Down
Loading