[PM-4306] Extract file-popout-callout component used within Send on browser (#6564)

* Extract callout in send-add-edit into separate component

- Created new file-popout-callout.component
- Register component within app.module
- Replaced usage within send-add-edit.component

* Override popup header style to fix bit-callout

* [PM-4375] Reuse show file selector callout logic (#6606)

* Added FilePopoutUtilsService with the logic of showing/hiding the popout callout and file selector button

* Added documentation to FilePopoutUtilsService

* Added documentation for class and constructor on FilePopoutUtilsService

---------

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
Co-authored-by: aj-rosado <109146700+aj-rosado@users.noreply.github.com>
This commit is contained in:
Daniel James Smith 2023-10-20 12:28:36 +02:00 committed by GitHub
parent ca7e1b2501
commit 35ed8f1d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 145 additions and 49 deletions

View File

@ -31,6 +31,7 @@ import { SsoComponent } from "../auth/popup/sso.component";
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component"; import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
import { TwoFactorComponent } from "../auth/popup/two-factor.component"; import { TwoFactorComponent } from "../auth/popup/two-factor.component";
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component"; import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
import { FilePopoutCalloutComponent } from "../tools/popup/components/file-popout-callout.component";
import { GeneratorComponent } from "../tools/popup/generator/generator.component"; import { GeneratorComponent } from "../tools/popup/generator/generator.component";
import { PasswordGeneratorHistoryComponent } from "../tools/popup/generator/password-generator-history.component"; import { PasswordGeneratorHistoryComponent } from "../tools/popup/generator/password-generator-history.component";
import { SendListComponent } from "../tools/popup/send/components/send-list.component"; import { SendListComponent } from "../tools/popup/send/components/send-list.component";
@ -98,6 +99,7 @@ import "../platform/popup/locales";
ScrollingModule, ScrollingModule,
ServicesModule, ServicesModule,
DialogModule, DialogModule,
FilePopoutCalloutComponent,
], ],
declarations: [ declarations: [
ActionButtonsComponent, ActionButtonsComponent,

View File

@ -104,6 +104,7 @@ import BrowserMessagingService from "../../platform/services/browser-messaging.s
import { BrowserStateService } from "../../platform/services/browser-state.service"; import { BrowserStateService } from "../../platform/services/browser-state.service";
import { BrowserSendService } from "../../services/browser-send.service"; import { BrowserSendService } from "../../services/browser-send.service";
import { BrowserSettingsService } from "../../services/browser-settings.service"; import { BrowserSettingsService } from "../../services/browser-settings.service";
import { FilePopoutUtilsService } from "../../tools/popup/services/file-popout-utils.service";
import { BrowserFolderService } from "../../vault/services/browser-folder.service"; import { BrowserFolderService } from "../../vault/services/browser-folder.service";
import { VaultFilterService } from "../../vault/services/vault-filter.service"; import { VaultFilterService } from "../../vault/services/vault-filter.service";
@ -520,6 +521,16 @@ function getBgService<T>(service: keyof MainBackground) {
LogService, LogService,
], ],
}, },
{
provide: FilePopoutUtilsService,
useFactory: (
platformUtilsService: PlatformUtilsService,
popupUtilsService: PopupUtilsService
) => {
return new FilePopoutUtilsService(platformUtilsService, popupUtilsService);
},
deps: [PlatformUtilsService, PopupUtilsService],
},
], ],
}) })
export class ServicesModule {} export class ServicesModule {}

View File

@ -0,0 +1,11 @@
<bit-callout
type="warning"
icon="bwi-external-link bwi-rotate-270 bwi-fw"
title="{{ 'sendFileCalloutHeader' | i18n }}"
(click)="popOutWindow()"
*ngIf="showFilePopoutMessage"
>
<div *ngIf="showChromiumFileWarning">{{ "sendLinuxChromiumFileWarning" | i18n }}</div>
<div *ngIf="showFirefoxFileWarning">{{ "sendFirefoxFileWarning" | i18n }}</div>
<div *ngIf="showSafariFileWarning">{{ "sendSafariFileWarning" | i18n }}</div>
</bit-callout>

View File

@ -0,0 +1,37 @@
import { CommonModule } from "@angular/common";
import { Component, OnInit } from "@angular/core";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { CalloutModule } from "@bitwarden/components";
import { PopupUtilsService } from "../../../popup/services/popup-utils.service";
import { FilePopoutUtilsService } from "../services/file-popout-utils.service";
@Component({
selector: "tools-file-popout-callout",
templateUrl: "file-popout-callout.component.html",
standalone: true,
imports: [CommonModule, JslibModule, CalloutModule],
})
export class FilePopoutCalloutComponent implements OnInit {
protected showFilePopoutMessage: boolean;
protected showFirefoxFileWarning: boolean;
protected showSafariFileWarning: boolean;
protected showChromiumFileWarning: boolean;
constructor(
private popupUtilsService: PopupUtilsService,
private filePopoutUtilsService: FilePopoutUtilsService
) {}
ngOnInit() {
this.showFilePopoutMessage = this.filePopoutUtilsService.showFilePopoutMessage(window);
this.showFirefoxFileWarning = this.filePopoutUtilsService.showFirefoxFileWarning(window);
this.showSafariFileWarning = this.filePopoutUtilsService.showSafariFileWarning(window);
this.showChromiumFileWarning = this.filePopoutUtilsService.showChromiumFileWarning(window);
}
popOutWindow() {
this.popupUtilsService.popOut(window);
}
}

View File

@ -22,18 +22,7 @@
{{ "sendOptionsPolicyInEffect" | i18n }} {{ "sendOptionsPolicyInEffect" | i18n }}
</app-callout> </app-callout>
<!-- File Warning --> <!-- File Warning -->
<app-callout <tools-file-popout-callout *ngIf="type === sendType.File && !disableSend" />
type="warning"
icon="bwi-external-link bwi-rotate-270 bwi-fw"
[clickable]="true"
title="{{ 'sendFileCalloutHeader' | i18n }}"
*ngIf="showFilePopoutMessage && type === sendType.File && !disableSend"
(click)="popOutWindow()"
>
<div *ngIf="showChromiumFileWarning">{{ "sendLinuxChromiumFileWarning" | i18n }}</div>
<div *ngIf="showFirefoxFileWarning">{{ "sendFirefoxFileWarning" | i18n }}</div>
<div *ngIf="showSafariFileWarning">{{ "sendSafariFileWarning" | i18n }}</div>
</app-callout>
<!-- Name --> <!-- Name -->
<div class="box"> <div class="box">
<div class="box-content"> <div class="box-content">

View File

@ -17,6 +17,7 @@ import { DialogService } from "@bitwarden/components";
import { BrowserStateService } from "../../../platform/services/abstractions/browser-state.service"; import { BrowserStateService } from "../../../platform/services/abstractions/browser-state.service";
import { PopupUtilsService } from "../../../popup/services/popup-utils.service"; import { PopupUtilsService } from "../../../popup/services/popup-utils.service";
import { FilePopoutUtilsService } from "../services/file-popout-utils.service";
@Component({ @Component({
selector: "app-send-add-edit", selector: "app-send-add-edit",
@ -29,9 +30,7 @@ export class SendAddEditComponent extends BaseAddEditComponent {
// File visibility // File visibility
isFirefox = false; isFirefox = false;
inPopout = false; inPopout = false;
inSidebar = false; showFileSelector = false;
isLinux = false;
isUnsupportedMac = false;
constructor( constructor(
i18nService: I18nService, i18nService: I18nService,
@ -49,7 +48,8 @@ export class SendAddEditComponent extends BaseAddEditComponent {
logService: LogService, logService: LogService,
sendApiService: SendApiService, sendApiService: SendApiService,
dialogService: DialogService, dialogService: DialogService,
formBuilder: FormBuilder formBuilder: FormBuilder,
private filePopoutUtilsService: FilePopoutUtilsService
) { ) {
super( super(
i18nService, i18nService,
@ -67,46 +67,16 @@ export class SendAddEditComponent extends BaseAddEditComponent {
); );
} }
get showFileSelector(): boolean {
return !(this.editMode || this.showFilePopoutMessage);
}
get showFilePopoutMessage(): boolean {
return (
!this.editMode &&
(this.showFirefoxFileWarning || this.showSafariFileWarning || this.showChromiumFileWarning)
);
}
get showFirefoxFileWarning(): boolean {
return this.isFirefox && !(this.inSidebar || this.inPopout);
}
get showSafariFileWarning(): boolean {
return this.isSafari && !this.inPopout;
}
// Only show this for Chromium based browsers in Linux and Mac > Big Sur
get showChromiumFileWarning(): boolean {
return (
(this.isLinux || this.isUnsupportedMac) &&
!this.isFirefox &&
!(this.inSidebar || this.inPopout)
);
}
popOutWindow() { popOutWindow() {
this.popupUtilsService.popOut(window); this.popupUtilsService.popOut(window);
} }
async ngOnInit() { async ngOnInit() {
// File visibility // File visibility
this.isFirefox = this.platformUtilsService.isFirefox(); this.showFileSelector =
!this.editMode && !this.filePopoutUtilsService.showFilePopoutMessage(window);
this.inPopout = this.popupUtilsService.inPopout(window); this.inPopout = this.popupUtilsService.inPopout(window);
this.inSidebar = this.popupUtilsService.inSidebar(window); this.isFirefox = this.platformUtilsService.isFirefox();
this.isLinux = window?.navigator?.userAgent.indexOf("Linux") !== -1;
this.isUnsupportedMac =
this.platformUtilsService.isChrome() && window?.navigator?.appVersion.includes("Mac OS X 11");
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe // eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
this.route.queryParams.pipe(first()).subscribe(async (params) => { this.route.queryParams.pipe(first()).subscribe(async (params) => {

View File

@ -0,0 +1,76 @@
import { Injectable } from "@angular/core";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { PopupUtilsService } from "../../../popup/services/popup-utils.service";
/**
* Service for determining whether to display file popout callout messages.
*/
@Injectable()
export class FilePopoutUtilsService {
/**
* Creates an instance of FilePopoutUtilsService.
*/
constructor(
private platformUtilsService: PlatformUtilsService,
private popupUtilsService: PopupUtilsService
) {}
/**
* Determines whether to show any file popout callout message in the current browser.
* @param win - The window context in which the check should be performed.
* @returns True if a file popout callout message should be displayed; otherwise, false.
*/
showFilePopoutMessage(win: Window): boolean {
return (
this.showFirefoxFileWarning(win) ||
this.showSafariFileWarning(win) ||
this.showChromiumFileWarning(win)
);
}
/**
* Determines whether to show a file popout callout message for the Firefox browser
* @param win - The window context in which the check should be performed.
* @returns True if the extension is not in a sidebar or popout; otherwise, false.
*/
showFirefoxFileWarning(win: Window): boolean {
return (
this.platformUtilsService.isFirefox() &&
!(this.popupUtilsService.inSidebar(win) || this.popupUtilsService.inPopout(win))
);
}
/**
* Determines whether to show a file popout message for the Safari browser
* @param win - The window context in which the check should be performed.
* @returns True if the extension is not in a popout; otherwise, false.
*/
showSafariFileWarning(win: Window): boolean {
return this.platformUtilsService.isSafari() && !this.popupUtilsService.inPopout(win);
}
/**
* Determines whether to show a file popout callout message for Chromium-based browsers in Linux and Mac OS X Big Sur
* @param win - The window context in which the check should be performed.
* @returns True if the extension is not in a sidebar or popout; otherwise, false.
*/
showChromiumFileWarning(win: Window): boolean {
return (
(this.isLinux(win) || this.isUnsupportedMac(win)) &&
!this.platformUtilsService.isFirefox() &&
!(this.popupUtilsService.inSidebar(win) || this.popupUtilsService.inPopout(win))
);
}
private isLinux(win: Window): boolean {
return win?.navigator?.userAgent.indexOf("Linux") !== -1;
}
private isUnsupportedMac(win: Window): boolean {
return (
this.platformUtilsService.isChrome() && win?.navigator?.appVersion.includes("Mac OS X 11")
);
}
}