mirror of
https://github.com/bitwarden/browser
synced 2026-01-08 03:23:50 +00:00
Move desktop into apps/desktop
This commit is contained in:
87
apps/desktop/src/main/menu/menu.about.ts
Normal file
87
apps/desktop/src/main/menu/menu.about.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { UpdaterMain } from "jslib-electron/updater.main";
|
||||
import { isMacAppStore, isSnapStore, isWindowsStore } from "jslib-electron/utils";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class AboutMenu implements IMenubarMenu {
|
||||
readonly id: string = "about";
|
||||
|
||||
get label(): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
return [this.separator, this.checkForUpdates, this.aboutBitwarden];
|
||||
}
|
||||
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _updater: UpdaterMain;
|
||||
private readonly _window: BrowserWindow;
|
||||
private readonly _version: string;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
version: string,
|
||||
window: BrowserWindow,
|
||||
updater: UpdaterMain
|
||||
) {
|
||||
this._i18nService = i18nService;
|
||||
this._updater = updater;
|
||||
this._version = version;
|
||||
this._window = window;
|
||||
}
|
||||
|
||||
private get separator(): MenuItemConstructorOptions {
|
||||
return { type: "separator" };
|
||||
}
|
||||
|
||||
private get checkForUpdates(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "checkForUpdates",
|
||||
label: this.localize("checkForUpdates"),
|
||||
visible: !isWindowsStore() && !isSnapStore() && !isMacAppStore(),
|
||||
click: () => this.checkForUpdate(),
|
||||
};
|
||||
}
|
||||
|
||||
private get aboutBitwarden(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "aboutBitwarden",
|
||||
label: this.localize("aboutBitwarden"),
|
||||
click: async () => {
|
||||
const aboutInformation =
|
||||
this.localize("version", this._version) +
|
||||
"\nShell " +
|
||||
process.versions.electron +
|
||||
"\nRenderer " +
|
||||
process.versions.chrome +
|
||||
"\nNode " +
|
||||
process.versions.node +
|
||||
"\nArchitecture " +
|
||||
process.arch;
|
||||
const result = await dialog.showMessageBox(this._window, {
|
||||
title: "Bitwarden",
|
||||
message: "Bitwarden",
|
||||
detail: aboutInformation,
|
||||
type: "info",
|
||||
noLink: true,
|
||||
buttons: [this.localize("ok"), this.localize("copy")],
|
||||
});
|
||||
if (result.response === 1) {
|
||||
clipboard.writeText(aboutInformation);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private localize(s: string, p?: string) {
|
||||
return this._i18nService.t(s, p);
|
||||
}
|
||||
|
||||
private async checkForUpdate() {
|
||||
this._updater.checkForUpdate(true);
|
||||
}
|
||||
}
|
||||
115
apps/desktop/src/main/menu/menu.account.ts
Normal file
115
apps/desktop/src/main/menu/menu.account.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { BrowserWindow, dialog, MenuItemConstructorOptions, shell } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { isMacAppStore, isWindowsStore } from "jslib-electron/utils";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class AccountMenu implements IMenubarMenu {
|
||||
readonly id: string = "accountMenu";
|
||||
|
||||
get label(): string {
|
||||
return this.localize("account");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
this.premiumMembership,
|
||||
this.changeMasterPassword,
|
||||
this.twoStepLogin,
|
||||
this.fingerprintPhrase,
|
||||
];
|
||||
}
|
||||
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _messagingService: MessagingService;
|
||||
private readonly _webVaultUrl: string;
|
||||
private readonly _window: BrowserWindow;
|
||||
private readonly _isLocked: boolean;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
webVaultUrl: string,
|
||||
window: BrowserWindow,
|
||||
isLocked: boolean
|
||||
) {
|
||||
this._i18nService = i18nService;
|
||||
this._messagingService = messagingService;
|
||||
this._webVaultUrl = webVaultUrl;
|
||||
this._window = window;
|
||||
this._isLocked = isLocked;
|
||||
}
|
||||
|
||||
private get premiumMembership(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("premiumMembership"),
|
||||
click: () => this.sendMessage("openPremium"),
|
||||
id: "premiumMembership",
|
||||
visible: !isWindowsStore() && !isMacAppStore(),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get changeMasterPassword(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("changeMasterPass"),
|
||||
id: "changeMasterPass",
|
||||
click: async () => {
|
||||
const result = await dialog.showMessageBox(this._window, {
|
||||
title: this.localize("changeMasterPass"),
|
||||
message: this.localize("changeMasterPass"),
|
||||
detail: this.localize("changeMasterPasswordConfirmation"),
|
||||
buttons: [this.localize("yes"), this.localize("no")],
|
||||
cancelId: 1,
|
||||
defaultId: 0,
|
||||
noLink: true,
|
||||
});
|
||||
if (result.response === 0) {
|
||||
shell.openExternal(this._webVaultUrl);
|
||||
}
|
||||
},
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get twoStepLogin(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("twoStepLogin"),
|
||||
id: "twoStepLogin",
|
||||
click: async () => {
|
||||
const result = await dialog.showMessageBox(this._window, {
|
||||
title: this.localize("twoStepLogin"),
|
||||
message: this.localize("twoStepLogin"),
|
||||
detail: this.localize("twoStepLoginConfirmation"),
|
||||
buttons: [this.localize("yes"), this.localize("no")],
|
||||
cancelId: 1,
|
||||
defaultId: 0,
|
||||
noLink: true,
|
||||
});
|
||||
if (result.response === 0) {
|
||||
shell.openExternal(this._webVaultUrl);
|
||||
}
|
||||
},
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get fingerprintPhrase(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("fingerprintPhrase"),
|
||||
id: "fingerprintPhrase",
|
||||
click: () => this.sendMessage("showFingerprintPhrase"),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
|
||||
private sendMessage(message: string, args?: any) {
|
||||
this._messagingService.send(message, args);
|
||||
}
|
||||
}
|
||||
113
apps/desktop/src/main/menu/menu.bitwarden.ts
Normal file
113
apps/desktop/src/main/menu/menu.bitwarden.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { BrowserWindow, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { UpdaterMain } from "jslib-electron/updater.main";
|
||||
import { isMac } from "jslib-electron/utils";
|
||||
|
||||
import { FirstMenu } from "./menu.first";
|
||||
import { MenuAccount } from "./menu.updater";
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
// AKA: "FirstMenu" or "MacMenu" - the first menu that shows on all macOs apps
|
||||
export class BitwardenMenu extends FirstMenu implements IMenubarMenu {
|
||||
readonly id: string = "bitwarden";
|
||||
readonly label: string = "Bitwarden";
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
const items = [this.aboutBitwarden, this.checkForUpdates];
|
||||
if (this.aboutBitwarden.visible === true || this.checkForUpdates.visible === true) {
|
||||
items.push(this.separator);
|
||||
}
|
||||
items.push(this.settings);
|
||||
items.push(this.lock);
|
||||
items.push(this.lockAll);
|
||||
items.push(this.logOut);
|
||||
items.push(this.separator);
|
||||
items.push(this.services);
|
||||
|
||||
if (
|
||||
this.hideBitwarden.visible === true ||
|
||||
this.hideOthers.visible === true ||
|
||||
this.showAll.visible === true
|
||||
) {
|
||||
items.push(this.separator);
|
||||
}
|
||||
|
||||
items.push(this.hideBitwarden);
|
||||
items.push(this.hideOthers);
|
||||
items.push(this.showAll);
|
||||
|
||||
if (this.quitBitwarden.visible === true) {
|
||||
items.push(this.separator);
|
||||
}
|
||||
items.push(this.quitBitwarden);
|
||||
return items;
|
||||
}
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
updater: UpdaterMain,
|
||||
window: BrowserWindow,
|
||||
accounts: { [userId: string]: MenuAccount },
|
||||
isLocked: boolean
|
||||
) {
|
||||
super(i18nService, messagingService, updater, window, accounts, isLocked);
|
||||
}
|
||||
|
||||
private get aboutBitwarden(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "aboutBitwarden",
|
||||
label: this.localize("aboutBitwarden"),
|
||||
role: "about",
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
|
||||
private get services(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "services",
|
||||
label: this.localize("services"),
|
||||
role: "services",
|
||||
submenu: [],
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
|
||||
private get hideBitwarden(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "hideBitwarden",
|
||||
label: this.localize("hideBitwarden"),
|
||||
role: "hide",
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
|
||||
private get hideOthers(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "hideOthers",
|
||||
label: this.localize("hideOthers"),
|
||||
role: "hideOthers",
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
|
||||
private get showAll(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "showAll",
|
||||
label: this.localize("showAll"),
|
||||
role: "unhide",
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
|
||||
private get quitBitwarden(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "quitBitwarden",
|
||||
label: this.localize("quitBitwarden"),
|
||||
role: "quit",
|
||||
visible: isMac(),
|
||||
};
|
||||
}
|
||||
}
|
||||
131
apps/desktop/src/main/menu/menu.edit.ts
Normal file
131
apps/desktop/src/main/menu/menu.edit.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class EditMenu implements IMenubarMenu {
|
||||
readonly id: string = "editMenu";
|
||||
|
||||
get label(): string {
|
||||
return this.localize("edit");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
this.undo,
|
||||
this.redo,
|
||||
this.separator,
|
||||
this.cut,
|
||||
this.copy,
|
||||
this.paste,
|
||||
this.separator,
|
||||
this.selectAll,
|
||||
this.separator,
|
||||
this.copyUsername,
|
||||
this.copyPassword,
|
||||
this.copyVerificationCodeTotp,
|
||||
];
|
||||
}
|
||||
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _messagingService: MessagingService;
|
||||
private readonly _isLocked: boolean;
|
||||
|
||||
constructor(i18nService: I18nService, messagingService: MessagingService, isLocked: boolean) {
|
||||
this._i18nService = i18nService;
|
||||
this._messagingService = messagingService;
|
||||
this._isLocked = isLocked;
|
||||
}
|
||||
|
||||
private get undo(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "undo",
|
||||
label: this.localize("undo"),
|
||||
role: "undo",
|
||||
};
|
||||
}
|
||||
|
||||
private get redo(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "redo",
|
||||
label: this.localize("redo"),
|
||||
role: "redo",
|
||||
};
|
||||
}
|
||||
|
||||
private get separator(): MenuItemConstructorOptions {
|
||||
return { type: "separator" };
|
||||
}
|
||||
|
||||
private get cut(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "cut",
|
||||
label: this.localize("cut"),
|
||||
role: "cut",
|
||||
};
|
||||
}
|
||||
|
||||
private get copy(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "copy",
|
||||
label: this.localize("copy"),
|
||||
role: "copy",
|
||||
};
|
||||
}
|
||||
|
||||
private get paste(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "paste",
|
||||
label: this.localize("paste"),
|
||||
role: "paste",
|
||||
};
|
||||
}
|
||||
|
||||
private get selectAll(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "selectAll",
|
||||
label: this.localize("selectAll"),
|
||||
role: "selectAll",
|
||||
};
|
||||
}
|
||||
|
||||
private get copyUsername(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("copyUsername"),
|
||||
id: "copyUsername",
|
||||
click: () => this.sendMessage("copyUsername"),
|
||||
accelerator: "CmdOrCtrl+U",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get copyPassword(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("copyPassword"),
|
||||
id: "copyPassword",
|
||||
click: () => this.sendMessage("copyPassword"),
|
||||
accelerator: "CmdOrCtrl+P",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get copyVerificationCodeTotp(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("copyVerificationCodeTotp"),
|
||||
id: "copyTotp",
|
||||
click: () => this.sendMessage("copyTotp"),
|
||||
accelerator: "CmdOrCtrl+T",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
|
||||
private sendMessage(message: string) {
|
||||
this._messagingService.send(message);
|
||||
}
|
||||
}
|
||||
141
apps/desktop/src/main/menu/menu.file.ts
Normal file
141
apps/desktop/src/main/menu/menu.file.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { BrowserWindow, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { UpdaterMain } from "jslib-electron/updater.main";
|
||||
import { isMac, isMacAppStore } from "jslib-electron/utils";
|
||||
|
||||
import { FirstMenu } from "./menu.first";
|
||||
import { MenuAccount } from "./menu.updater";
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class FileMenu extends FirstMenu implements IMenubarMenu {
|
||||
readonly id: string = "fileMenu";
|
||||
|
||||
get label(): string {
|
||||
return this.localize("file");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
let items = [
|
||||
this.addNewLogin,
|
||||
this.addNewItem,
|
||||
this.addNewFolder,
|
||||
this.separator,
|
||||
this.syncVault,
|
||||
this.exportVault,
|
||||
];
|
||||
|
||||
if (!isMac()) {
|
||||
items = [
|
||||
...items,
|
||||
...[
|
||||
this.separator,
|
||||
this.settings,
|
||||
this.lock,
|
||||
this.lockAll,
|
||||
this.logOut,
|
||||
this.separator,
|
||||
this.quitBitwarden,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
updater: UpdaterMain,
|
||||
window: BrowserWindow,
|
||||
accounts: { [userId: string]: MenuAccount },
|
||||
isLocked: boolean
|
||||
) {
|
||||
super(i18nService, messagingService, updater, window, accounts, isLocked);
|
||||
}
|
||||
|
||||
private get addNewLogin(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("addNewLogin"),
|
||||
click: () => this.sendMessage("newLogin"),
|
||||
accelerator: "CmdOrCtrl+N",
|
||||
id: "addNewLogin",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get addNewItem(): MenuItemConstructorOptions {
|
||||
return {
|
||||
label: this.localize("addNewItem"),
|
||||
id: "addNewItem",
|
||||
submenu: this.addNewItemSubmenu,
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get addNewItemSubmenu(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
{
|
||||
id: "typeLogin",
|
||||
label: this.localize("typeLogin"),
|
||||
click: () => this.sendMessage("newLogin"),
|
||||
accelerator: "CmdOrCtrl+Shift+L",
|
||||
},
|
||||
{
|
||||
id: "typeCard",
|
||||
label: this.localize("typeCard"),
|
||||
click: () => this.sendMessage("newCard"),
|
||||
accelerator: "CmdOrCtrl+Shift+C",
|
||||
},
|
||||
{
|
||||
id: "typeIdentity",
|
||||
label: this.localize("typeIdentity"),
|
||||
click: () => this.sendMessage("newIdentity"),
|
||||
accelerator: "CmdOrCtrl+Shift+I",
|
||||
},
|
||||
{
|
||||
id: "typeSecureNote",
|
||||
label: this.localize("typeSecureNote"),
|
||||
click: () => this.sendMessage("newSecureNote"),
|
||||
accelerator: "CmdOrCtrl+Shift+S",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private get addNewFolder(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "addNewFolder",
|
||||
label: this.localize("addNewFolder"),
|
||||
click: () => this.sendMessage("newFolder"),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get syncVault(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "syncVault",
|
||||
label: this.localize("syncVault"),
|
||||
click: () => this.sendMessage("syncVault"),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get exportVault(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "exportVault",
|
||||
label: this.localize("exportVault"),
|
||||
click: () => this.sendMessage("exportVault"),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get quitBitwarden(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "quitBitwarden",
|
||||
label: this.localize("quitBitwarden"),
|
||||
visible: !isMacAppStore(),
|
||||
role: "quit",
|
||||
};
|
||||
}
|
||||
}
|
||||
152
apps/desktop/src/main/menu/menu.first.ts
Normal file
152
apps/desktop/src/main/menu/menu.first.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
import { BrowserWindow, dialog, MenuItem, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { UpdaterMain } from "jslib-electron/updater.main";
|
||||
import { isMacAppStore, isSnapStore, isWindowsStore } from "jslib-electron/utils";
|
||||
|
||||
import { MenuAccount } from "./menu.updater";
|
||||
|
||||
export class FirstMenu {
|
||||
protected readonly _i18nService: I18nService;
|
||||
protected readonly _updater: UpdaterMain;
|
||||
protected readonly _messagingService: MessagingService;
|
||||
protected readonly _accounts: { [userId: string]: MenuAccount };
|
||||
protected readonly _window: BrowserWindow;
|
||||
protected readonly _isLocked: boolean;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
updater: UpdaterMain,
|
||||
window: BrowserWindow,
|
||||
accounts: { [userId: string]: MenuAccount },
|
||||
isLocked: boolean
|
||||
) {
|
||||
this._i18nService = i18nService;
|
||||
this._updater = updater;
|
||||
this._messagingService = messagingService;
|
||||
this._window = window;
|
||||
this._accounts = accounts;
|
||||
this._isLocked = isLocked;
|
||||
}
|
||||
|
||||
protected get hasAccounts(): boolean {
|
||||
return this._accounts != null && Object.keys(this._accounts).length > 0;
|
||||
}
|
||||
|
||||
protected get checkForUpdates(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "checkForUpdates",
|
||||
label: this.localize("checkForUpdates"),
|
||||
click: (menuItem) => this.checkForUpdate(menuItem),
|
||||
visible: !isMacAppStore() && !isWindowsStore() && !isSnapStore(),
|
||||
};
|
||||
}
|
||||
|
||||
protected get separator(): MenuItemConstructorOptions {
|
||||
return {
|
||||
type: "separator",
|
||||
};
|
||||
}
|
||||
|
||||
protected get settings(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "settings",
|
||||
label: this.localize(process.platform === "darwin" ? "preferences" : "settings"),
|
||||
click: () => this.sendMessage("openSettings"),
|
||||
accelerator: "CmdOrCtrl+,",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
protected get lock(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "lock",
|
||||
label: this.localize("lockVault"),
|
||||
submenu: this.lockSubmenu,
|
||||
enabled: this.hasAccounts,
|
||||
};
|
||||
}
|
||||
|
||||
protected get lockSubmenu(): MenuItemConstructorOptions[] {
|
||||
const value: MenuItemConstructorOptions[] = [];
|
||||
for (const userId in this._accounts) {
|
||||
if (userId == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
value.push({
|
||||
label: this._accounts[userId].email,
|
||||
id: `lockNow_${this._accounts[userId].userId}`,
|
||||
click: () => this.sendMessage("lockVault", { userId: this._accounts[userId].userId }),
|
||||
enabled: !this._accounts[userId].isLocked,
|
||||
visible: this._accounts[userId].isAuthenticated,
|
||||
});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected get lockAll(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "lockAllNow",
|
||||
label: this.localize("lockAllVaults"),
|
||||
click: () => this.sendMessage("lockAllVaults"),
|
||||
accelerator: "CmdOrCtrl+L",
|
||||
enabled: this.hasAccounts,
|
||||
};
|
||||
}
|
||||
|
||||
protected get logOut(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "logOut",
|
||||
label: this.localize("logOut"),
|
||||
submenu: this.logOutSubmenu,
|
||||
enabled: this.hasAccounts,
|
||||
};
|
||||
}
|
||||
|
||||
protected get logOutSubmenu(): MenuItemConstructorOptions[] {
|
||||
const value: MenuItemConstructorOptions[] = [];
|
||||
for (const userId in this._accounts) {
|
||||
if (userId == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
value.push({
|
||||
label: this._accounts[userId].email,
|
||||
id: `logOut_${this._accounts[userId].userId}`,
|
||||
click: async () => {
|
||||
const result = await dialog.showMessageBox(this._window, {
|
||||
title: this.localize("logOut"),
|
||||
message: this.localize("logOut"),
|
||||
detail: this.localize("logOutConfirmation"),
|
||||
buttons: [this.localize("logOut"), this.localize("cancel")],
|
||||
cancelId: 1,
|
||||
defaultId: 0,
|
||||
noLink: true,
|
||||
});
|
||||
if (result.response === 0) {
|
||||
this.sendMessage("logout", { userId: this._accounts[userId].userId });
|
||||
}
|
||||
},
|
||||
visible: this._accounts[userId].isAuthenticated,
|
||||
});
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
|
||||
protected async checkForUpdate(menuItem: MenuItem) {
|
||||
menuItem.enabled = false;
|
||||
this._updater.checkForUpdate(true);
|
||||
menuItem.enabled = true;
|
||||
}
|
||||
|
||||
protected sendMessage(message: string, args?: any) {
|
||||
this._messagingService.send(message, args);
|
||||
}
|
||||
}
|
||||
234
apps/desktop/src/main/menu/menu.help.ts
Normal file
234
apps/desktop/src/main/menu/menu.help.ts
Normal file
@@ -0,0 +1,234 @@
|
||||
import { shell, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { isMacAppStore, isWindowsStore } from "jslib-electron/utils";
|
||||
|
||||
import { AboutMenu } from "./menu.about";
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class HelpMenu implements IMenubarMenu {
|
||||
readonly id: string = "help";
|
||||
|
||||
get label(): string {
|
||||
return this.localize("help");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
const items = [
|
||||
this.getHelp,
|
||||
this.contactUs,
|
||||
this.fileBugReport,
|
||||
this.legal,
|
||||
this.separator,
|
||||
this.followUs,
|
||||
this.separator,
|
||||
this.goToWebVault,
|
||||
this.separator,
|
||||
this.getMobileApp,
|
||||
this.getBrowserExtension,
|
||||
];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private get contactUs(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "contactUs",
|
||||
label: this.localize("contactUs"),
|
||||
click: () => shell.openExternal("https://bitwarden.com/contact"),
|
||||
};
|
||||
}
|
||||
|
||||
private get getHelp(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "getHelp",
|
||||
label: this.localize("getHelp"),
|
||||
click: () => shell.openExternal("https://bitwarden.com/help"),
|
||||
};
|
||||
}
|
||||
|
||||
private get fileBugReport(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "fileBugReport",
|
||||
label: this.localize("fileBugReport"),
|
||||
click: () => shell.openExternal("https://github.com/bitwarden/desktop/issues"),
|
||||
};
|
||||
}
|
||||
|
||||
private get legal(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "legal",
|
||||
label: this.localize("legal"),
|
||||
visible: isMacAppStore(),
|
||||
submenu: this.legalSubmenu,
|
||||
};
|
||||
}
|
||||
|
||||
private get legalSubmenu(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
{
|
||||
id: "termsOfService",
|
||||
label: this.localize("termsOfService"),
|
||||
click: () => shell.openExternal("https://bitwarden.com/terms/"),
|
||||
},
|
||||
{
|
||||
id: "privacyPolicy",
|
||||
label: this.localize("privacyPolicy"),
|
||||
click: () => shell.openExternal("https://bitwarden.com/privacy/"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private get separator(): MenuItemConstructorOptions {
|
||||
return { type: "separator" };
|
||||
}
|
||||
|
||||
private get followUs(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "followUs",
|
||||
label: this.localize("followUs"),
|
||||
submenu: this.followUsSubmenu,
|
||||
};
|
||||
}
|
||||
|
||||
private get followUsSubmenu(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
{
|
||||
id: "blog",
|
||||
label: this.localize("blog"),
|
||||
click: () => shell.openExternal("https://blog.bitwarden.com"),
|
||||
},
|
||||
{
|
||||
id: "twitter",
|
||||
label: "Twitter",
|
||||
click: () => shell.openExternal("https://twitter.com/bitwarden"),
|
||||
},
|
||||
{
|
||||
id: "facebook",
|
||||
label: "Facebook",
|
||||
click: () => shell.openExternal("https://www.facebook.com/bitwarden/"),
|
||||
},
|
||||
{
|
||||
id: "github",
|
||||
label: "GitHub",
|
||||
click: () => shell.openExternal("https://github.com/bitwarden"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private get goToWebVault(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "goToWebVault",
|
||||
label: this.localize("goToWebVault"),
|
||||
click: () => shell.openExternal(this._webVaultUrl),
|
||||
};
|
||||
}
|
||||
|
||||
private get getMobileApp(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "getMobileApp",
|
||||
label: this.localize("getMobileApp"),
|
||||
visible: !isWindowsStore(),
|
||||
submenu: this.getMobileAppSubmenu,
|
||||
};
|
||||
}
|
||||
|
||||
private get getMobileAppSubmenu(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
{
|
||||
id: "iOS",
|
||||
label: "iOS",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://itunes.apple.com/app/" + "bitwarden-free-password-manager/id1137397744?mt=8"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "android",
|
||||
label: "Android",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://play.google.com/store/apps/" + "details?id=com.x8bit.bitwarden"
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private get getBrowserExtension(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "getBrowserExtension",
|
||||
label: this.localize("getBrowserExtension"),
|
||||
visible: !isWindowsStore(),
|
||||
submenu: this.getBrowserExtensionSubmenu,
|
||||
};
|
||||
}
|
||||
|
||||
private get getBrowserExtensionSubmenu(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
{
|
||||
id: "chrome",
|
||||
label: "Chrome",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://chrome.google.com/webstore/detail/" +
|
||||
"bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "firefox",
|
||||
label: "Firefox",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://addons.mozilla.org/firefox/addon/" + "bitwarden-password-manager/"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "firefox",
|
||||
label: "Opera",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://addons.opera.com/extensions/details/" + "bitwarden-free-password-manager/"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "firefox",
|
||||
label: "Edge",
|
||||
click: () => {
|
||||
shell.openExternal(
|
||||
"https://microsoftedge.microsoft.com/addons/" +
|
||||
"detail/jbkfoedolllekgbhcbcoahefnbanhhlh"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "safari",
|
||||
label: "Safari",
|
||||
click: () => {
|
||||
shell.openExternal("https://bitwarden.com/download/");
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
}
|
||||
52
apps/desktop/src/main/menu/menu.main.ts
Normal file
52
apps/desktop/src/main/menu/menu.main.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { app, Menu } from "electron";
|
||||
|
||||
import { BaseMenu } from "jslib-electron/baseMenu";
|
||||
|
||||
import { Main } from "../../main";
|
||||
|
||||
import { MenuUpdateRequest } from "./menu.updater";
|
||||
import { Menubar } from "./menubar";
|
||||
|
||||
const cloudWebVaultUrl = "https://vault.bitwarden.com";
|
||||
|
||||
export class MenuMain extends BaseMenu {
|
||||
constructor(private main: Main) {
|
||||
super(main.i18nService, main.windowMain);
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.initContextMenu();
|
||||
await this.setMenu();
|
||||
}
|
||||
|
||||
async updateApplicationMenuState(updateRequest: MenuUpdateRequest) {
|
||||
await this.setMenu(updateRequest);
|
||||
}
|
||||
|
||||
private async setMenu(updateRequest?: MenuUpdateRequest) {
|
||||
Menu.setApplicationMenu(
|
||||
new Menubar(
|
||||
this.main.i18nService,
|
||||
this.main.messagingService,
|
||||
this.main.updaterMain,
|
||||
this.windowMain,
|
||||
await this.getWebVaultUrl(),
|
||||
app.getVersion(),
|
||||
updateRequest
|
||||
).menu
|
||||
);
|
||||
}
|
||||
|
||||
private async getWebVaultUrl() {
|
||||
let webVaultUrl = cloudWebVaultUrl;
|
||||
const urlsObj: any = await this.main.stateService.getEnvironmentUrls();
|
||||
if (urlsObj != null) {
|
||||
if (urlsObj.base != null) {
|
||||
webVaultUrl = urlsObj.base;
|
||||
} else if (urlsObj.webVault != null) {
|
||||
webVaultUrl = urlsObj.webVault;
|
||||
}
|
||||
}
|
||||
return webVaultUrl;
|
||||
}
|
||||
}
|
||||
12
apps/desktop/src/main/menu/menu.updater.ts
Normal file
12
apps/desktop/src/main/menu/menu.updater.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export class MenuUpdateRequest {
|
||||
hideChangeMasterPassword: boolean;
|
||||
activeUserId: string;
|
||||
accounts: { [userId: string]: MenuAccount };
|
||||
}
|
||||
|
||||
export class MenuAccount {
|
||||
isAuthenticated: boolean;
|
||||
isLocked: boolean;
|
||||
userId: string;
|
||||
email: string;
|
||||
}
|
||||
135
apps/desktop/src/main/menu/menu.view.ts
Normal file
135
apps/desktop/src/main/menu/menu.view.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class ViewMenu implements IMenubarMenu {
|
||||
readonly id: "viewMenu";
|
||||
|
||||
get label(): string {
|
||||
return this.localize("view");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
return [
|
||||
this.searchVault,
|
||||
this.separator,
|
||||
this.generator,
|
||||
this.passwordHistory,
|
||||
this.separator,
|
||||
this.zoomIn,
|
||||
this.zoomOut,
|
||||
this.resetZoom,
|
||||
this.separator,
|
||||
this.toggleFullscreen,
|
||||
this.separator,
|
||||
this.reload,
|
||||
this.toggleDevTools,
|
||||
];
|
||||
}
|
||||
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _messagingService: MessagingService;
|
||||
private readonly _isLocked: boolean;
|
||||
|
||||
constructor(i18nService: I18nService, messagingService: MessagingService, isLocked: boolean) {
|
||||
this._i18nService = i18nService;
|
||||
this._messagingService = messagingService;
|
||||
this._isLocked = isLocked;
|
||||
}
|
||||
|
||||
private get searchVault(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "searchVault",
|
||||
label: this.localize("searchVault"),
|
||||
click: () => this.sendMessage("focusSearch"),
|
||||
accelerator: "CmdOrCtrl+F",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get separator(): MenuItemConstructorOptions {
|
||||
return { type: "separator" };
|
||||
}
|
||||
|
||||
private get generator(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "generator",
|
||||
label: this.localize("generator"),
|
||||
click: () => this.sendMessage("openGenerator"),
|
||||
accelerator: "CmdOrCtrl+G",
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get passwordHistory(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "passwordHistory",
|
||||
label: this.localize("passwordHistory"),
|
||||
click: () => this.sendMessage("openPasswordHistory"),
|
||||
enabled: !this._isLocked,
|
||||
};
|
||||
}
|
||||
|
||||
private get zoomIn(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "zoomIn",
|
||||
label: this.localize("zoomIn"),
|
||||
role: "zoomIn",
|
||||
accelerator: "CmdOrCtrl+=",
|
||||
};
|
||||
}
|
||||
|
||||
private get zoomOut(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "zoomOut",
|
||||
label: this.localize("zoomOut"),
|
||||
role: "zoomOut",
|
||||
accelerator: "CmdOrCtrl+-",
|
||||
};
|
||||
}
|
||||
|
||||
private get resetZoom(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "resetZoom",
|
||||
label: this.localize("resetZoom"),
|
||||
role: "resetZoom",
|
||||
accelerator: "CmdOrCtrl+0",
|
||||
};
|
||||
}
|
||||
|
||||
private get toggleFullscreen(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "toggleFullScreen",
|
||||
label: this.localize("toggleFullScreen"),
|
||||
role: "togglefullscreen",
|
||||
};
|
||||
}
|
||||
|
||||
private get reload(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "reload",
|
||||
label: this.localize("reload"),
|
||||
role: "forceReload",
|
||||
};
|
||||
}
|
||||
|
||||
private get toggleDevTools(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "toggleDevTools",
|
||||
label: this.localize("toggleDevTools"),
|
||||
role: "toggleDevTools",
|
||||
accelerator: "F12",
|
||||
};
|
||||
}
|
||||
|
||||
private localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
|
||||
private sendMessage(message: string) {
|
||||
this._messagingService.send(message);
|
||||
}
|
||||
}
|
||||
105
apps/desktop/src/main/menu/menu.window.ts
Normal file
105
apps/desktop/src/main/menu/menu.window.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { isMac } from "jslib-electron/utils";
|
||||
import { WindowMain } from "jslib-electron/window.main";
|
||||
|
||||
import { IMenubarMenu } from "./menubar";
|
||||
|
||||
export class WindowMenu implements IMenubarMenu {
|
||||
readonly id: string;
|
||||
|
||||
get label(): string {
|
||||
return this.localize("window");
|
||||
}
|
||||
|
||||
get items(): MenuItemConstructorOptions[] {
|
||||
const items = [this.minimize, this.hideToMenu, this.alwaysOnTop];
|
||||
|
||||
if (isMac()) {
|
||||
items.push(this.zoom, this.separator, this.bringAllToFront);
|
||||
}
|
||||
|
||||
items.push(this.separator, this.close);
|
||||
return items;
|
||||
}
|
||||
|
||||
private readonly _i18nService: I18nService;
|
||||
private readonly _messagingService: MessagingService;
|
||||
private readonly _window: WindowMain;
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
windowMain: WindowMain
|
||||
) {
|
||||
this._i18nService = i18nService;
|
||||
this._messagingService = messagingService;
|
||||
this._window = windowMain;
|
||||
}
|
||||
|
||||
private get minimize(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "minimize",
|
||||
label: this.localize("minimize"),
|
||||
role: "minimize",
|
||||
};
|
||||
}
|
||||
|
||||
private get hideToMenu(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "hideToMenu",
|
||||
label: this.localize(isMac() ? "hideToMenuBar" : "hideToTray"),
|
||||
click: () => this.sendMessage("hideToTray"),
|
||||
accelerator: "CmdOrCtrl+Shift+M",
|
||||
};
|
||||
}
|
||||
|
||||
private get alwaysOnTop(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "alwaysOnTop",
|
||||
label: this.localize("alwaysOnTop"),
|
||||
type: "checkbox",
|
||||
checked: this._window.win.isAlwaysOnTop(),
|
||||
click: () => this._window.toggleAlwaysOnTop(),
|
||||
accelerator: "CmdOrCtrl+Shift+T",
|
||||
};
|
||||
}
|
||||
|
||||
private get zoom(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "zoom",
|
||||
label: this.localize("zoom"),
|
||||
role: "zoom",
|
||||
};
|
||||
}
|
||||
|
||||
private get separator(): MenuItemConstructorOptions {
|
||||
return { type: "separator" };
|
||||
}
|
||||
|
||||
private get bringAllToFront(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "bringAllToFront",
|
||||
label: this.localize("bringAllToFront"),
|
||||
role: "front",
|
||||
};
|
||||
}
|
||||
|
||||
private get close(): MenuItemConstructorOptions {
|
||||
return {
|
||||
id: "close",
|
||||
label: this.localize("close"),
|
||||
role: "close",
|
||||
};
|
||||
}
|
||||
|
||||
private localize(s: string) {
|
||||
return this._i18nService.t(s);
|
||||
}
|
||||
|
||||
private sendMessage(message: string, args?: any) {
|
||||
this._messagingService.send(message, args);
|
||||
}
|
||||
}
|
||||
100
apps/desktop/src/main/menu/menubar.ts
Normal file
100
apps/desktop/src/main/menu/menubar.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { Menu, MenuItemConstructorOptions } from "electron";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { UpdaterMain } from "jslib-electron/updater.main";
|
||||
import { isMac } from "jslib-electron/utils";
|
||||
import { WindowMain } from "jslib-electron/window.main";
|
||||
|
||||
import { AboutMenu } from "./menu.about";
|
||||
import { AccountMenu } from "./menu.account";
|
||||
import { BitwardenMenu } from "./menu.bitwarden";
|
||||
import { EditMenu } from "./menu.edit";
|
||||
import { FileMenu } from "./menu.file";
|
||||
import { HelpMenu } from "./menu.help";
|
||||
import { MenuUpdateRequest } from "./menu.updater";
|
||||
import { ViewMenu } from "./menu.view";
|
||||
import { WindowMenu } from "./menu.window";
|
||||
|
||||
export interface IMenubarMenu {
|
||||
id: string;
|
||||
label: string;
|
||||
visible?: boolean; // Assumes true if null
|
||||
items: MenuItemConstructorOptions[];
|
||||
}
|
||||
|
||||
export class Menubar {
|
||||
private readonly items: IMenubarMenu[];
|
||||
|
||||
get menu(): Menu {
|
||||
const template: MenuItemConstructorOptions[] = [];
|
||||
if (this.items != null) {
|
||||
this.items.forEach((item: IMenubarMenu) => {
|
||||
if (item != null) {
|
||||
template.push({
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
submenu: item.items,
|
||||
visible: item.visible ?? true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return Menu.buildFromTemplate(template);
|
||||
}
|
||||
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
messagingService: MessagingService,
|
||||
updaterMain: UpdaterMain,
|
||||
windowMain: WindowMain,
|
||||
webVaultUrl: string,
|
||||
appVersion: string,
|
||||
updateRequest?: MenuUpdateRequest
|
||||
) {
|
||||
let isLocked = true;
|
||||
if (
|
||||
updateRequest != null &&
|
||||
updateRequest.accounts != null &&
|
||||
updateRequest.activeUserId != null
|
||||
) {
|
||||
isLocked = updateRequest.accounts[updateRequest.activeUserId]?.isLocked ?? true;
|
||||
}
|
||||
|
||||
this.items = [
|
||||
new FileMenu(
|
||||
i18nService,
|
||||
messagingService,
|
||||
updaterMain,
|
||||
windowMain.win,
|
||||
updateRequest?.accounts,
|
||||
isLocked
|
||||
),
|
||||
new EditMenu(i18nService, messagingService, isLocked),
|
||||
new ViewMenu(i18nService, messagingService, isLocked),
|
||||
new AccountMenu(i18nService, messagingService, webVaultUrl, windowMain.win, isLocked),
|
||||
new WindowMenu(i18nService, messagingService, windowMain),
|
||||
new HelpMenu(
|
||||
i18nService,
|
||||
webVaultUrl,
|
||||
new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain)
|
||||
),
|
||||
];
|
||||
|
||||
if (isMac()) {
|
||||
this.items = [
|
||||
...[
|
||||
new BitwardenMenu(
|
||||
i18nService,
|
||||
messagingService,
|
||||
updaterMain,
|
||||
windowMain.win,
|
||||
updateRequest?.accounts,
|
||||
isLocked
|
||||
),
|
||||
],
|
||||
...this.items,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user