diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 553055439c..4a89889810 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -166,15 +166,21 @@
"confirmIdentity": {
"message": "Confirm your identity to continue."
},
- "account": {
- "message": "Account"
- },
"changeMasterPassword": {
"message": "Change master password"
},
"continueToWebApp": {
"message": "Continue to web app?"
},
+ "continueToWebAppDesc": {
+ "message": "Explore more features of your Bitwarden account on the web app."
+ },
+ "continueToHelpCenter": {
+ "message": "Continue to Help Center?"
+ },
+ "continueToHelpCenterDesc": {
+ "message": "Learn more about how to use Bitwarden on the Help Center."
+ },
"changeMasterPasswordOnWebConfirmation": {
"message": "You can change your master password on the Bitwarden web app."
},
@@ -192,9 +198,45 @@
"logOut": {
"message": "Log out"
},
+ "aboutBitwarden": {
+ "message": "About Bitwarden"
+ },
"about": {
"message": "About"
},
+ "moreFromBitwarden": {
+ "message": "More from Bitwarden"
+ },
+ "continueToBitwardenDotCom": {
+ "message": "Continue to bitwarden.com?"
+ },
+ "bitwardenForBusiness": {
+ "message": "Bitwarden for Business"
+ },
+ "bitwardenAuthenticator": {
+ "message": "Bitwarden Authenticator"
+ },
+ "continueToAuthenticatorPageDesc": {
+ "message": "Bitwarden Authenticator allows you to store authenticator keys and generate TOTP codes for 2-step verification flows. Learn more on the bitwarden.com website"
+ },
+ "bitwardenSecretsManager": {
+ "message": "Bitwarden Secrets Manager"
+ },
+ "continueToSecretsManagerPageDesc": {
+ "message": "Securely store, manage, and share developer secrets with Bitwarden Secrets Manager. Learn more on the bitwarden.com website."
+ },
+ "passwordlessDotDev": {
+ "message": "Passwordless.dev"
+ },
+ "continueToPasswordlessDotDevPageDesc": {
+ "message": "Create smooth and secure login experiences free from traditional passwords with Passwordless.dev. Learn more on the bitwarden.com website."
+ },
+ "freeBitwardenFamilies": {
+ "message": "Free Bitwarden Families"
+ },
+ "freeBitwardenFamiliesPageDesc": {
+ "message": "You are eligible for Free Bitwarden Families. Redeem this offer today in the web app."
+ },
"version": {
"message": "Version"
},
@@ -253,8 +295,8 @@
"passGenInfo": {
"message": "Automatically generate strong, unique passwords for your logins."
},
- "bitWebVault": {
- "message": "Bitwarden web vault"
+ "bitWebVaultApp": {
+ "message": "Bitwarden web app"
},
"importItems": {
"message": "Import items"
@@ -779,11 +821,8 @@
"shared": {
"message": "Shared"
},
- "learnOrg": {
- "message": "Learn about organizations"
- },
- "learnOrgConfirmation": {
- "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
+ "bitwardenForBusinessPageDesc": {
+ "message": "Bitwarden for Business allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website."
},
"moveToOrganization": {
"message": "Move to organization"
diff --git a/apps/browser/src/popup/app-routing.animations.ts b/apps/browser/src/popup/app-routing.animations.ts
index 96e5dbbe37..b2fa53caba 100644
--- a/apps/browser/src/popup/app-routing.animations.ts
+++ b/apps/browser/src/popup/app-routing.animations.ts
@@ -208,8 +208,8 @@ export const routerTransition = trigger("routerTransition", [
transition("tabs => lock", inSlideDown),
- transition("tabs => help-and-feedback", inSlideLeft),
- transition("help-and-feedback => tabs", outSlideRight),
+ transition("tabs => about", inSlideLeft),
+ transition("about => tabs", outSlideRight),
transition("tabs => send-type", inSlideLeft),
transition("send-type => tabs", outSlideRight),
diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts
index b4445430a6..deafbb9753 100644
--- a/apps/browser/src/popup/app-routing.module.ts
+++ b/apps/browser/src/popup/app-routing.module.ts
@@ -36,6 +36,8 @@ import { PasswordGeneratorHistoryComponent } from "../tools/popup/generator/pass
import { SendAddEditComponent } from "../tools/popup/send/send-add-edit.component";
import { SendGroupingsComponent } from "../tools/popup/send/send-groupings.component";
import { SendTypeComponent } from "../tools/popup/send/send-type.component";
+import { AboutPageComponent } from "../tools/popup/settings/about-page/about-page.component";
+import { MoreFromBitwardenPageComponent } from "../tools/popup/settings/about-page/more-from-bitwarden-page.component";
import { ExportComponent } from "../tools/popup/settings/export.component";
import { ImportBrowserComponent } from "../tools/popup/settings/import/import-browser.component";
import { SettingsV2Component } from "../tools/popup/settings/settings-v2.component";
@@ -60,7 +62,6 @@ import { VaultSettingsComponent } from "../vault/popup/settings/vault-settings.c
import { extensionRefreshRedirect, extensionRefreshSwap } from "./extension-refresh-route-utils";
import { debounceNavigationGuard } from "./services/debounce-navigation.service";
-import { HelpAndFeedbackComponent } from "./settings/help-and-feedback.component";
import { OptionsComponent } from "./settings/options.component";
import { TabsV2Component } from "./tabs-v2.component";
import { TabsComponent } from "./tabs.component";
@@ -349,10 +350,16 @@ const routes: Routes = [
data: { state: "update-temp-password" },
},
{
- path: "help-and-feedback",
- component: HelpAndFeedbackComponent,
+ path: "about",
+ component: AboutPageComponent,
canActivate: [AuthGuard],
- data: { state: "help-and-feedback" },
+ data: { state: "about" },
+ },
+ {
+ path: "more-from-bitwarden",
+ component: MoreFromBitwardenPageComponent,
+ canActivate: [AuthGuard],
+ data: { state: "moreFromBitwarden" },
},
...extensionRefreshSwap(TabsComponent, TabsV2Component, {
path: "tabs",
diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts
index 4381dddf0c..54a9da028f 100644
--- a/apps/browser/src/popup/app.module.ts
+++ b/apps/browser/src/popup/app.module.ts
@@ -84,7 +84,6 @@ import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { UserVerificationComponent } from "./components/user-verification.component";
import { ServicesModule } from "./services/services.module";
-import { HelpAndFeedbackComponent } from "./settings/help-and-feedback.component";
import { OptionsComponent } from "./settings/options.component";
import { TabsV2Component } from "./tabs-v2.component";
import { TabsComponent } from "./tabs.component";
@@ -185,7 +184,6 @@ import "../platform/popup/locales";
RemovePasswordComponent,
VaultSelectComponent,
Fido2Component,
- HelpAndFeedbackComponent,
AutofillComponent,
EnvironmentSelectorComponent,
AccountSwitcherComponent,
diff --git a/apps/browser/src/popup/settings/help-and-feedback.component.ts b/apps/browser/src/popup/settings/help-and-feedback.component.ts
deleted file mode 100644
index cba57529f0..0000000000
--- a/apps/browser/src/popup/settings/help-and-feedback.component.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Component } from "@angular/core";
-
-import { BrowserApi } from "../../platform/browser/browser-api";
-
-@Component({
- selector: "app-help-and-feedback",
- templateUrl: "help-and-feedback.component.html",
-})
-export class HelpAndFeedbackComponent {
- launchHelp() {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserApi.createNewTab("https://bitwarden.com/help/");
- }
- launchContactForm() {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserApi.createNewTab("https://bitwarden.com/contact/");
- }
-
- launchForums() {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserApi.createNewTab("https://bitwarden.com/getinvolved/");
- }
-}
diff --git a/apps/browser/src/popup/settings/help-and-feedback.component.html b/apps/browser/src/tools/popup/settings/about-page/about-page.component.html
similarity index 51%
rename from apps/browser/src/popup/settings/help-and-feedback.component.html
rename to apps/browser/src/tools/popup/settings/about-page/about-page.component.html
index f2cbfa9355..3ab41cee11 100644
--- a/apps/browser/src/popup/settings/help-and-feedback.component.html
+++ b/apps/browser/src/tools/popup/settings/about-page/about-page.component.html
@@ -6,34 +6,47 @@
- {{ "helpFeedback" | i18n }}
+ {{ "about" | i18n }}
-
+
+
+
@@ -43,12 +56,26 @@
appStopClick
(click)="launchContactForm()"
>
-
-
-
{{ "contactSupport" | i18n }}
+
+
diff --git a/apps/browser/src/tools/popup/settings/about-page/about-page.component.ts b/apps/browser/src/tools/popup/settings/about-page/about-page.component.ts
new file mode 100644
index 0000000000..d87a26948d
--- /dev/null
+++ b/apps/browser/src/tools/popup/settings/about-page/about-page.component.ts
@@ -0,0 +1,84 @@
+import { CommonModule } from "@angular/common";
+import { Component } from "@angular/core";
+import { RouterModule } from "@angular/router";
+import { firstValueFrom } from "rxjs";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { DeviceType } from "@bitwarden/common/enums";
+import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
+import { DialogService } from "@bitwarden/components";
+
+import { BrowserApi } from "../../../../platform/browser/browser-api";
+import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
+import { AboutDialogComponent } from "../about-dialog/about-dialog.component";
+
+const RateUrls = {
+ [DeviceType.ChromeExtension]:
+ "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews",
+ [DeviceType.FirefoxExtension]:
+ "https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews",
+ [DeviceType.OperaExtension]:
+ "https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container",
+ [DeviceType.EdgeExtension]:
+ "https://microsoftedge.microsoft.com/addons/detail/jbkfoedolllekgbhcbcoahefnbanhhlh",
+ [DeviceType.VivaldiExtension]:
+ "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews",
+ [DeviceType.SafariExtension]: "https://apps.apple.com/app/bitwarden/id1352778147",
+};
+
+@Component({
+ templateUrl: "about-page.component.html",
+ standalone: true,
+ imports: [CommonModule, JslibModule, RouterModule, PopOutComponent],
+})
+export class AboutPageComponent {
+ constructor(
+ private dialogService: DialogService,
+ private environmentService: EnvironmentService,
+ private platformUtilsService: PlatformUtilsService,
+ ) {}
+
+ about() {
+ this.dialogService.open(AboutDialogComponent);
+ }
+
+ async launchHelp() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToHelpCenter" },
+ content: { key: "continueToHelpCenterDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ await BrowserApi.createNewTab("https://bitwarden.com/help/");
+ }
+ }
+
+ async openWebVault() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToWebApp" },
+ content: { key: "continueToWebAppDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ const env = await firstValueFrom(this.environmentService.environment$);
+ const url = env.getWebVaultUrl();
+ await BrowserApi.createNewTab(url);
+ }
+ }
+
+ async launchContactForm() {
+ await BrowserApi.createNewTab("https://bitwarden.com/contact/");
+ }
+
+ async launchForums() {
+ await BrowserApi.createNewTab("https://bitwarden.com/getinvolved/");
+ }
+
+ async rate() {
+ const deviceType = this.platformUtilsService.getDevice();
+ await BrowserApi.createNewTab((RateUrls as any)[deviceType]);
+ }
+}
diff --git a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.html b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.html
new file mode 100644
index 0000000000..bf9decca4e
--- /dev/null
+++ b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.ts b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.ts
new file mode 100644
index 0000000000..a9e9e797bf
--- /dev/null
+++ b/apps/browser/src/tools/popup/settings/about-page/more-from-bitwarden-page.component.ts
@@ -0,0 +1,91 @@
+import { CommonModule } from "@angular/common";
+import { Component } from "@angular/core";
+import { RouterModule } from "@angular/router";
+import { Observable, firstValueFrom } from "rxjs";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
+import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
+import { DialogService } from "@bitwarden/components";
+
+import { BrowserApi } from "../../../../platform/browser/browser-api";
+import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
+
+@Component({
+ templateUrl: "more-from-bitwarden-page.component.html",
+ standalone: true,
+ imports: [CommonModule, JslibModule, RouterModule, PopOutComponent],
+})
+export class MoreFromBitwardenPageComponent {
+ canAccessPremium$: Observable;
+
+ constructor(
+ private dialogService: DialogService,
+ private billingAccountProfileStateService: BillingAccountProfileStateService,
+ private environmentService: EnvironmentService,
+ ) {
+ this.canAccessPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$;
+ }
+
+ async openFreeBitwardenFamiliesPage() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToWebApp" },
+ content: { key: "freeBitwardenFamiliesPageDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ const env = await firstValueFrom(this.environmentService.environment$);
+ const url = env.getWebVaultUrl();
+ await BrowserApi.createNewTab(url + "/#/settings/sponsored-families");
+ }
+ }
+
+ async openBitwardenForBusinessPage() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToBitwardenDotCom" },
+ content: { key: "bitwardenForBusinessPageDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ await BrowserApi.createNewTab("https://bitwarden.com/products/business/");
+ }
+ }
+
+ async openAuthenticatorPage() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToBitwardenDotCom" },
+ content: { key: "continueToAuthenticatorPageDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ await BrowserApi.createNewTab("https://bitwarden.com/products/authenticator");
+ }
+ }
+
+ async openSecretsManagerPage() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToBitwardenDotCom" },
+ content: { key: "continueToSecretsManagerPageDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ await BrowserApi.createNewTab("https://bitwarden.com/products/secrets-manager");
+ }
+ }
+
+ async openPasswordlessDotDevPage() {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "continueToBitwardenDotCom" },
+ content: { key: "continueToPasswordlessDotDevPageDesc" },
+ type: "info",
+ acceptButtonText: { key: "continue" },
+ });
+ if (confirmed) {
+ await BrowserApi.createNewTab("https://bitwarden.com/products/passwordless");
+ }
+ }
+}
diff --git a/apps/browser/src/tools/popup/settings/settings.component.html b/apps/browser/src/tools/popup/settings/settings.component.html
index 7506a07da5..7dba3d0a3d 100644
--- a/apps/browser/src/tools/popup/settings/settings.component.html
+++ b/apps/browser/src/tools/popup/settings/settings.component.html
@@ -1,15 +1,14 @@
-
+
{{ "settings" | i18n }}
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/browser/src/tools/popup/settings/settings.component.ts b/apps/browser/src/tools/popup/settings/settings.component.ts
index d0c5d63092..973efc7203 100644
--- a/apps/browser/src/tools/popup/settings/settings.component.ts
+++ b/apps/browser/src/tools/popup/settings/settings.component.ts
@@ -1,101 +1,9 @@
-import { Component, OnInit } from "@angular/core";
-import { Router } from "@angular/router";
-import { firstValueFrom, Subject } from "rxjs";
-
-import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
-import { DeviceType } from "@bitwarden/common/enums";
-import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { DialogService } from "@bitwarden/components";
-
-import { BrowserApi } from "../../../platform/browser/browser-api";
-import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
-
-import { AboutDialogComponent } from "./about-dialog/about-dialog.component";
-
-const RateUrls = {
- [DeviceType.ChromeExtension]:
- "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews",
- [DeviceType.FirefoxExtension]:
- "https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews",
- [DeviceType.OperaExtension]:
- "https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container",
- [DeviceType.EdgeExtension]:
- "https://microsoftedge.microsoft.com/addons/detail/jbkfoedolllekgbhcbcoahefnbanhhlh",
- [DeviceType.VivaldiExtension]:
- "https://chromewebstore.google.com/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews",
- [DeviceType.SafariExtension]: "https://apps.apple.com/app/bitwarden/id1352778147",
-};
+import { Component } from "@angular/core";
@Component({
selector: "tools-settings",
templateUrl: "settings.component.html",
})
-// eslint-disable-next-line rxjs-angular/prefer-takeuntil
-export class SettingsComponent implements OnInit {
- private destroy$ = new Subject();
-
- constructor(
- private platformUtilsService: PlatformUtilsService,
- private i18nService: I18nService,
- private vaultTimeoutService: VaultTimeoutService,
- public messagingService: MessagingService,
- private router: Router,
- private environmentService: EnvironmentService,
- private dialogService: DialogService,
- ) {}
-
- async ngOnInit() {}
-
- async share() {
- const confirmed = await this.dialogService.openSimpleDialog({
- title: { key: "learnOrg" },
- content: { key: "learnOrgConfirmation" },
- type: "info",
- });
- if (confirmed) {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserApi.createNewTab("https://bitwarden.com/help/about-organizations/");
- }
- }
-
- async webVault() {
- const env = await firstValueFrom(this.environmentService.environment$);
- const url = env.getWebVaultUrl();
- await BrowserApi.createNewTab(url);
- }
-
- async import() {
- await this.router.navigate(["/import"]);
- if (await BrowserApi.isPopupOpen()) {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserPopupUtils.openCurrentPagePopout(window);
- }
- }
-
- export() {
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- this.router.navigate(["/export"]);
- }
-
- about() {
- this.dialogService.open(AboutDialogComponent);
- }
-
- rate() {
- const deviceType = this.platformUtilsService.getDevice();
- // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- BrowserApi.createNewTab((RateUrls as any)[deviceType]);
- }
-
- ngOnDestroy() {
- this.destroy$.next();
- this.destroy$.complete();
- }
+export class SettingsComponent {
+ constructor() {}
}