diff --git a/packages/neuron-ui/src/services/remote/app.ts b/packages/neuron-ui/src/services/remote/app.ts index 315ae51784..96276e7e74 100644 --- a/packages/neuron-ui/src/services/remote/app.ts +++ b/packages/neuron-ui/src/services/remote/app.ts @@ -1,8 +1,8 @@ import { controllerMethodWrapper } from './controllerMethodWrapper' -const CONTROLLER_NAME = 'app' +const CONTROLLER_NAME = 'api' export const getNeuronWalletState = controllerMethodWrapper(CONTROLLER_NAME)(controller => () => - controller.getInitState() + controller.loadInitData() ) export const handleViewError = controllerMethodWrapper(CONTROLLER_NAME)(controller => (errorMessage: string) => diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts new file mode 100644 index 0000000000..fce639074d --- /dev/null +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -0,0 +1,121 @@ +import { take } from 'rxjs/operators' + +import env from 'env' +import i18n from 'utils/i18n' +import { popContextMenu } from './app/menu' +import { showWindow } from './app/show-window' +import { TransactionsController, WalletsController, SyncInfoController } from 'controllers' +import NetworksService from 'services/networks' +import WalletsService from 'services/wallets' +import SkipDataAndType from 'services/settings/skip-data-and-type' +import { ConnectionStatusSubject } from 'models/subjects/node' +import { SystemScriptSubject } from 'models/subjects/system-script' +import { ResponseCode } from 'utils/const' + +export default class ApiController { + public static loadInitData = async () => { + const walletsService = WalletsService.getInstance() + const networksService = NetworksService.getInstance() + const [ + currentWallet = null, + wallets = [], + currentNetworkID = '', + networks = [], + syncedBlockNumber = '0', + connectionStatus = false, + codeHash = '', + ] = await Promise.all([ + walletsService.getCurrent(), + walletsService.getAll(), + networksService.getCurrentID(), + networksService.getAll(), + + SyncInfoController.currentBlockNumber() + .then(res => { + if (res.status) { + return res.result.currentBlockNumber + } + return '0' + }) + .catch(() => '0'), + new Promise(resolve => { + ConnectionStatusSubject.pipe(take(1)).subscribe( + status => { + resolve(status) + }, + () => { + resolve(false) + }, + ) + }), + new Promise(resolve => { + SystemScriptSubject.pipe(take(1)).subscribe(({ codeHash: currentCodeHash }) => resolve(currentCodeHash)) + }), + ]) + + const minerAddresses = await Promise.all( + wallets.map(({ id }) => + WalletsController.getAllAddresses(id).then(addrRes => { + if (addrRes.result) { + const minerAddr = addrRes.result.find(addr => addr.type === 0 && addr.index === 0) + if (minerAddr) { + return { + address: minerAddr.address, + identifier: minerAddr.identifier, + } + } + } + return undefined + }), + ), + ) + const addresses: Controller.Address[] = await (currentWallet + ? WalletsController.getAllAddresses(currentWallet.id).then(res => res.result) + : []) + + const transactions = currentWallet + ? await TransactionsController.getAllByKeywords({ + pageNo: 1, + pageSize: 15, + keywords: '', + walletID: currentWallet.id, + }).then(res => res.result) + : [] + + const skipDataAndType = SkipDataAndType.getInstance().get() + + const initState = { + currentWallet, + wallets: [...wallets.map(({ name, id }, idx: number) => ({ id, name, minerAddress: minerAddresses[idx] }))], + currentNetworkID, + networks, + addresses, + transactions, + syncedBlockNumber, + connectionStatus, + codeHash, + skipDataAndType, + } + + return { status: ResponseCode.Success, result: initState } + } + + public static handleViewError = (error: string) => { + if (env.isDevMode) { + console.error(error) + } + } + + public static isMainWindow = (winID: number) => { + // TODO: Fix this + return winID === 0 // AppController.mainWindow && winID === AppController.mainWindow.id + } + + public static async contextMenu(params: { type: string; id: string }) { + return popContextMenu(params) + } + + public static async showTransactionDetails(hash: string) { + showWindow(`${env.mainURL}#/transaction/${hash}`, i18n.t(`messageBox.transaction.title`, { hash })) + } +} diff --git a/packages/neuron-wallet/src/controllers/app/index.ts b/packages/neuron-wallet/src/controllers/app/index.ts index 4d5fed0aaf..3d52c5eebc 100644 --- a/packages/neuron-wallet/src/controllers/app/index.ts +++ b/packages/neuron-wallet/src/controllers/app/index.ts @@ -1,67 +1,47 @@ import path from 'path' -import { app as electronApp, remote, shell, MenuItem, dialog, BrowserWindow } from 'electron' +import { app as electronApp, remote, BrowserWindow } from 'electron' import windowStateKeeper from 'electron-window-state' -import { take } from 'rxjs/operators' import env from 'env' -import { updateApplicationMenu, popContextMenu } from './menu' -import { TransactionsController, WalletsController, SyncInfoController, UpdateController } from 'controllers' -import NetworksService from 'services/networks' -import WalletsService from 'services/wallets' -import SkipDataAndType from 'services/settings/skip-data-and-type' -import { ResponseCode } from 'utils/const' +import { updateApplicationMenu } from './menu' import logger from 'utils/logger' -import i18n from 'utils/i18n' -import CommandSubject from 'models/subjects/command' -import { ConnectionStatusSubject } from 'models/subjects/node' -import { SystemScriptSubject } from 'models/subjects/system-script' import { subscribe } from './subscribe' -enum URL { - Preference = '/settings/general', - CreateWallet = '/wizard/mnemonic/create', - ImportMnemonic = '/wizard/mnemonic/import', - ImportKeystore = '/keystore/import', -} - -// Acts as a middle man so that subscribe doesn't have to know AppController -const eventResponder = { - sendMessage: (channel: string, arg: any) => { - AppController.sendMessage(channel, arg) - }, - - updateMenu: () => { - AppController.updateApplicationMenu() - } -} -subscribe(eventResponder) - const app = electronApp || (remote && remote.app) export default class AppController { - public static mainWindow: BrowserWindow | null + public mainWindow: BrowserWindow | null + + constructor() { + this.mainWindow = null + subscribe(this) + } - public static sendMessage = (channel: string, obj: any) => { - if (AppController.mainWindow) { - AppController.mainWindow.webContents.send(channel, obj) + public sendMessage = (channel: string, obj: any) => { + if (this.mainWindow) { + this.mainWindow.webContents.send(channel, obj) } } - public static openWindow = () => { - if (AppController.mainWindow) { + public updateMenu = () => { + updateApplicationMenu(this.mainWindow) + } + + public openWindow = () => { + if (this.mainWindow) { return } - AppController.createWindow() + this.createWindow() } - static createWindow = () => { + createWindow = () => { const windowState = windowStateKeeper({ defaultWidth: 1366, defaultHeight: 768, }) - const mainWindow = new BrowserWindow({ + this.mainWindow = new BrowserWindow({ x: windowState.x, y: windowState.y, width: windowState.width, @@ -78,219 +58,37 @@ export default class AppController { }, }) - windowState.manage(mainWindow) + windowState.manage(this.mainWindow) - mainWindow.on('ready-to-show', () => { - if (AppController.mainWindow) { - AppController.mainWindow.show() - AppController.mainWindow.focus() + this.mainWindow.on('ready-to-show', () => { + if (this.mainWindow) { + this.mainWindow.show() + this.mainWindow.focus() logger.info('The main window is ready to show') } else { logger.error('The main window is not initialized on ready to show') } }) - mainWindow.on('closed', () => { + this.mainWindow.on('closed', () => { if (process.platform !== 'darwin') { app.quit() } - if (AppController.mainWindow) { - AppController.mainWindow.removeAllListeners() - AppController.mainWindow = null + if (this.mainWindow) { + this.mainWindow.removeAllListeners() + this.mainWindow = null } }) - mainWindow.on('focus', () => { - AppController.updateApplicationMenu() + this.mainWindow.on('focus', () => { + this.updateMenu() }) - mainWindow.on('blur', () => { - AppController.updateApplicationMenu() + this.mainWindow.on('blur', () => { + this.updateMenu() }) - mainWindow.loadURL(env.mainURL) - AppController.mainWindow = mainWindow - AppController.updateApplicationMenu() - } - - public static getInitState = async () => { - const walletsService = WalletsService.getInstance() - const networksService = NetworksService.getInstance() - const [ - currentWallet = null, - wallets = [], - currentNetworkID = '', - networks = [], - syncedBlockNumber = '0', - connectionStatus = false, - codeHash = '', - ] = await Promise.all([ - walletsService.getCurrent(), - walletsService.getAll(), - networksService.getCurrentID(), - networksService.getAll(), - - SyncInfoController.currentBlockNumber() - .then(res => { - if (res.status) { - return res.result.currentBlockNumber - } - return '0' - }) - .catch(() => '0'), - new Promise(resolve => { - ConnectionStatusSubject.pipe(take(1)).subscribe( - status => { - resolve(status) - }, - () => { - resolve(false) - }, - ) - }), - new Promise(resolve => { - SystemScriptSubject.pipe(take(1)).subscribe(({ codeHash: currentCodeHash }) => resolve(currentCodeHash)) - }), - ]) - - const minerAddresses = await Promise.all( - wallets.map(({ id }) => - WalletsController.getAllAddresses(id).then(addrRes => { - if (addrRes.result) { - const minerAddr = addrRes.result.find(addr => addr.type === 0 && addr.index === 0) - if (minerAddr) { - return { - address: minerAddr.address, - identifier: minerAddr.identifier, - } - } - } - return undefined - }), - ), - ) - const addresses: Controller.Address[] = await (currentWallet - ? WalletsController.getAllAddresses(currentWallet.id).then(res => res.result) - : []) - - const transactions = currentWallet - ? await TransactionsController.getAllByKeywords({ - pageNo: 1, - pageSize: 15, - keywords: '', - walletID: currentWallet.id, - }).then(res => res.result) - : [] - - const skipDataAndType = SkipDataAndType.getInstance().get() - - const initState = { - currentWallet, - wallets: [...wallets.map(({ name, id }, idx: number) => ({ id, name, minerAddress: minerAddresses[idx] }))], - currentNetworkID, - networks, - addresses, - transactions, - syncedBlockNumber, - connectionStatus, - codeHash, - skipDataAndType, - } - - return { status: ResponseCode.Success, result: initState } - } - - public static handleViewError = (error: string) => { - if (env.isDevMode) { - console.error(error) - } - } - - public static isMainWindow = (winID: number) => { - return AppController.mainWindow && winID === AppController.mainWindow.id - } - - public static updateApplicationMenu = () => { - updateApplicationMenu() - } - - public static async contextMenu(params: { type: string; id: string }) { - return popContextMenu(params) - } - - public static toggleAddressBook() { - if (AppController.mainWindow) { - CommandSubject.next({ - winID: AppController.mainWindow.id, - type: 'toggle-address-book', - payload: null, - }) - } - } - - public static navTo(url: string) { - if (AppController.mainWindow) { - CommandSubject.next({ winID: AppController.mainWindow.id, type: 'nav', payload: url }) - } - } - - public static openExternal(url: string) { - shell.openExternal(url) - } - - public static showAbout() { - const options = { - type: 'info', - title: app.getName(), - message: app.getName(), - detail: app.getVersion(), - buttons: ['OK'], - cancelId: 0, - } - dialog.showMessageBox(options) - } - - public static checkUpdates(menuItem: MenuItem) { - new UpdateController().checkUpdates(menuItem) - } - - public static showPreference() { - AppController.navTo(URL.Preference) - } - - public static createWallet() { - AppController.navTo(URL.CreateWallet) - } - - public static importWallet(type: 'mnemonic' | 'keystore') { - if (type === 'mnemonic') { - AppController.navTo(URL.ImportMnemonic) - } else if (type === 'keystore') { - AppController.navTo(URL.ImportKeystore) - } - } - - public static async showTransactionDetails(hash: string) { - const win = new BrowserWindow({ - width: 1200, - show: false, - webPreferences: { - preload: path.join(__dirname, './preload.js'), - }, - }) - win.loadURL(`${env.mainURL}#/transaction/${hash}`) - win.on('ready-to-show', () => { - win.setTitle(i18n.t(`messageBox.transaction.title`, { hash })) - win.show() - win.focus() - }) - } -} - -/* eslint-disable */ -declare global { - module Controller { - type AppMethod = Exclude + this.mainWindow.loadURL(env.mainURL) + this.updateMenu() } } -/* eslint-enable */ diff --git a/packages/neuron-wallet/src/controllers/app/menu.ts b/packages/neuron-wallet/src/controllers/app/menu.ts index abb09651de..d0631722f1 100644 --- a/packages/neuron-wallet/src/controllers/app/menu.ts +++ b/packages/neuron-wallet/src/controllers/app/menu.ts @@ -1,13 +1,19 @@ -import { app, BrowserWindow, dialog, MenuItemConstructorOptions, clipboard, Menu, MenuItem, MessageBoxOptions, MessageBoxReturnValue } from 'electron' +import { app, shell, BrowserWindow, dialog, MenuItemConstructorOptions, clipboard, Menu, MenuItem, MessageBoxOptions, MessageBoxReturnValue } from 'electron' import { bech32Address, AddressPrefix, AddressType } from '@nervosnetwork/ckb-sdk-utils' import i18n from 'utils/i18n' import env from 'env' -import AppController from 'controllers/app' +import { UpdateController } from 'controllers' +import { showWindow } from './show-window' import NetworksService from 'services/networks' import WalletsService from 'services/wallets' +import CommandSubject from 'models/subjects/command' -// TODO: Refactor this to remove circular reference between menu and app controller. -// Perhaps menu should only do dispatching. +enum URL { + Preference = '/settings/general', + CreateWallet = '/wizard/mnemonic/create', + ImportMnemonic = '/wizard/mnemonic/import', + ImportKeystore = '/keystore/import', +} enum ExternalURL { Website = 'https://www.nervos.org/', @@ -15,23 +21,48 @@ enum ExternalURL { Issues = 'https://github.com/nervosnetwork/neuron/issues', } -const isMac = process.platform === 'darwin' - const separator: MenuItemConstructorOptions = { type: 'separator', } -const networksService = NetworksService.getInstance() - const showMessageBox = (options: MessageBoxOptions, callback?: (returnValue: MessageBoxReturnValue) => void) => { dialog.showMessageBox(options).then(callback) } -const generateTemplate = () => { +const showAbout = () => { + const options = { + type: 'info', + title: app.getName(), + message: app.getName(), + detail: app.getVersion(), + buttons: ['OK'], + cancelId: 0, + } + dialog.showMessageBox(options) +} + +const navTo = (url: string) => { + const window = BrowserWindow.getFocusedWindow() + if (window) { + CommandSubject.next({ winID: window.id, type: 'nav', payload: url }) + } +} + +const requestPassword = (walletID: string, actionType: 'delete-wallet' | 'backup-wallet') => { + const window = BrowserWindow.getFocusedWindow() + if (window) { + CommandSubject.next({ winID: window.id, type: actionType, payload: walletID }) + } +} + +const updateApplicationMenu = (mainWindow: BrowserWindow | null) => { + const isMac = process.platform === 'darwin' + let isMainWindow = mainWindow == BrowserWindow.getFocusedWindow() + const walletsService = WalletsService.getInstance() + const wallets = walletsService.getAll().map(({ id, name }) => ({ id, name })) const currentWallet = walletsService.getCurrent() const hasCurrentWallet = currentWallet !== undefined - const isMainWindow = AppController && BrowserWindow.getFocusedWindow() === AppController.mainWindow const appMenuItem: MenuItemConstructorOptions = { id: 'app', @@ -43,12 +74,12 @@ const generateTemplate = () => { app: app.getName(), }), role: 'about', - click: () => { AppController.showAbout() }, + click: () => { showAbout() }, }, { enabled: isMainWindow, label: i18n.t('application-menu.neuron.check-updates'), - click: (menuItem: MenuItem) => { AppController.checkUpdates(menuItem) } + click: (menuItem: MenuItem) => { new UpdateController().checkUpdates(menuItem) } }, separator, { @@ -56,7 +87,7 @@ const generateTemplate = () => { enabled: isMainWindow, label: i18n.t('application-menu.neuron.preferences'), accelerator: 'CmdOrCtrl+,', - click: () => { AppController.showPreference() } + click: () => { navTo(URL.Preference) } }, separator, { @@ -68,16 +99,26 @@ const generateTemplate = () => { ], } + const selectWalletMenu: MenuItemConstructorOptions[] = wallets.map(wallet => { + return { + id: wallet.id, + label: wallet.name, + type: 'radio', + checked: currentWallet && wallet.id === currentWallet.id, + click: () => { WalletsService.getInstance().setCurrent(wallet.id) } + } + }) + const walletMenuItem: MenuItemConstructorOptions = { id: 'wallet', label: i18n.t('application-menu.wallet.label'), enabled: isMainWindow, submenu: [ - { id: 'select', label: i18n.t('application-menu.wallet.select'), submenu: [] }, + { id: 'select', label: i18n.t('application-menu.wallet.select'), submenu: selectWalletMenu }, { id: 'create', label: i18n.t('application-menu.wallet.create-new'), - click: () => { AppController.createWallet() } + click: () => { navTo(URL.CreateWallet) } }, { id: 'import', @@ -86,12 +127,12 @@ const generateTemplate = () => { { id: 'import-with-mnemonic', label: i18n.t('application-menu.wallet.import-mnemonic'), - click: () => { AppController.importWallet('mnemonic') } + click: () => { navTo(URL.ImportMnemonic) } }, { id: 'import-with-keystore', label: i18n.t('application-menu.wallet.import-keystore'), - click: () => { AppController.importWallet('keystore') }, + click: () => { navTo(URL.ImportKeystore )}, }, ], }, @@ -104,7 +145,7 @@ const generateTemplate = () => { if (!currentWallet) { return } - walletsService.requestPassword(currentWallet.id, 'backup-wallet') + requestPassword(currentWallet.id, 'backup-wallet') }, }, { @@ -115,7 +156,7 @@ const generateTemplate = () => { if (!currentWallet) { return } - walletsService.requestPassword(currentWallet.id, 'delete-wallet') + requestPassword(currentWallet.id, 'delete-wallet') }, }, ], @@ -156,7 +197,15 @@ const generateTemplate = () => { { label: i18n.t('application-menu.view.address-book'), enabled: isMainWindow && hasCurrentWallet, - click: () => { AppController.toggleAddressBook() }, + click: () => { + if (mainWindow) { + CommandSubject.next({ + winID: mainWindow.id, + type: 'toggle-address-book', + payload: null, + }) + } + }, accelerator: 'CmdOrCtrl+B', }, ], @@ -181,15 +230,15 @@ const generateTemplate = () => { const helpSubmenu: MenuItemConstructorOptions[] = [ { label: 'Nervos', - click: () => { AppController.openExternal(ExternalURL.Website) } + click: () => { shell.openExternal(ExternalURL.Website) } }, { label: i18n.t('application-menu.help.source-code'), - click: () => { AppController.openExternal(ExternalURL.Repository) } + click: () => { shell.openExternal(ExternalURL.Repository) } }, { label: i18n.t('application-menu.help.report-issue'), - click: () => { AppController.openExternal(ExternalURL.Issues) } + click: () => { shell.openExternal(ExternalURL.Issues) } }, ] if (!isMac) { @@ -197,11 +246,11 @@ const generateTemplate = () => { helpSubmenu.push({ id: 'preference', label: i18n.t('application-menu.help.settings'), - click: () => { AppController.showPreference() } + click: () => { navTo(URL.Preference) } }) helpSubmenu.push({ label: i18n.t('application-menu.neuron.check-updates'), - click: (menuItem: MenuItem) => { AppController.checkUpdates(menuItem) } + click: (menuItem: MenuItem) => { new UpdateController().checkUpdates(menuItem) } }) helpSubmenu.push({ id: 'about', @@ -209,7 +258,7 @@ const generateTemplate = () => { app: app.getName(), }), role: 'about', - click: () => { AppController.showAbout() } + click: () => { showAbout() } }) } @@ -246,14 +295,17 @@ const generateTemplate = () => { if (isMac) { applicationMenuTemplate.unshift(appMenuItem) } - return applicationMenuTemplate + + const menu = Menu.buildFromTemplate(applicationMenuTemplate) + + Menu.setApplicationMenu(menu) } const contextMenuTemplate: { [key: string]: (id: string) => Promise } = { - copyMainnetAddress: async (identifier: string) => { - const address = bech32Address(identifier, { + copyMainnetAddress: async (publicKeyHash: string) => { + const address = bech32Address(publicKeyHash, { prefix: AddressPrefix.Mainnet, type: AddressType.HashIdx, codeHashIndex: '0x00', @@ -266,6 +318,7 @@ const contextMenuTemplate: { ] }, networkList: async (id: string) => { + const networksService = NetworksService.getInstance() const [network, currentNetworkID] = await Promise.all([ networksService.get(id).catch(() => null), networksService.getCurrentID().catch(() => null), @@ -298,7 +351,7 @@ const contextMenuTemplate: { { label: i18n.t('contextMenu.edit'), enabled: !isDefault, - click: () => { AppController.navTo(`/network/${id}`) } + click: () => { navTo(`/network/${id}`) } }, { label: i18n.t('contextMenu.delete'), @@ -355,15 +408,15 @@ const contextMenuTemplate: { }, { label: i18n.t('contextMenu.backup'), - click: async () => { walletsService.requestPassword(id, 'backup-wallet') } + click: async () => { requestPassword(id, 'backup-wallet') } }, { label: i18n.t('contextMenu.edit'), - click: () => { AppController.navTo(`/editwallet/${id}`) } + click: () => { navTo(`/editwallet/${id}`) } }, { label: i18n.t('contextMenu.delete'), - click: async () => { walletsService.requestPassword(id, 'delete-wallet') } + click: async () => { requestPassword(id, 'delete-wallet') } }, ] }, @@ -380,11 +433,11 @@ const contextMenuTemplate: { }, { label: i18n.t('contextMenu.request-payment'), - click: () => { AppController.navTo(`/receive/${address}`) } + click: () => { navTo(`/receive/${address}`) } }, { label: i18n.t('contextMenu.view-on-explorer'), - click: () => { AppController.openExternal(`${env.explorer}/address/${address}`) } + click: () => { shell.openExternal(`${env.explorer}/address/${address}`) } }, ] }, @@ -392,7 +445,9 @@ const contextMenuTemplate: { return [ { label: i18n.t('contextMenu.detail'), - click: () => AppController.showTransactionDetails(hash), + click: () => { + showWindow(`${env.mainURL}#/transaction/${hash}`, i18n.t(`messageBox.transaction.title`, { hash })) + } }, { label: i18n.t('contextMenu.copy-transaction-hash'), @@ -400,37 +455,12 @@ const contextMenuTemplate: { }, { label: i18n.t('contextMenu.view-on-explorer'), - click: () => { AppController.openExternal(`${env.explorer}/transaction/${hash}`) } + click: () => { shell.openExternal(`${env.explorer}/transaction/${hash}`) } }, ] }, } -const updateApplicationMenu = () => { - const menu = Menu.buildFromTemplate(generateTemplate()) - const selectMenu = menu.getMenuItemById('select') - - const walletsService = WalletsService.getInstance() - const wallets = walletsService.getAll().map(({ id, name }) => ({ id, name })) - const currentWallet = walletsService.getCurrent() - const isMainWindow = AppController && BrowserWindow.getFocusedWindow() === AppController.mainWindow - - wallets.forEach(wallet => { - selectMenu.submenu.append( - new MenuItem({ - id: wallet.id, - label: wallet.name, - type: 'radio', - checked: currentWallet && wallet.id === currentWallet.id, - click: () => { WalletsService.getInstance().setCurrent(wallet.id) } - }) - ) - }) - selectMenu.enabled = isMainWindow && wallets.length > 0 - - Menu.setApplicationMenu(menu) -} - const popContextMenu = async (params: { type: string; id: string }) => { if (!params || params.id === undefined) { return diff --git a/packages/neuron-wallet/src/controllers/app/show-window.ts b/packages/neuron-wallet/src/controllers/app/show-window.ts new file mode 100644 index 0000000000..ff989bf5f2 --- /dev/null +++ b/packages/neuron-wallet/src/controllers/app/show-window.ts @@ -0,0 +1,22 @@ +import { BrowserWindow } from 'electron' +import path from 'path' + +const showWindow = (url: string, title: string): BrowserWindow => { + const win = new BrowserWindow({ + width: 1200, + show: false, + webPreferences: { + preload: path.join(__dirname, './preload.js'), + }, + }) + win.loadURL(url) + win.on('ready-to-show', () => { + win.setTitle(title) + win.show() + win.focus() + }) + + return win +} + +export { showWindow } diff --git a/packages/neuron-wallet/src/controllers/index.ts b/packages/neuron-wallet/src/controllers/index.ts index 95009cbeae..0c20b50af4 100644 --- a/packages/neuron-wallet/src/controllers/index.ts +++ b/packages/neuron-wallet/src/controllers/index.ts @@ -6,6 +6,8 @@ import SyncInfoController from './sync-info' import SkipDataAndTypeController from './skip-data-and-type' import UpdateController from './update' +import ApiController from './api' + export { AppController, NetworksController, @@ -13,5 +15,6 @@ export { TransactionsController, SyncInfoController, SkipDataAndTypeController, - UpdateController + UpdateController, + ApiController } diff --git a/packages/neuron-wallet/src/controllers/wallets.ts b/packages/neuron-wallet/src/controllers/wallets.ts index 76cc794054..677823bad3 100644 --- a/packages/neuron-wallet/src/controllers/wallets.ts +++ b/packages/neuron-wallet/src/controllers/wallets.ts @@ -1,5 +1,5 @@ import fs from 'fs' -import { dialog, SaveDialogReturnValue } from 'electron' +import { dialog, SaveDialogReturnValue, BrowserWindow } from 'electron' import WalletsService, { Wallet, WalletProperties, FileKeystoreWallet } from 'services/wallets' import Keystore from 'models/keys/keystore' import Keychain from 'models/keys/keychain' @@ -21,7 +21,6 @@ import i18n from 'utils/i18n' import AddressService from 'services/addresses' import WalletCreatedSubject from 'models/subjects/wallet-created-subject' import logger from 'utils/logger' -import AppController from './app' /** * @class WalletsController @@ -286,7 +285,7 @@ export default class WalletsController { const keystore = wallet.loadKeystore() return new Promise(resolve => { - dialog.showSaveDialog(AppController.mainWindow!, { title: i18n.t('messages.save-keystore'), defaultPath: wallet.name + '.json' }).then( + dialog.showSaveDialog(BrowserWindow.getFocusedWindow()!, { title: i18n.t('messages.save-keystore'), defaultPath: wallet.name + '.json' }).then( (returnValue: SaveDialogReturnValue) => { if (returnValue.filePath) { fs.writeFileSync(returnValue.filePath, JSON.stringify(keystore)) diff --git a/packages/neuron-wallet/src/main.ts b/packages/neuron-wallet/src/main.ts index fab79275c8..550f1588eb 100644 --- a/packages/neuron-wallet/src/main.ts +++ b/packages/neuron-wallet/src/main.ts @@ -5,9 +5,7 @@ import initConnection from 'database/address/ormconfig' import createSyncBlockTask from 'startup/sync-block-task/create' import { changeLanguage } from 'utils/i18n' -const openWindow = () => { - AppController.openWindow() -} +const appController = new AppController() app.on('ready', async () => { changeLanguage(app.getLocale()) @@ -15,7 +13,7 @@ app.on('ready', async () => { await initConnection() createSyncBlockTask() - openWindow() + appController.openWindow() }) -app.on('activate', openWindow) +app.on('activate', appController.openWindow) diff --git a/packages/neuron-wallet/src/services/wallets.ts b/packages/neuron-wallet/src/services/wallets.ts index 507d614f69..76189cb253 100644 --- a/packages/neuron-wallet/src/services/wallets.ts +++ b/packages/neuron-wallet/src/services/wallets.ts @@ -13,8 +13,6 @@ import AddressDbChangedSubject from 'models/subjects/address-db-changed-subject' import AddressesUsedSubject from 'models/subjects/addresses-used-subject' import { WalletListSubject, CurrentWalletSubject } from 'models/subjects/wallets' import dataUpdateSubject from 'models/subjects/data-update' -import CommandSubject from 'models/subjects/command' -import AppController from 'controllers/app' import CellsService from 'services/cells' import { AddressPrefix } from '@nervosnetwork/ckb-sdk-utils' @@ -466,14 +464,4 @@ export default class WalletService { privateKey: `0x${masterKeychain.derivePath(path).privateKey.toString('hex')}`, })) } - - public requestPassword = (walletID: string, actionType: 'delete-wallet' | 'backup-wallet') => { - if (AppController.mainWindow) { - CommandSubject.next({ - winID: AppController.mainWindow.id, - type: actionType, - payload: walletID, - }) - } - } } diff --git a/packages/neuron-wallet/tests-e2e/application/preload.js b/packages/neuron-wallet/tests-e2e/application/preload.js index 301bbedd45..ae45152b8e 100644 --- a/packages/neuron-wallet/tests-e2e/application/preload.js +++ b/packages/neuron-wallet/tests-e2e/application/preload.js @@ -6,11 +6,13 @@ const services_networks = __importDefault(require("../../dist/services/networks" electron.ipcMain.on('E2E_EDIT_WALLET', function (event, arg) { const walletId = arg[0]; + // TODO: fix navTo controllers_app.default.navTo(`/editwallet/${walletId}`); }); electron.ipcMain.on('E2E_EDIT_NETWORK', function (event, arg) { const networkId = arg[0]; + // TODO: fix navTo controllers_app.default.navTo(`/network/${networkId}`); });