"Fossies" - the Fresh Open Source Software Archive

Member "deltachat-desktop-1.3.4/src/main/ipc.ts" (18 May 2020, 12337 Bytes) of package /linux/misc/deltachat-desktop-1.3.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) TypeScript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "ipc.ts": 1.3.3_vs_1.3.4.

    1 import { C } from 'deltachat-node'
    2 import { app as rawApp, dialog, ipcMain, shell } from 'electron'
    3 import { copy, copyFile, emptyDir, ensureDir, pathExists } from 'fs-extra'
    4 import { extname, join, relative } from 'path'
    5 import { getLogger } from '../shared/logger'
    6 import { AppState, Credentials, LocalSettings } from '../shared/shared-types'
    7 import { getConfigPath } from './application-constants'
    8 import { credential_config } from './deltachat/login'
    9 import loadTranslations from './load-translations'
   10 import { LogHandler } from './log-handler'
   11 import {
   12   DeltaChatAccount,
   13   getLogins,
   14   getNewAccountPath,
   15   removeAccount,
   16 } from './logins'
   17 import { init as refreshMenu } from './menu'
   18 import { ExtendedAppMainProcess } from './types'
   19 import * as mainWindow from './windows/main'
   20 import { openHelpWindow } from './windows/help'
   21 
   22 const log = getLogger('main/ipc')
   23 const DeltaChatController: typeof import('./deltachat/controller').default = (() => {
   24   try {
   25     return require('./deltachat/controller').default
   26   } catch (error) {
   27     log.critical(
   28       "Fatal: The DeltaChat Module couldn't be loaded. Please check if all dependencies for deltachat-core are installed!",
   29       error
   30     )
   31     const { dialog } = require('electron')
   32     const { getLogsPath } = require('./application-constants')
   33     dialog.showErrorBox(
   34       'Fatal Error',
   35       `The DeltaChat Module couldn't be loaded.\n Please check if all dependencies for deltachat-core are installed!\n The Log file is located in this folder: ${getLogsPath()}`
   36     )
   37   }
   38 })()
   39 
   40 const app = rawApp as ExtendedAppMainProcess
   41 
   42 export function init(cwd: string, state: AppState, logHandler: LogHandler) {
   43   const main = mainWindow
   44   const dcController = new DeltaChatController(cwd, state.saved)
   45 
   46   dcController.on('ready', async (credentials: Credentials) => {
   47     if (!state.logins.find(({ addr }) => addr === credentials.addr)) {
   48       state.logins = await getLogins()
   49     }
   50     // update saved / last account + make sure no passwords are present
   51     state.saved.credentials = {
   52       ...credentials,
   53       mail_pw: undefined,
   54       send_pw: undefined,
   55     } as Credentials
   56     app.saveState()
   57   })
   58 
   59   dcController.on('logout', () => {
   60     state.saved.credentials = null
   61     app.saveState()
   62   })
   63 
   64   ipcMain.once('ipcReady', e => {
   65     app.ipcReady = true
   66     app.emit('ipcReady')
   67   })
   68 
   69   ipcMain.on('all', (e, ...args: any[]) => {
   70     log.debug('Renderer event:', e, ...args)
   71   })
   72 
   73   // ipcMain.on('setAspectRatio', (e, ...args) => main.setAspectRatio(...args))
   74   // ipcMain.on('setBounds', (e, ...args:any[]) => main.setBounds(...args))
   75   ipcMain.on('setProgress', (e, progress: number) => main.setProgress(progress))
   76   ipcMain.on('show', () => main.show())
   77   // ipcMain.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args))
   78   ipcMain.on('chooseLanguage', (e, locale: string) => {
   79     loadTranslations(locale)
   80     dcController.loginController.setCoreStrings(txCoreStrings())
   81     refreshMenu(logHandler)
   82   })
   83 
   84   ipcMain.once('frontendReady', () => app.emit('frontendReady'))
   85 
   86   /* dispatch a method on DC core */
   87   ipcMain.on(
   88     'EVENT_DC_DISPATCH',
   89     (e: any, identifier: number, methodName: string, args: any[]) => {
   90       if (!Array.isArray(args)) args = [args]
   91       log.debug('EVENT_DC_DISPATCH: ', methodName, args)
   92       dcController.callMethod(e, methodName, args)
   93     }
   94   )
   95 
   96   /* dispatch a method on DC core with result passed to callback */
   97   ipcMain.on(
   98     'EVENT_DC_DISPATCH_CB',
   99     async (e: any, identifier: number, methodName: string, args: any[]) => {
  100       if (!Array.isArray(args)) args = [args]
  101       log.debug(`EVENT_DC_DISPATCH_CB (${identifier}) : ${methodName} ${args}`)
  102       const returnValue = await dcController.callMethod(e, methodName, args)
  103       main.send(
  104         `EVENT_DD_DISPATCH_RETURN_${identifier}_${methodName}`,
  105         returnValue
  106       )
  107     }
  108   )
  109 
  110   ipcMain.on('handleLogMessage', (e, channel, level, stacktrace, ...args) =>
  111     logHandler.log(channel, level, stacktrace, ...args)
  112   )
  113 
  114   ipcMain.on('login', (_e: any, credentials) => {
  115     dcController.loginController.login(
  116       getNewAccountPath(credentials.addr),
  117       credentials,
  118       sendStateToRenderer,
  119       txCoreStrings()
  120     )
  121   })
  122 
  123   ipcMain.on('loadAccount', (e, login: DeltaChatAccount) => {
  124     dcController.loginController.login(
  125       login.path,
  126       { addr: login.addr },
  127       sendStateToRenderer,
  128       txCoreStrings()
  129     )
  130   })
  131 
  132   const updateLogins = async () => {
  133     state.logins = await getLogins()
  134     sendStateToRenderer()
  135   }
  136 
  137   ipcMain.on('forgetLogin', async (_e: any, login: DeltaChatAccount) => {
  138     try {
  139       await removeAccount(login.path)
  140       main.send('success', 'successfully forgot account')
  141     } catch (error) {
  142       main.send('error', error.message)
  143     }
  144     updateLogins()
  145   })
  146 
  147   ipcMain.on('updateLogins', updateLogins)
  148 
  149   ipcMain.on('getMessage', (e, msgId: number) => {
  150     e.returnValue = dcController.messageList.messageIdToJson(msgId)
  151   })
  152 
  153   /* unused
  154   ipcMain.on('getChatContacts', (e, chatId) => {
  155     e.returnValue = dc.chat.getChatContacts(chatId)
  156   })
  157   */
  158 
  159   ipcMain.on('backupImport', (e, fileName) =>
  160     dcController.backup.import(fileName)
  161   )
  162   ipcMain.on('backupExport', (e, dir) => dcController.backup.export(dir))
  163 
  164   ipcMain.on('setConfig', (e, key, value) => {
  165     e.returnValue = dcController.settings.setConfig(key, value)
  166   })
  167 
  168   ipcMain.on('logout', () => dcController.loginController.logout())
  169 
  170   ipcMain.on('initiateKeyTransfer', e => {
  171     dcController.autocrypt.initiateKeyTransfer((err, resp) => {
  172       main.send('initiateKeyTransferResp', err, resp)
  173     })
  174   })
  175 
  176   ipcMain.on('continueKeyTransfer', (e, messageId, setupCode) => {
  177     dcController.autocrypt.continueKeyTransfer(messageId, setupCode, err => {
  178       main.send('continueKeyTransferResp', err)
  179     })
  180   })
  181 
  182   ipcMain.on('saveFile', (e, source, target) => {
  183     copyFile(source, target, err => {
  184       if (err) main.send('error', err.message)
  185     })
  186   })
  187 
  188   ipcMain.on('ondragstart', (event, filePath) => {
  189     event.sender.startDrag({ file: filePath, icon: null })
  190   })
  191 
  192   ipcMain.on('render', sendStateToRenderer)
  193 
  194   const updateDesktopSetting = (
  195     e: Electron.IpcMainEvent,
  196     key: keyof LocalSettings,
  197     value: string
  198   ) => {
  199     const { saved } = app.state
  200     ;(saved as any)[key] = value
  201     app.saveState({ saved })
  202     sendStateToRenderer()
  203   }
  204   ipcMain.on('updateDesktopSetting', updateDesktopSetting)
  205 
  206   ipcMain.on('saveLastChatId', (e, chatId) => {
  207     const { lastChats } = app.state.saved
  208     lastChats[dcController.credentials.addr] = chatId
  209     // don't save to disk, because this is already done on close and it might block
  210     // we can ignore the crash case, because a crash isn't supposed to happen
  211     // and it's not important data
  212   })
  213 
  214   ipcMain.on('getLastSelectedChatId', e => {
  215     const { lastChats } = app.state.saved
  216     e.returnValue = lastChats[dcController.credentials.addr]
  217   })
  218 
  219   ipcMain.on('selectBackgroundImage', (e, file) => {
  220     const copyAndSetBg = async (originalfile: string) => {
  221       await ensureDir(join(getConfigPath(), 'background/'))
  222       await emptyDir(join(getConfigPath(), 'background/'))
  223       const newPath = join(
  224         getConfigPath(),
  225         'background/',
  226         `background_${Date.now()}` + extname(originalfile)
  227       )
  228       copyFile(originalfile, newPath, (err: Error) => {
  229         if (err) {
  230           log.error('BG-IMG Copy Failed', err)
  231           return
  232         }
  233         updateDesktopSetting(
  234           null,
  235           'chatViewBgImg',
  236           `url("${newPath.replace(/\\/g, '/')}")`
  237         )
  238       })
  239     }
  240     if (!file) {
  241       dialog.showOpenDialog(
  242         undefined,
  243         {
  244           title: 'Select Background Image',
  245           filters: [
  246             { name: 'Images', extensions: ['jpg', 'png', 'gif', 'webp'] },
  247             { name: 'All Files', extensions: ['*'] },
  248           ],
  249           properties: ['openFile'],
  250         },
  251         (filenames: string[]) => {
  252           if (!filenames) {
  253             return
  254           }
  255           log.info('BG-IMG Selected File:', filenames[0])
  256           copyAndSetBg(filenames[0])
  257         }
  258       )
  259     } else {
  260       const filepath = join(__dirname, '../../images/backgrounds/', file)
  261       copyAndSetBg(filepath)
  262     }
  263   })
  264 
  265   ipcMain.on('updateCredentials', (e, credentials) => {
  266     if (!credentials.mail_pw) {
  267       // this means another setting value was changed
  268       credentials.mail_pw = dcController.settings.getConfig('mail_pw')
  269     }
  270     dcController.configuring = true
  271     dcController.updating = true
  272     sendStateToRenderer()
  273     dcController.loginController.configure(credentials, () => {
  274       dcController.configuring = false
  275       main.send('success', 'Configuration success!')
  276       sendStateToRenderer()
  277     })
  278   })
  279 
  280   ipcMain.on('cancelCredentialsUpdate', () => {
  281     dcController.configuring = false
  282     const deltachat = dcController.getState()
  283     sendState(deltachat)
  284   })
  285 
  286   ipcMain.on('help', async (_ev, locale) => {
  287     await openHelpWindow(locale)
  288   })
  289 
  290   function sendStateToRenderer() {
  291     log.debug('RENDER')
  292     const deltachat = dcController.getState()
  293     main.setTitle(deltachat.credentials.addr)
  294     sendState(deltachat)
  295   }
  296 
  297   function sendState(deltachat: AppState['deltachat']) {
  298     Object.assign(state, { deltachat })
  299     main.send('render', state)
  300   }
  301 
  302   // if we find saved credentials we login in with these
  303   // which will create a new Deltachat instance which
  304   // is bound to a certain account
  305   const savedCredentials = state.saved.credentials
  306   if (
  307     savedCredentials &&
  308     typeof savedCredentials === 'object' &&
  309     Object.keys(savedCredentials).length !== 0
  310   ) {
  311     const selectedAccount = state.logins.find(
  312       account => account.addr === savedCredentials.addr
  313     )
  314 
  315     if (selectedAccount) {
  316       dcController.loginController.login(
  317         selectedAccount.path,
  318         savedCredentials as credential_config,
  319         sendStateToRenderer,
  320         txCoreStrings()
  321       )
  322     } else {
  323       log.error(
  324         'Previous account not found!',
  325         state.saved.credentials,
  326         'is not in the list of found logins:',
  327         state.logins
  328       )
  329     }
  330   }
  331 }
  332 
  333 function txCoreStrings() {
  334   const tx = app.translate
  335   const strings: { [key: number]: string } = {}
  336   // TODO: Check if we need the uncommented core translations
  337   strings[C.DC_STR_NOMESSAGES] = tx('chat_no_messages')
  338   strings[C.DC_STR_SELF] = tx('self')
  339   strings[C.DC_STR_DRAFT] = tx('draft')
  340   strings[C.DC_STR_VOICEMESSAGE] = tx('voice_message')
  341   strings[C.DC_STR_DEADDROP] = tx('login_inbox')
  342   strings[C.DC_STR_IMAGE] = tx('image')
  343   strings[C.DC_STR_GIF] = tx('gif')
  344   strings[C.DC_STR_VIDEO] = tx('video')
  345   strings[C.DC_STR_AUDIO] = tx('audio')
  346   strings[C.DC_STR_FILE] = tx('file')
  347   strings[C.DC_STR_ENCRYPTEDMSG] = tx('encrypted_message')
  348   strings[C.DC_STR_STATUSLINE] = tx('pref_default_status_text')
  349   strings[C.DC_STR_NEWGROUPDRAFT] = tx('group_hello_draft')
  350   strings[C.DC_STR_MSGGRPNAME] = tx('systemmsg_group_name_changed')
  351   strings[C.DC_STR_MSGGRPIMGCHANGED] = tx('systemmsg_group_image_changed')
  352   strings[C.DC_STR_MSGADDMEMBER] = tx('systemmsg_member_added')
  353   strings[C.DC_STR_MSGDELMEMBER] = tx('systemmsg_member_removed')
  354   strings[C.DC_STR_MSGGROUPLEFT] = tx('systemmsg_group_left')
  355   // strings[C.DC_STR_E2E_AVAILABLE] = tx('DC_STR_E2E_AVAILABLE')
  356   // strings[C.DC_STR_ENCR_TRANSP] = tx('DC_STR_ENCR_TRANSP')
  357   // strings[C.DC_STR_ENCR_NONE] = tx('DC_STR_ENCR_NONE')
  358   strings[C.DC_STR_FINGERPRINTS] = tx('qrscan_fingerprint_label')
  359   strings[C.DC_STR_READRCPT] = tx('systemmsg_read_receipt_subject')
  360   strings[C.DC_STR_READRCPT_MAILBODY] = tx('systemmsg_read_receipt_body')
  361   strings[C.DC_STR_MSGGRPIMGDELETED] = tx('systemmsg_group_image_deleted')
  362   strings[C.DC_STR_E2E_PREFERRED] = tx('autocrypt_prefer_e2ee')
  363   strings[C.DC_STR_ARCHIVEDCHATS] = tx('chat_archived_chats_title')
  364   // strings[C.DC_STR_STARREDMSGS] = tx('DC_STR_STARREDMSGS')
  365   strings[C.DC_STR_AC_SETUP_MSG_SUBJECT] = tx('autocrypt_asm_subject')
  366   strings[C.DC_STR_AC_SETUP_MSG_BODY] = tx('autocrypt_asm_general_body')
  367   strings[C.DC_STR_CANTDECRYPT_MSG_BODY] = tx('systemmsg_cannot_decrypt')
  368   strings[C.DC_STR_CANNOT_LOGIN] = tx('login_error_cannot_login')
  369   strings[C.DC_STR_SERVER_RESPONSE] = tx('login_error_server_response')
  370 
  371   return strings
  372 }