From 00f2317a8210f9ac86d7fd0739bd549055265de8 Mon Sep 17 00:00:00 2001
From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com>
Date: Wed, 18 Sep 2024 14:36:53 -0700
Subject: [PATCH] [PM-11903] - add file send component (#11132)
* wip - send file details
* wip - file send
* send file details
* fix click on send list container
* remove popup code
* remove popup code
* finalize send file details
* address PR feedback. add base form to send form
* revert changes to send list items container
* revert changes to send list items container
---------
Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
---
apps/browser/src/_locales/en/messages.json | 3 +
.../add-edit/send-add-edit.component.ts | 19 ++--
.../base-send-details.component.ts | 2 +
.../send-details/send-details.component.html | 7 ++
.../send-details/send-details.component.ts | 2 +
.../send-file-details.component.html | 30 ++++++
.../send-file-details.component.ts | 92 +++++++++++++++++++
.../components/send-form.component.ts | 8 +-
.../src/send-form/send-form-container.ts | 4 +
9 files changed, 152 insertions(+), 15 deletions(-)
create mode 100644 libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.html
create mode 100644 libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts
diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index a57b65f6982..061929fc49c 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -1136,6 +1136,9 @@
"file": {
"message": "File"
},
+ "fileToShare": {
+ "message": "File to share"
+ },
"selectFile": {
"message": "Select a file"
},
diff --git a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts
index 48e6cbb8a31..49526bb032b 100644
--- a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts
+++ b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts
@@ -117,25 +117,18 @@ export class SendAddEditComponent {
)
.subscribe((config) => {
this.config = config;
- this.headerText = this.getHeaderText(config.mode, config.sendType);
+ this.headerText = this.getHeaderText(config.mode);
});
}
/**
- * Gets the header text based on the mode and type.
+ * Gets the header text based on the mode.
* @param mode The mode of the send form.
- * @param type The type of the send form.
* @returns The header text.
*/
- private getHeaderText(mode: SendFormMode, type: SendType) {
- const headerKey =
- mode === "edit" || mode === "partial-edit" ? "editItemHeader" : "newItemHeader";
-
- switch (type) {
- case SendType.Text:
- return this.i18nService.t(headerKey, this.i18nService.t("sendTypeText"));
- case SendType.File:
- return this.i18nService.t(headerKey, this.i18nService.t("sendTypeFile"));
- }
+ private getHeaderText(mode: SendFormMode) {
+ return this.i18nService.t(
+ mode === "edit" || mode === "partial-edit" ? "editSend" : "createSend",
+ );
}
}
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts
index 282f6caffab..f3e2229dd2b 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts
@@ -62,6 +62,8 @@ export class BaseSendDetailsComponent implements OnInit {
} as SendView);
});
});
+
+ this.sendFormContainer.registerChildForm("sendDetailsForm", this.sendDetailsForm);
}
async ngOnInit() {
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html
index e1f3f4f0d9f..47e1fc6059a 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html
@@ -16,6 +16,13 @@
{{ "sendDetails" | i18n }}
[sendDetailsForm]="sendDetailsForm"
>
+
+
{{ "deletionDate" | i18n }}
+
+
{{ "file" | i18n }}
+
{{ originalSendView.file.fileName }}
+
{{ originalSendView.file.sizeName }}
+
+
+ {{ "fileToShare" | i18n }}
+
+
+ {{ fileName || ("noFileChosen" | i18n) }}
+
+
+ {{ "maxFileSize" | i18n }}
+
+
+
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts
new file mode 100644
index 00000000000..86c9fa96f1a
--- /dev/null
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts
@@ -0,0 +1,92 @@
+import { CommonModule } from "@angular/common";
+import { Component, Input, OnInit } from "@angular/core";
+import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
+import {
+ FormBuilder,
+ FormControl,
+ FormGroup,
+ Validators,
+ ReactiveFormsModule,
+ FormsModule,
+} from "@angular/forms";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
+import { SendFileView } from "@bitwarden/common/tools/send/models/view/send-file.view";
+import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
+import { ButtonModule, FormFieldModule, SectionComponent } from "@bitwarden/components";
+
+import { SendFormConfig } from "../../abstractions/send-form-config.service";
+import { SendFormContainer } from "../../send-form-container";
+
+import { BaseSendDetailsForm } from "./base-send-details.component";
+
+type BaseSendFileDetailsForm = FormGroup<{
+ file: FormControl;
+}>;
+
+export type SendFileDetailsForm = BaseSendFileDetailsForm & BaseSendDetailsForm;
+
+@Component({
+ selector: "tools-send-file-details",
+ templateUrl: "./send-file-details.component.html",
+ standalone: true,
+ imports: [
+ ButtonModule,
+ CommonModule,
+ JslibModule,
+ ReactiveFormsModule,
+ FormFieldModule,
+ SectionComponent,
+ FormsModule,
+ ],
+})
+export class SendFileDetailsComponent implements OnInit {
+ @Input() config: SendFormConfig;
+ @Input() originalSendView?: SendView;
+ @Input() sendDetailsForm: BaseSendDetailsForm;
+
+ baseSendFileDetailsForm: BaseSendFileDetailsForm;
+ sendFileDetailsForm: SendFileDetailsForm;
+
+ FileSendType = SendType.File;
+ fileName = "";
+
+ constructor(
+ private formBuilder: FormBuilder,
+ protected sendFormContainer: SendFormContainer,
+ ) {
+ this.baseSendFileDetailsForm = this.formBuilder.group({
+ file: this.formBuilder.control(null, Validators.required),
+ });
+
+ this.sendFileDetailsForm = Object.assign(this.baseSendFileDetailsForm, this.sendDetailsForm);
+
+ this.sendFormContainer.registerChildForm("sendFileDetailsForm", this.sendFileDetailsForm);
+
+ this.sendFileDetailsForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
+ this.sendFormContainer.patchSend((send) => {
+ return Object.assign(send, {
+ file: value.file,
+ });
+ });
+ });
+ }
+
+ onFileSelected = (event: Event): void => {
+ const file = (event.target as HTMLInputElement).files?.[0];
+ if (!file) {
+ return;
+ }
+ this.fileName = file.name;
+ this.sendFormContainer.onFileSelected(file);
+ };
+
+ ngOnInit() {
+ if (this.originalSendView) {
+ this.sendFileDetailsForm.patchValue({
+ file: this.originalSendView.file,
+ });
+ }
+ }
+}
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts
index 2cb1907d921..b265b644df4 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts
+++ b/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts
@@ -65,6 +65,7 @@ export class SendFormComponent implements AfterViewInit, OnInit, OnChanges, Send
private bitSubmit: BitSubmitDirective;
private destroyRef = inject(DestroyRef);
private _firstInitialized = false;
+ private file: File | null = null;
/**
* The form ID to use for the form. Used to connect it to a submit button.
@@ -188,14 +189,17 @@ export class SendFormComponent implements AfterViewInit, OnInit, OnChanges, Send
private i18nService: I18nService,
) {}
+ onFileSelected(file: File): void {
+ this.file = file;
+ }
+
submit = async () => {
if (this.sendForm.invalid) {
this.sendForm.markAllAsTouched();
return;
}
- // TODO: Add file handling
- await this.addEditFormService.saveSend(this.updatedSendView, null, this.config);
+ await this.addEditFormService.saveSend(this.updatedSendView, this.file, this.config);
this.toastService.showToast({
variant: "success",
diff --git a/libs/tools/send/send-ui/src/send-form/send-form-container.ts b/libs/tools/send/send-ui/src/send-form/send-form-container.ts
index f3af1ecd816..21508d96727 100644
--- a/libs/tools/send/send-ui/src/send-form/send-form-container.ts
+++ b/libs/tools/send/send-ui/src/send-form/send-form-container.ts
@@ -2,6 +2,7 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import { SendFormConfig } from "./abstractions/send-form-config.service";
import { SendDetailsComponent } from "./components/send-details/send-details.component";
+import { SendFileDetailsForm } from "./components/send-details/send-file-details.component";
import { SendTextDetailsForm } from "./components/send-details/send-text-details.component";
/**
* The complete form for a send. Includes all the sub-forms from their respective section components.
@@ -10,6 +11,7 @@ import { SendTextDetailsForm } from "./components/send-details/send-text-details
export type SendForm = {
sendDetailsForm?: SendDetailsComponent["sendDetailsForm"];
sendTextDetailsForm?: SendTextDetailsForm;
+ sendFileDetailsForm?: SendFileDetailsForm;
};
/**
@@ -37,5 +39,7 @@ export abstract class SendFormContainer {
group: Exclude,
): void;
+ abstract onFileSelected(file: File): void;
+
abstract patchSend(updateFn: (current: SendView) => SendView): void;
}