diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 5b306fdb2a7..63d5f9eb9cb 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -1996,6 +1996,9 @@
"passwordProtected": {
"message": "Password protected"
},
+ "copyLink": {
+ "message": "Copy link"
+ },
"copySendLink": {
"message": "Copy Send link",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
diff --git a/apps/browser/src/tools/popup/send/send-v2.component.html b/apps/browser/src/tools/popup/send/send-v2.component.html
index 3499f8c32ef..52f7c3ed8ff 100644
--- a/apps/browser/src/tools/popup/send/send-v2.component.html
+++ b/apps/browser/src/tools/popup/send/send-v2.component.html
@@ -8,14 +8,12 @@
-
+
{{ "sendsNoItemsTitle" | i18n }}
{{ "sendsNoItemsMessage" | i18n }}
+
diff --git a/apps/browser/src/tools/popup/send/send-v2.component.ts b/apps/browser/src/tools/popup/send/send-v2.component.ts
index fba14b762b1..c720a27ffb0 100644
--- a/apps/browser/src/tools/popup/send/send-v2.component.ts
+++ b/apps/browser/src/tools/popup/send/send-v2.component.ts
@@ -1,21 +1,24 @@
import { CommonModule } from "@angular/common";
import { Component, OnDestroy, OnInit } from "@angular/core";
import { RouterLink } from "@angular/router";
+import { mergeMap, Subject, takeUntil } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
+import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
+import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
import { ButtonModule, NoItemsModule } from "@bitwarden/components";
-import { NoSendsIcon, NewSendDropdownComponent } from "@bitwarden/send-ui";
+import {
+ NoSendsIcon,
+ NewSendDropdownComponent,
+ SendListItemsContainerComponent,
+} from "@bitwarden/send-ui";
import { CurrentAccountComponent } from "../../../auth/popup/account-switching/current-account.component";
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
-enum SendsListState {
- Empty,
-}
-
@Component({
templateUrl: "send-v2.component.html",
standalone: true,
@@ -30,23 +33,30 @@ enum SendsListState {
ButtonModule,
RouterLink,
NewSendDropdownComponent,
+ SendListItemsContainerComponent,
],
})
export class SendV2Component implements OnInit, OnDestroy {
sendType = SendType;
- /** Visual state of the Sends list */
- protected sendsListState: SendsListState | null = null;
+ protected sends: SendView[] = [];
+
+ private destroy$ = new Subject
();
protected noItemIcon = NoSendsIcon;
- protected SendsListStateEnum = SendsListState;
+ constructor(protected sendService: SendService) {}
- constructor() {
- this.sendsListState = SendsListState.Empty;
+ async ngOnInit() {
+ this.sendService.sendViews$
+ .pipe(
+ mergeMap(async (sends) => {
+ this.sends = sends.sort((a, b) => a.name.localeCompare(b.name));
+ }),
+ takeUntil(this.destroy$),
+ )
+ .subscribe();
}
- ngOnInit(): void {}
-
ngOnDestroy(): void {}
}
diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json
index c0ce5c17ee2..31de4095827 100644
--- a/apps/desktop/src/locales/en/messages.json
+++ b/apps/desktop/src/locales/en/messages.json
@@ -1368,7 +1368,7 @@
},
"exportPasswordDescription": {
"message": "This password will be used to export and import this file"
- },
+ },
"accountRestrictedOptionDescription": {
"message": "Use your account encryption key, derived from your account's username and Master Password, to encrypt the export and restrict import to only the current Bitwarden account."
},
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 73396c39c16..560803c87e0 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -4350,6 +4350,9 @@
"message": "Send link",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
+ "copyLink": {
+ "message": "Copy link"
+ },
"copySendLink": {
"message": "Copy Send link",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
diff --git a/libs/common/src/platform/services/config/default-config.service.ts b/libs/common/src/platform/services/config/default-config.service.ts
index 16878a72832..7bdf79f409b 100644
--- a/libs/common/src/platform/services/config/default-config.service.ts
+++ b/libs/common/src/platform/services/config/default-config.service.ts
@@ -115,6 +115,7 @@ export class DefaultConfigService implements ConfigService {
return DefaultFeatureFlagValue[key];
}
+ serverConfig.featureStates[FeatureFlag.ExtensionRefresh] = true;
return serverConfig.featureStates[key] as FeatureFlagValueType;
}),
);
diff --git a/libs/common/src/vault/models/view/send.view.ts b/libs/common/src/vault/models/view/send.view.ts
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/libs/tools/send/send-ui/src/index.ts b/libs/tools/send/send-ui/src/index.ts
index fc7c87449dd..2bb0a3e942d 100644
--- a/libs/tools/send/send-ui/src/index.ts
+++ b/libs/tools/send/send-ui/src/index.ts
@@ -1,2 +1,3 @@
export * from "./icons";
export { NewSendDropdownComponent } from "./new-send-dropdown/new-send-dropdown.component";
+export { SendListItemsContainerComponent } from "./send-list-items-container/send-list-items-container.component";
diff --git a/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.html b/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.html
new file mode 100644
index 00000000000..6a4c6a308ed
--- /dev/null
+++ b/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.html
@@ -0,0 +1,54 @@
+ 0">
+
+
+ {{ "allSends" | i18n }}
+
+ {{ sends.length }}
+
+
+
+
+
+
+
diff --git a/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.ts b/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.ts
new file mode 100644
index 00000000000..ef7232e97a0
--- /dev/null
+++ b/libs/tools/send/send-ui/src/send-list-items-container/send-list-items-container.component.ts
@@ -0,0 +1,95 @@
+import { CommonModule } from "@angular/common";
+import { Component, Input } from "@angular/core";
+import { RouterLink } from "@angular/router";
+import { firstValueFrom } from "rxjs";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
+import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
+import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
+import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
+import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
+import {
+ BadgeModule,
+ ButtonModule,
+ DialogService,
+ IconButtonModule,
+ ItemModule,
+ SectionComponent,
+ SectionHeaderComponent,
+ ToastService,
+ TypographyModule,
+} from "@bitwarden/components";
+
+@Component({
+ imports: [
+ CommonModule,
+ ItemModule,
+ ButtonModule,
+ BadgeModule,
+ IconButtonModule,
+ SectionComponent,
+ TypographyModule,
+ JslibModule,
+ SectionHeaderComponent,
+ RouterLink,
+ ],
+ selector: "app-send-list-items-container",
+ templateUrl: "send-list-items-container.component.html",
+ standalone: true,
+})
+export class SendListItemsContainerComponent {
+ sendType = SendType;
+ /**
+ * The list of sends to display.
+ */
+ @Input()
+ sends: SendView[] = [];
+
+ constructor(
+ protected dialogService: DialogService,
+ protected environmentService: EnvironmentService,
+ protected i18nService: I18nService,
+ protected logService: LogService,
+ protected platformUtilsService: PlatformUtilsService,
+ protected sendApiService: SendApiService,
+ protected toastService: ToastService,
+ ) {}
+
+ async deleteSend(s: SendView): Promise {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "deleteSend" },
+ content: { key: "deleteSendConfirmation" },
+ type: "warning",
+ });
+
+ if (!confirmed) {
+ return false;
+ }
+
+ await this.sendApiService.delete(s.id);
+
+ try {
+ this.toastService.showToast({
+ variant: "success",
+ title: null,
+ message: this.i18nService.t("deletedSend"),
+ });
+ } catch (e) {
+ this.logService.error(e);
+ }
+ }
+
+ async copySendLink(s: SendView) {
+ const env = await firstValueFrom(this.environmentService.environment$);
+ const link = env.getSendUrl() + s.accessId + "/" + s.urlB64Key;
+ this.platformUtilsService.copyToClipboard(link);
+ this.toastService.showToast({
+ variant: "success",
+ title: null,
+ message: this.i18nService.t("valueCopied", this.i18nService.t("sendLink")),
+ });
+ }
+}