diff --git a/jslib b/jslib index c395293e64..78d40d9f18 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit c395293e64d5e8e276ede7ed84649fadde60dcb0 +Subproject commit 78d40d9f18c23a185465d5fca238b258b2848193 diff --git a/src/app/send/send.component.ts b/src/app/send/send.component.ts index 2a683428b7..f2246cb77f 100644 --- a/src/app/send/send.component.ts +++ b/src/app/send/send.component.ts @@ -1,5 +1,3 @@ -import { remote } from 'electron'; - import { Component, NgZone, @@ -19,6 +17,7 @@ import { UserService } from 'jslib/abstractions/user.service'; import { SendComponent as BaseSendComponent } from 'jslib/angular/components/send/send.component'; import { BroadcasterService } from 'jslib/angular/services/broadcaster.service'; +import { invokeMenu, RendererMenuItem } from 'jslib/electron/utils'; import { SendView } from 'jslib/models/view/sendView'; @@ -112,18 +111,19 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro } viewSendMenu(send: SendView) { - const menu = new remote.Menu(); - menu.append(new remote.MenuItem({ + const menu: RendererMenuItem[] = []; + menu.push({ label: this.i18nService.t('copyLink'), click: () => this.copy(send), - })); - menu.append(new remote.MenuItem({ + }); + menu.push({ label: this.i18nService.t('delete'), click: async () => { await this.delete(send); await this.deletedSend(send); }, - })); - menu.popup({ window: remote.getCurrentWindow() }); + }); + + invokeMenu(menu); } } diff --git a/src/app/services.module.ts b/src/app/services.module.ts index eb21c8f3e2..c02c598676 100644 --- a/src/app/services.module.ts +++ b/src/app/services.module.ts @@ -1,5 +1,3 @@ -import { remote } from 'electron'; - import { APP_INITIALIZER, LOCALE_ID, @@ -12,7 +10,7 @@ import { ElectronLogService } from 'jslib/electron/services/electronLog.service' import { ElectronPlatformUtilsService } from 'jslib/electron/services/electronPlatformUtils.service'; import { ElectronRendererMessagingService } from 'jslib/electron/services/electronRendererMessaging.service'; import { ElectronRendererSecureStorageService } from 'jslib/electron/services/electronRendererSecureStorage.service'; -import { ElectronStorageService } from 'jslib/electron/services/electronStorage.service'; +import { ElectronRendererStorageService } from 'jslib/electron/services/electronRendererStorage.service'; import { isDev } from 'jslib/electron/utils'; import { DeviceType } from 'jslib/enums/deviceType'; @@ -94,7 +92,7 @@ const i18nService = new I18nService(window.navigator.language, './locales'); const stateService = new StateService(); const broadcasterService = new BroadcasterService(); const messagingService = new ElectronRendererMessagingService(broadcasterService); -const storageService: StorageServiceAbstraction = new ElectronStorageService(remote.app.getPath('userData')); +const storageService: StorageServiceAbstraction = new ElectronRendererStorageService(); const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, true, storageService); const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService(); const cryptoFunctionService: CryptoFunctionServiceAbstraction = new WebCryptoFunctionService(window, @@ -114,7 +112,7 @@ const cipherService = new CipherService(cryptoService, userService, settingsServ const folderService = new FolderService(cryptoService, userService, apiService, storageService, i18nService, cipherService); const collectionService = new CollectionService(cryptoService, userService, storageService, i18nService); -searchService = new SearchService(cipherService, logService); +searchService = new SearchService(cipherService, logService, i18nService); const sendService = new SendService(cryptoService, userService, apiService, fileUploadService, storageService, i18nService, cryptoFunctionService); const policyService = new PolicyService(userService, storageService); @@ -158,8 +156,11 @@ export function initFactory(): Function { htmlEl.classList.add('locale_' + i18nService.translationLocale); let theme = await storageService.get(ConstantsService.themeKey); if (theme == null) { - theme = platformUtilsService.getDevice() === DeviceType.MacOsDesktop && - remote.nativeTheme.shouldUseDarkColors ? 'dark' : 'light'; + if (platformUtilsService.getDevice() === DeviceType.MacOsDesktop) { + theme = await platformUtilsService.getDefaultSystemTheme(); + } else { + theme = 'light'; + } } htmlEl.classList.add('theme_' + theme); stateService.save(ConstantsService.disableFaviconKey, @@ -167,7 +168,7 @@ export function initFactory(): Function { let installAction = null; const installedVersion = await storageService.get(ConstantsService.installedVersionKey); - const currentVersion = platformUtilsService.getApplicationVersion(); + const currentVersion = await platformUtilsService.getApplicationVersion(); if (installedVersion == null) { installAction = 'install'; } else if (installedVersion !== currentVersion) { diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts index 9178e85736..08405bcc8e 100644 --- a/src/app/vault/vault.component.ts +++ b/src/app/vault/vault.component.ts @@ -1,5 +1,3 @@ -import { remote } from 'electron'; - import { ChangeDetectorRef, Component, @@ -26,7 +24,6 @@ import { AddEditComponent } from './add-edit.component'; import { AttachmentsComponent } from './attachments.component'; import { CiphersComponent } from './ciphers.component'; import { CollectionsComponent } from './collections.component'; -import { ExportComponent } from './export.component'; import { FolderAddEditComponent } from './folder-add-edit.component'; import { GroupingsComponent } from './groupings.component'; import { PasswordGeneratorComponent } from './password-generator.component'; @@ -40,7 +37,6 @@ import { EventType } from 'jslib/enums/eventType'; import { CipherView } from 'jslib/models/view/cipherView'; import { FolderView } from 'jslib/models/view/folderView'; -import { userError } from '@angular/compiler-cli/src/transformers/util'; import { EventService } from 'jslib/abstractions/event.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { MessagingService } from 'jslib/abstractions/messaging.service'; @@ -48,6 +44,7 @@ import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { SyncService } from 'jslib/abstractions/sync.service'; import { TotpService } from 'jslib/abstractions/totp.service'; import { UserService } from 'jslib/abstractions/user.service'; +import { invokeMenu, RendererMenuItem } from 'jslib/electron/utils'; const BroadcasterSubscriptionId = 'VaultComponent'; @@ -243,88 +240,90 @@ export class VaultComponent implements OnInit, OnDestroy { } viewCipherMenu(cipher: CipherView) { - const menu = new remote.Menu(); - menu.append(new remote.MenuItem({ - label: this.i18nService.t('view'), - click: () => this.functionWithChangeDetection(() => { - this.viewCipher(cipher); - }), - })); + const menu: RendererMenuItem[] = [ + { + label: this.i18nService.t('view'), + click: () => this.functionWithChangeDetection(() => { + this.viewCipher(cipher); + }), + }, + ]; if (!cipher.isDeleted) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('edit'), click: () => this.functionWithChangeDetection(() => { this.editCipher(cipher); }), - })); - menu.append(new remote.MenuItem({ + }); + menu.push({ label: this.i18nService.t('clone'), click: () => this.functionWithChangeDetection(() => { this.cloneCipher(cipher); }), - })); + }); } switch (cipher.type) { case CipherType.Login: if (cipher.login.canLaunch || cipher.login.username != null || cipher.login.password != null) { - menu.append(new remote.MenuItem({ type: 'separator' })); + menu.push({ type: 'separator' }); } if (cipher.login.canLaunch) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('launch'), click: () => this.platformUtilsService.launchUri(cipher.login.launchUri), - })); + }); } if (cipher.login.username != null) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('copyUsername'), click: () => this.copyValue(cipher.login.username, 'username'), - })); + }); } if (cipher.login.password != null && cipher.viewPassword) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('copyPassword'), click: () => { this.copyValue(cipher.login.password, 'password'); this.eventService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id); }, - })); + }); } if (cipher.login.hasTotp && (cipher.organizationUseTotp || this.userHasPremiumAccess)) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('copyVerificationCodeTotp'), click: async () => { const value = await this.totpService.getCode(cipher.login.totp); this.copyValue(value, 'verificationCodeTotp'); }, - })); + }); } break; case CipherType.Card: if (cipher.card.number != null || cipher.card.code != null) { - menu.append(new remote.MenuItem({ type: 'separator' })); + menu.push({ type: 'separator' }); } if (cipher.card.number != null) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('copyNumber'), click: () => this.copyValue(cipher.card.number, 'number'), - })); + }); } if (cipher.card.code != null) { - menu.append(new remote.MenuItem({ + menu.push({ label: this.i18nService.t('copySecurityCode'), click: () => { this.copyValue(cipher.card.code, 'securityCode'); this.eventService.collect(EventType.Cipher_ClientCopiedCardCode, cipher.id); }, - })); + }); } break; default: break; } - menu.popup({ window: remote.getCurrentWindow() }); + + invokeMenu(menu); } async editCipher(cipher: CipherView) { @@ -366,24 +365,27 @@ export class VaultComponent implements OnInit, OnDestroy { } addCipherOptions() { - const menu = new remote.Menu(); - menu.append(new remote.MenuItem({ - label: this.i18nService.t('typeLogin'), - click: () => this.addCipherWithChangeDetection(CipherType.Login), - })); - menu.append(new remote.MenuItem({ - label: this.i18nService.t('typeCard'), - click: () => this.addCipherWithChangeDetection(CipherType.Card), - })); - menu.append(new remote.MenuItem({ - label: this.i18nService.t('typeIdentity'), - click: () => this.addCipherWithChangeDetection(CipherType.Identity), - })); - menu.append(new remote.MenuItem({ - label: this.i18nService.t('typeSecureNote'), - click: () => this.addCipherWithChangeDetection(CipherType.SecureNote), - })); - menu.popup({ window: remote.getCurrentWindow() }); + const menu: RendererMenuItem[] = [ + { + label: this.i18nService.t('typeLogin'), + click: () => this.addCipherWithChangeDetection(CipherType.Login), + }, + { + label: this.i18nService.t('typeCard'), + click: () => this.addCipherWithChangeDetection(CipherType.Card), + }, + { + label: this.i18nService.t('typeIdentity'), + click: () => this.addCipherWithChangeDetection(CipherType.Identity), + }, + { + label: this.i18nService.t('typeSecureNote'), + click: () => this.addCipherWithChangeDetection(CipherType.SecureNote), + }, + + ]; + + invokeMenu(menu); } async savedCipher(cipher: CipherView) {