diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index 8a6233ec63..3a4835f16a 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -2687,5 +2687,14 @@ "commonImportFormats": { "message": "Common formats", "description": "Label indicating the most common import formats" + }, + "troubleshooting": { + "message": "Troubleshooting" + }, + "disableHardwareAccelerationRestart": { + "message": "Disable hardware acceleration and restart" + }, + "enableHardwareAccelerationRestart": { + "message": "Enable hardware acceleration and restart" } } diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index ee36d49dd9..e0d4dbfb03 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -207,6 +207,7 @@ export class Main { this.environmentService, this.windowMain, this.updaterMain, + this.desktopSettingsService, ); this.biometricsService = new BiometricsService( diff --git a/apps/desktop/src/main/menu/menu.help.ts b/apps/desktop/src/main/menu/menu.help.ts index 133c90a6af..46328e2089 100644 --- a/apps/desktop/src/main/menu/menu.help.ts +++ b/apps/desktop/src/main/menu/menu.help.ts @@ -1,7 +1,8 @@ -import { shell, MenuItemConstructorOptions } from "electron"; +import { shell, MenuItemConstructorOptions, app } from "electron"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { DesktopSettingsService } from "../../platform/services/desktop-settings.service"; import { isMacAppStore, isWindowsStore } from "../../utils"; import { AboutMenu } from "./menu.about"; @@ -26,23 +27,23 @@ export class HelpMenu implements IMenubarMenu { this.separator, this.getMobileApp, this.getBrowserExtension, + this.separator, + this.troubleshooting, ]; - if (this._aboutMenu != null) { - items.push(...this._aboutMenu.items); + if (this.aboutMenu != null) { + items.push(...this.aboutMenu.items); } return items; } - private readonly _i18nService: I18nService; - private readonly _webVaultUrl: string; - private readonly _aboutMenu: AboutMenu; - - constructor(i18nService: I18nService, webVaultUrl: string, aboutMenu: AboutMenu) { - this._i18nService = i18nService; - this._webVaultUrl = webVaultUrl; - this._aboutMenu = aboutMenu; - } + constructor( + private i18nService: I18nService, + private desktopSettingsService: DesktopSettingsService, + private webVaultUrl: string, + private hardwareAccelerationEnabled: boolean, + private aboutMenu: AboutMenu, + ) {} private get helpAndFeedback(): MenuItemConstructorOptions { return { @@ -130,7 +131,7 @@ export class HelpMenu implements IMenubarMenu { return { id: "goToWebVault", label: this.localize("goToWebVault"), - click: () => shell.openExternal(this._webVaultUrl), + click: () => shell.openExternal(this.webVaultUrl), }; } @@ -148,25 +149,19 @@ export class HelpMenu implements IMenubarMenu { { id: "iOS", label: "iOS", - click: () => { - // 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 + click: () => shell.openExternal( "https://itunes.apple.com/app/" + "bitwarden-free-password-manager/id1137397744?mt=8", - ); - }, + ), }, { id: "android", label: "Android", visible: !isMacAppStore(), // Apple Guideline 2.3.10 - Accurate Metadata - click: () => { - // 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 + click: () => shell.openExternal( "https://play.google.com/store/apps/" + "details?id=com.x8bit.bitwarden", - ); - }, + ), }, ]; } @@ -185,62 +180,74 @@ export class HelpMenu implements IMenubarMenu { { id: "chrome", label: "Chrome", - click: () => { - // 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 + click: () => shell.openExternal( "https://chromewebstore.google.com/detail/" + "bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb", - ); - }, + ), }, { id: "firefox", label: "Firefox", - click: () => { - // 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 + click: () => shell.openExternal( "https://addons.mozilla.org/firefox/addon/" + "bitwarden-password-manager/", - ); - }, + ), }, { id: "firefox", label: "Opera", - click: () => { - // 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 + click: () => shell.openExternal( "https://addons.opera.com/extensions/details/" + "bitwarden-free-password-manager/", - ); - }, + ), }, { id: "firefox", label: "Edge", - click: () => { - // 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 + click: () => shell.openExternal( "https://microsoftedge.microsoft.com/addons/" + "detail/jbkfoedolllekgbhcbcoahefnbanhhlh", - ); - }, + ), }, { id: "safari", label: "Safari", - click: () => { - // 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 - shell.openExternal("https://bitwarden.com/download/"); + click: () => shell.openExternal("https://bitwarden.com/download/"), + }, + ]; + } + + private get troubleshooting(): MenuItemConstructorOptions { + return { + id: "troubleshooting", + label: this.localize("troubleshooting"), + submenu: this.troubleshootingSubmenu, + }; + } + + private get troubleshootingSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "hardwareAcceleration", + label: this.localize( + this.hardwareAccelerationEnabled + ? "disableHardwareAccelerationRestart" + : "enableHardwareAccelerationRestart", + ), + click: async () => { + await this.desktopSettingsService.setHardwareAcceleration( + !this.hardwareAccelerationEnabled, + ); + app.relaunch(); + app.exit(); }, }, ]; } private localize(s: string) { - return this._i18nService.t(s); + return this.i18nService.t(s); } } diff --git a/apps/desktop/src/main/menu/menu.main.ts b/apps/desktop/src/main/menu/menu.main.ts index 4d3dc0d62e..9a63d389b5 100644 --- a/apps/desktop/src/main/menu/menu.main.ts +++ b/apps/desktop/src/main/menu/menu.main.ts @@ -5,6 +5,7 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; +import { DesktopSettingsService } from "../../platform/services/desktop-settings.service"; import { UpdaterMain } from "../updater.main"; import { WindowMain } from "../window.main"; @@ -20,6 +21,7 @@ export class MenuMain { private environmentService: EnvironmentService, private windowMain: WindowMain, private updaterMain: UpdaterMain, + private desktopSettingsService: DesktopSettingsService, ) {} async init() { @@ -36,10 +38,12 @@ export class MenuMain { new Menubar( this.i18nService, this.messagingService, + this.desktopSettingsService, this.updaterMain, this.windowMain, await this.getWebVaultUrl(), app.getVersion(), + await firstValueFrom(this.desktopSettingsService.hardwareAcceleration$), updateRequest, ).menu, ); diff --git a/apps/desktop/src/main/menu/menubar.ts b/apps/desktop/src/main/menu/menubar.ts index da55ed951c..eb1dacf825 100644 --- a/apps/desktop/src/main/menu/menubar.ts +++ b/apps/desktop/src/main/menu/menubar.ts @@ -3,6 +3,7 @@ import { Menu, MenuItemConstructorOptions } from "electron"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; +import { DesktopSettingsService } from "../../platform/services/desktop-settings.service"; import { isMac } from "../../utils"; import { UpdaterMain } from "../updater.main"; import { WindowMain } from "../window.main"; @@ -47,10 +48,12 @@ export class Menubar { constructor( i18nService: I18nService, messagingService: MessagingService, + desktopSettingsService: DesktopSettingsService, updaterMain: UpdaterMain, windowMain: WindowMain, webVaultUrl: string, appVersion: string, + hardwareAccelerationEnabled: boolean, updateRequest?: MenuUpdateRequest, ) { let isLocked = true; @@ -89,7 +92,9 @@ export class Menubar { new WindowMenu(i18nService, messagingService, windowMain), new HelpMenu( i18nService, + desktopSettingsService, webVaultUrl, + hardwareAccelerationEnabled, new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain), ), ];