From 84c71cecf4944621547c08448af3e1d0a3a30916 Mon Sep 17 00:00:00 2001 From: Pedro Aim Date: Fri, 5 Jun 2020 17:24:00 -0500 Subject: [PATCH 1/2] showing background progress of backup --- electron_app/src/BackupManager.js | 9 +- electron_app/src/database/DBEexporter.js | 163 ++++++++++----- electron_app/src/ipc/backup.js | 195 +++++++++++++----- email_mailbox/src/components/Panel.js | 10 + email_mailbox/src/components/PanelWrapper.js | 72 +++++++ email_mailbox/src/components/Snackbar.js | 78 +++++++ email_mailbox/src/components/snackbar.scss | 114 ++++++++++ email_mailbox/src/lang/de.json | 22 ++ email_mailbox/src/lang/en.json | 22 ++ email_mailbox/src/lang/es.json | 22 ++ email_mailbox/src/lang/fr.json | 22 ++ email_mailbox/src/lang/ru.json | 22 ++ .../src/utils/electronEventInterface.js | 6 + 13 files changed, 660 insertions(+), 97 deletions(-) create mode 100644 email_mailbox/src/components/Snackbar.js create mode 100644 email_mailbox/src/components/snackbar.scss diff --git a/electron_app/src/BackupManager.js b/electron_app/src/BackupManager.js index 4be58ed5e..503932124 100644 --- a/electron_app/src/BackupManager.js +++ b/electron_app/src/BackupManager.js @@ -142,12 +142,17 @@ const getFileSizeInBytes = filename => { /* Export Backup ----------------------------- */ -const exportBackupUnencrypted = async ({ backupPath, accountObj }) => { +const exportBackupUnencrypted = async ({ + backupPath, + accountObj, + progressCallback +}) => { try { try { await exportEncryptDatabaseToFile({ outputPath: ExportUnencryptedFilename, - accountObj + accountObj, + progressCallback }); } catch (dbErr) { throw new Error('Failed to export database'); diff --git a/electron_app/src/database/DBEexporter.js b/electron_app/src/database/DBEexporter.js index c15da256f..8dadd9528 100644 --- a/electron_app/src/database/DBEexporter.js +++ b/electron_app/src/database/DBEexporter.js @@ -614,38 +614,40 @@ const exportEmailTable = async accountId => { } ) .then(async rows => { - return await Promise.all( - rows.map(async row => { - let newRow = row.toJSON(); - if (!newRow.unsentDate) delete newRow.unsentDate; - if (!newRow.trashDate) delete newRow.trashDate; - if (newRow.replyTo === null) newRow = { ...newRow, replyTo: '' }; - if (!newRow.boundary) delete newRow.boundary; - - const body = - (await getEmailBody({ - username, - metadataKey: newRow.key, - password: globalManager.databaseKey.get() - })) || - newRow.content || - ''; - const headers = await getEmailHeaders({ + const emailRows = []; + + for (const emailRow of rows) { + let newRow = emailRow.toJSON(); + if (!newRow.unsentDate) delete newRow.unsentDate; + if (!newRow.trashDate) delete newRow.trashDate; + if (newRow.replyTo === null) newRow = { ...newRow, replyTo: '' }; + if (!newRow.boundary) delete newRow.boundary; + + const body = + (await getEmailBody({ username, metadataKey: newRow.key, password: globalManager.databaseKey.get() - }); - - const key = parseInt(newRow.key); - return { - ...newRow, - content: body, - key, - date: parseOutgoingDate(newRow.date), - headers: headers || undefined - }; - }) - ); + })) || + newRow.content || + ''; + const headers = await getEmailHeaders({ + username, + metadataKey: newRow.key, + password: globalManager.databaseKey.get() + }); + + const key = parseInt(newRow.key); + emailRows.push({ + ...newRow, + content: body, + key, + date: parseOutgoingDate(newRow.date), + headers: headers || undefined + }); + } + + return emailRows; }); emailRows = [...emailRows, ...result]; if (result.length < SELECT_ALL_BATCH) { @@ -820,8 +822,23 @@ const exportCustomDomainsTable = async accountId => { return formatTableRowsToString(Table.CUSTOM_DOMAIN, customDomainsRows); }; -const exportEncryptDatabaseToFile = async ({ outputPath, accountObj }) => { +const handleProgressCallback = (progress, message, email, progressCallback) => { + if (!progressCallback) return; + progressCallback({ + progress: parseInt(progress), + message, + email + }); +}; + +const exportEncryptDatabaseToFile = async ({ + outputPath, + accountObj, + progressCallback +}) => { const filepath = outputPath; + const PROGRESS_TOTAL_STEPS = 19; + let exportProgress = 0; const [recipientId, domain] = accountObj ? accountObj.recipientId.split('@') @@ -832,31 +849,81 @@ const exportEncryptDatabaseToFile = async ({ outputPath, accountObj }) => { recipientId: recipientId, domain: domain || APP_DOMAIN }); - await saveToFile({ data: fileInformation, filepath, mode: 'w' }, true); - const contacts = await exportContactTable(accountId); - await saveToFile({ data: contacts, filepath, mode: 'a' }); - - const labels = await exportLabelTable(accountId); - await saveToFile({ data: labels, filepath, mode: 'a' }); + exportProgress += 100 / PROGRESS_TOTAL_STEPS; + handleProgressCallback( + exportProgress, + 'saving_account', + `${recipientId}@${domain || APP_DOMAIN}`, + progressCallback + ); - const emails = await exportEmailTable(accountId); - await saveToFile({ data: emails, filepath, mode: 'a' }); + await saveToFile({ data: fileInformation, filepath, mode: 'w' }, true); - const emailContacts = await exportEmailContactTable(accountId); - await saveToFile({ data: emailContacts, filepath, mode: 'a' }); + const exportTables = [ + { + export: exportContactTable, + suffix: 'contacts' + }, + { + export: exportLabelTable, + suffix: 'labels' + }, + { + export: exportEmailTable, + suffix: 'emails' + }, + { + export: exportEmailContactTable, + suffix: 'email_contacts' + }, + { + export: exportEmailLabelTable, + suffix: 'email_labels' + }, + { + export: exportFileTable, + suffix: 'files' + }, + { + export: exportAliasTable, + suffix: 'aliases' + }, + { + export: exportCustomDomainsTable, + suffix: 'domains' + } + ]; + + for (const exportTable of exportTables) { + exportProgress += 100 / PROGRESS_TOTAL_STEPS; + handleProgressCallback( + exportProgress, + `exporting_${exportTable.suffix}`, + `${recipientId}@${domain || APP_DOMAIN}`, + progressCallback + ); - const emailLabels = await exportEmailLabelTable(accountId); - await saveToFile({ data: emailLabels, filepath, mode: 'a' }); + const result = await exportTable.export(accountId); - const files = await exportFileTable(accountId); - await saveToFile({ data: files, filepath, mode: 'a' }); + exportProgress += 100 / PROGRESS_TOTAL_STEPS; + handleProgressCallback( + exportProgress, + `saving_${exportTable.suffix}`, + `${recipientId}@${domain || APP_DOMAIN}`, + progressCallback + ); - const aliases = await exportAliasTable(accountId); - await saveToFile({ data: aliases, filepath, mode: 'a' }); + await saveToFile({ data: result, filepath, mode: 'a' }); + } - const customDomains = await exportCustomDomainsTable(accountId); - await saveToFile({ data: customDomains, filepath, mode: 'a' }); + exportProgress = 99; + handleProgressCallback( + exportProgress, + 'almost_done', + `${recipientId}@${domain || APP_DOMAIN}`, + progressCallback + ); }; const importDatabaseFromFile = async ({ diff --git a/electron_app/src/ipc/backup.js b/electron_app/src/ipc/backup.js index e5abdd36d..15a5d005c 100644 --- a/electron_app/src/ipc/backup.js +++ b/electron_app/src/ipc/backup.js @@ -13,6 +13,7 @@ const { const globalManager = require('./../globalManager'); const { showNotification } = require('./../notificationManager'); const { sendEventToAllWindows } = require('./../windows/windowUtils'); +const { send } = require('./../windows/mailbox'); const { defineBackupFileName, defineUnitToAppend, @@ -20,7 +21,9 @@ const { } = require('./../utils/TimeUtils'); const { updateAccount } = require('./../database'); const myAccount = require('../Account'); -let autoBackupIntervalId = {}; +let autoBackupsTime = []; +let currentAutobackup = null; +let nextBackupTimer = null; const simulatePause = ms => { return new Promise(resolve => { @@ -37,31 +40,51 @@ ipc.answerRenderer('create-default-backup-folder', () => createDefaultBackupFolder() ); +const handleProgressCallback = (progress, message, email, progressCallback) => { + if (!progressCallback) return; + progressCallback({ + progress, + message, + email + }); +}; + const doExportBackupUnencrypted = async params => { const { backupPath, notificationParams, isAutoBackup = true, - accountObj + accountObj, + progressCallback } = params; try { - globalManager.windowsEvents.disable(); + const [recipientId, domain] = accountObj + ? accountObj.recipientId.split('@') + : myAccount.recipientId.split('@'); + + handleProgressCallback( + -1, + 'starting_backup', + `${recipientId}@${domain}`, + progressCallback + ); + commitBackupStatus('local-backup-disable-events', 1); prepareBackupFiles(); - await simulatePause(2000); - globalManager.windowsEvents.enable(); commitBackupStatus('local-backup-enable-events', 2); + const backupSize = await exportBackupUnencrypted({ backupPath, - accountObj + accountObj, + progressCallback }); + commitBackupStatus('local-backup-export-finished', 3, { backupSize, isAutoBackup }); - await simulatePause(2000); + commitBackupStatus('local-backup-success', null); - await simulatePause(2000); if (notificationParams) { showNotification({ title: notificationParams.success.title, @@ -74,8 +97,10 @@ const doExportBackupUnencrypted = async params => { } return backupSize; } catch (error) { + console.error(error); globalManager.windowsEvents.enable(); commitBackupStatus('local-backup-enable-events', null, { error }); + commitBackupStatus('local-backup-failed', null, null); if (notificationParams) { showNotification({ title: notificationParams.error.title, @@ -178,15 +203,57 @@ ipc.answerRenderer('restore-backup-encrypted', async params => { }); const initAutoBackupMonitor = () => { - let account; - for (account of myAccount.loggedAccounts) { - startBackupMonitor(account); + autoBackupsTime = []; + for (const account of myAccount.loggedAccounts) { + const { autoBackupEnable, autoBackupNextDate } = account; + + if ( + !autoBackupEnable || + !autoBackupNextDate || + account.id === currentAutobackup + ) + return; + + const now = moment(); + const pendingDate = moment(autoBackupNextDate); + const timeDiff = pendingDate.diff(now); + autoBackupsTime.push({ + username: account.recipientId, + accountId: account.id, + triggerTimer: timeDiff <= 0 ? 1 : timeDiff + }); } + + if (!currentAutobackup) checkNextBackup(); +}; + +const checkNextBackup = () => { + if (currentAutobackup || autoBackupsTime.length === 0) return; + + autoBackupsTime.sort((acc1, acc2) => { + if (acc1.triggerTimer < acc2.triggerTimer) return -1; + if (acc1.triggerTimer > acc2.triggerTimer) return 1; + return 0; + }); + + if (nextBackupTimer) clearTimeout(nextBackupTimer); + nextBackupTimer = setTimeout(() => { + initAutoBackup(autoBackupsTime[0].accountId); + }, autoBackupsTime[0].triggerTimer); }; -const startBackupMonitor = account => { - const accountId = account.id; - clearTimeout(autoBackupIntervalId[accountId]); +const initAutoBackup = async accountId => { + autoBackupsTime = autoBackupsTime.filter(timer => { + return timer.accountId !== accountId; + }); + currentAutobackup = accountId; + + const account = myAccount.loggedAccounts.find(acc => acc.id === accountId); + if (!account) { + backupDone(); + return; + } + const { autoBackupEnable, autoBackupPath, @@ -194,44 +261,76 @@ const startBackupMonitor = account => { autoBackupNextDate } = account; if (!autoBackupEnable || !autoBackupNextDate) { + backupDone(); return; } - const now = moment(); - const pendingDate = moment(autoBackupNextDate); - const timeDiff = pendingDate.diff(now); - autoBackupIntervalId[accountId] = setTimeout(async () => { - try { - const backupFileName = defineBackupFileName('db'); - const backupSize = await doExportBackupUnencrypted({ - backupPath: `${autoBackupPath}/${backupFileName}` - }); - const timeUnit = defineUnitToAppend(autoBackupFrequency); - const today = moment(Date.now()); - const nextDate = moment(autoBackupNextDate); - do { - nextDate.add(1, timeUnit); - } while (nextDate.isBefore(today)); - await updateAccount({ - id: accountId, - autoBackupLastDate: pendingDate.format(backupDateFormat), - autoBackupLastSize: backupSize, - autoBackupNextDate: nextDate.format(backupDateFormat) - }); - startBackupMonitor(account); - } catch (backupErr) { - log( - `Failed to do scheduled backup at ${pendingDate.format( - backupDateFormat - )}` - ); - } - }, timeDiff); + + try { + const backupFileName = defineBackupFileName('db'); + const backupSize = await doExportBackupUnencrypted({ + backupPath: `${autoBackupPath}/${backupFileName}`, + progressCallback: data => { + send('backup-progress', data); + } + }); + const timeUnit = defineUnitToAppend(autoBackupFrequency); + const today = moment(Date.now()); + const nextDate = moment(autoBackupNextDate); + do { + nextDate.add(1, timeUnit); + } while (nextDate.isBefore(today)); + await updateAccount({ + id: accountId, + autoBackupLastDate: today.format(backupDateFormat), + autoBackupLastSize: backupSize, + autoBackupNextDate: nextDate.format(backupDateFormat) + }); + const timeDiff = nextDate.diff(today); + autoBackupsTime.push({ + username: account.recipientId, + accountId, + triggerTimer: timeDiff <= 0 ? 1 : timeDiff + }); + + backupDone(); + } catch (backupErr) { + log( + `Failed to do scheduled backup for account ${account.recipientId} : ${ + account.name + }` + ); + backupFail(); + } +}; + +const backupDone = () => { + currentAutobackup = null; + nextBackupTimer = null; + checkNextBackup(); }; -ipc.answerRenderer('init-autobackup-monitor', initAutoBackupMonitor); +const backupFail = () => { + currentAutobackup = null; + nextBackupTimer = null; + initAutoBackupMonitor(); +}; + +ipc.answerRenderer('init-autobackup-monitor', () => { + if (!currentAutobackup && nextBackupTimer) { + clearTimeout(nextBackupTimer); + } + initAutoBackupMonitor(); +}); ipc.answerRenderer('disable-auto-backup', accountId => { - clearTimeout(autoBackupIntervalId[accountId]); + if (!currentAutobackup && nextBackupTimer) { + clearTimeout(nextBackupTimer); + } + autoBackupsTime = autoBackupsTime.filter(timer => { + return timer.accountId !== accountId; + }); + + if (!currentAutobackup) checkNextBackup(); }); const log = message => { @@ -241,7 +340,9 @@ const log = message => { }; process.on('exit', () => { - autoBackupIntervalId = {}; + clearTimeout(nextBackupTimer); + currentAutobackup = null; + autoBackupsTime = []; }); module.exports = { diff --git a/email_mailbox/src/components/Panel.js b/email_mailbox/src/components/Panel.js index 66920de5d..56b7481ac 100644 --- a/email_mailbox/src/components/Panel.js +++ b/email_mailbox/src/components/Panel.js @@ -16,6 +16,7 @@ import UpdatePopup from './UpdatePopup'; import { MAILBOX_POPUP_TYPES } from './PanelWrapper'; import { mySettings } from '../utils/electronInterface'; import UserGuide from './UserGuide'; +import Snackbar from './Snackbar'; import './panel.scss'; const Panel = props => ( @@ -56,6 +57,13 @@ const Panel = props => ( ...props })} + {props.backupSnackbar && + !props.backupSnackbar.hide && ( + + )} ); @@ -178,6 +186,7 @@ renderMailboxPopup.propTypes = { }; Panel.propTypes = { + backupSnackbar: PropTypes.object, isHiddenMailboxPopup: PropTypes.bool, isOpenActivityPanel: PropTypes.bool, isOpenSideBar: PropTypes.bool, @@ -187,6 +196,7 @@ Panel.propTypes = { onClickCloseWelcome: PropTypes.func, onClickThreadBack: PropTypes.func, onClickSection: PropTypes.func, + onDismissSnackbar: PropTypes.func, onToggleActivityPanel: PropTypes.func, onToggleSideBar: PropTypes.func, onUpdateApp: PropTypes.func, diff --git a/email_mailbox/src/components/PanelWrapper.js b/email_mailbox/src/components/PanelWrapper.js index 46a020eb3..f8533d72b 100644 --- a/email_mailbox/src/components/PanelWrapper.js +++ b/email_mailbox/src/components/PanelWrapper.js @@ -20,6 +20,9 @@ import { } from '../actions'; import { USER_GUIDE_STEPS } from './UserGuide'; import { TAB } from './Settings'; +import string from '../lang'; + +const backupString = string.backup; const MAILBOX_POPUP_TYPES = { ACCOUNT_DELETED: 'account-deleted', @@ -46,6 +49,7 @@ class PanelWrapper extends Component { isOpenWelcome: true, mailboxPopupType: undefined, mailboxPopupData: undefined, + backupSnackbar: undefined, sectionSelected: { type: SectionType.MAILBOX, params: { @@ -86,6 +90,8 @@ class PanelWrapper extends Component { onUpdateApp={this.handleUpdateApp} sectionSelected={this.state.sectionSelected} onUpdateNow={this.handleUpdateNow} + backupSnackbar={this.state.backupSnackbar} + onDismissSnackbar={this.handleSnackbarDismiss} {...this.props} /> ); @@ -280,6 +286,7 @@ class PanelWrapper extends Component { addEvent(Event.SET_SECTION_TYPE, this.setSectionTypeListenerCallback); addEvent(Event.SUSPENDED_ACCOUNT, this.suspendedAccountListenerCallback); addEvent(Event.BIG_UPDATE_AVAILABLE, this.handleBigUpdateListenerCallback); + addEvent(Event.BACKUP_PROGRESS, this.handleBackupProgress); addEvent( Event.REACTIVATED_ACCOUNT, this.reactivatedAccountListenerCallback @@ -295,6 +302,8 @@ class PanelWrapper extends Component { addEvent(Event.OPEN_PLUS, this.handleOpenPlus); addEvent(Event.RESTORE_BACKUP_INIT, this.restoreBackupInitListenerCallback); addEvent(Event.REFRESH_MAILBOX_SYNC, this.refreshMailboxSync); + addEvent(Event.LOCAL_BACKUP_SUCCESS, this.handleBackupFinish); + addEvent(Event.LOCAL_BACKUP_FAILED, this.handleBackupFailed); }; removeEventHandlers = () => { @@ -319,6 +328,7 @@ class PanelWrapper extends Component { removeEvent(Event.ACCOUNT_DELETED, this.accountDeletedListenerCallback); removeEvent(Event.SET_SECTION_TYPE, this.setSectionTypeListenerCallback); removeEvent(Event.SUSPENDED_ACCOUNT, this.suspendedAccountListenerCallback); + removeEvent(Event.BACKUP_PROGRESS, this.handleBackupProgress); removeEvent( Event.REACTIVATED_ACCOUNT, this.reactivatedAccountListenerCallback @@ -337,6 +347,8 @@ class PanelWrapper extends Component { ); removeEvent(Event.REFRESH_MAILBOX_SYNC, this.refreshMailboxSync); removeEvent(Event.OPEN_PLUS, this.handleOpenPlus); + removeEvent(Event.LOCAL_BACKUP_SUCCESS, this.handleBackupFinish); + removeEvent(Event.LOCAL_BACKUP_FAILED, this.handleBackupFailed); }; enableWindowListenerCallback = () => { @@ -521,6 +533,66 @@ class PanelWrapper extends Component { this.props.onChangingTrustedContact(eventParams); }; + handleSnackbarDismiss = () => { + const currentSnackbar = this.state.backupSnackbar || {}; + this.setState({ + backupSnackbar: { + ...currentSnackbar, + hide: true + } + }); + }; + + handleBackupProgress = data => { + const currentSnackbar = this.state.backupSnackbar || {}; + const newMessage = backupString[data.message] || currentSnackbar.message; + this.setState({ + backupSnackbar: { + ...currentSnackbar, + ...data, + message: newMessage + } + }); + }; + + handleBackupFinish = () => { + const currentSnackbar = this.state.backupSnackbar || {}; + this.setState( + { + backupSnackbar: { + ...currentSnackbar, + progress: 100, + message: backupString.success_backup + } + }, + () => { + setTimeout(this.handleBackupCleanUp, 2000); + } + ); + }; + + handleBackupFailed = () => { + const currentSnackbar = this.state.backupSnackbar || {}; + this.setState( + { + backupSnackbar: { + ...currentSnackbar, + progress: -2, + message: backupString.failure_backup + } + }, + () => { + setTimeout(this.handleBackupCleanUp, 2000); + } + ); + }; + + handleBackupCleanUp = () => { + this.setState({ + backupSnackbar: undefined + }); + }; + updateLoadingSync = eventParams => { const { totalTask, completedTask } = eventParams; this.props.onUpdateLoadingSync({ totalTask, completedTask }); diff --git a/email_mailbox/src/components/Snackbar.js b/email_mailbox/src/components/Snackbar.js new file mode 100644 index 000000000..e3cb5dcf7 --- /dev/null +++ b/email_mailbox/src/components/Snackbar.js @@ -0,0 +1,78 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import './snackbar.scss'; + +const Loading = () => ( +
+
+
+
+
+
+); + +const Snackbar = props => ( +
+ +
+
+ {props.message} +
+
+ {props.email} +
+
+ {props.progress < 100 && ( +
+ +
+ )} +
+); + +const ProgressIndicator = props => { + switch (props.progress) { + case -2: + return ( +
+
+ +
+
+ ); + case -1: + return ( +
+ +
+ ); + case 100: + return ( +
+
+ +
+
+ ); + default: + return ( +
+ + {props.progress}% +
+ ); + } +}; + +Snackbar.propTypes = { + email: PropTypes.string, + message: PropTypes.string, + progress: PropTypes.number, + onDismissSnackbar: PropTypes.func +}; + +ProgressIndicator.propTypes = { + progress: PropTypes.number +}; + +export default Snackbar; diff --git a/email_mailbox/src/components/snackbar.scss b/email_mailbox/src/components/snackbar.scss new file mode 100644 index 000000000..7480b2b55 --- /dev/null +++ b/email_mailbox/src/components/snackbar.scss @@ -0,0 +1,114 @@ +@import "./../styles/index.scss"; + +.snackbar-wrapper { + position: absolute; + right: 30px; + bottom: 10px; + border-radius: 5px; + padding: 12px; + width: 240px; + height: 30px; + display: flex; + z-index: 1000; +} + +.snackbar-loader-container { + position: relative; + width: 42px; + height: 100%; + margin-left: 8px; + + .loading-ring { + position: absolute; + left: -10px; + top: -5px; + + > div { + width: 35px; + height: 35px; + } + } + + span { + top: 8px; + left: -1px; + font-size: 11px; + position: absolute; + } +} + +.snackbar-message-contianer { + display: flex; + flex-direction: column; + justify-content: center; + + .snackbar-message { + font-size: 13px; + } + + .snackbar-account { + font-size: 12px; + } +} + +.snackbar-success-progress { + position: absolute; + width: 30px; + height: 100%; + background: #58a40b; + border-radius: 50%; + top: -1px; + left: -7px; + display: flex; + justify-content: center; + align-items: center; + font-size: 25px; + color: white; +} + +.snackbar-failure-progress { + position: absolute; + width: 30px; + height: 100%; + background: #ff3366; + border-radius: 50%; + top: -1px; + left: -7px; + display: flex; + justify-content: center; + align-items: center; + font-size: 25px; + color: white; +} + +.snackbar-close{ + position: absolute; + width: 40px; + height: 30px; + right: 0px; + display: flex; + justify-content: center; + align-items: center; + font-size: 25px; + color: #ff3366; + + &:hover { + cursor: pointer; + } +} + + +/* THEME + ----------------------------- */ +@mixin themable($_THEME, $_BACKGROUND_COLOR_SIDEBAR, $_COLOR_ICON_NAVITEM_SELECTED){ + [data-theme^=#{$_THEME}], + [data-theme] [data-theme^=#{$_THEME}] { + .snackbar-wrapper{ + background: $_BACKGROUND_COLOR_SIDEBAR; + color: $_COLOR_ICON_NAVITEM_SELECTED; + } + } +} + +@include themable($_THEME_LIGHT, $_BACKGROUND_COLOR_SIDEBAR_LIGHT, $_COLOR_ICON_NAVITEM_SELECTED_LIGHT); +@include themable($_THEME_DARK, $_BACKGROUND_COLOR_SIDEBAR_DARK, $_COLOR_ICON_NAVITEM_SELECTED_DARK); \ No newline at end of file diff --git a/email_mailbox/src/lang/de.json b/email_mailbox/src/lang/de.json index 77204c07b..4f7d5a3de 100644 --- a/email_mailbox/src/lang/de.json +++ b/email_mailbox/src/lang/de.json @@ -109,6 +109,28 @@ } } }, + "backup": { + "starting_backup": "Starting Backup...", + "saving_account": "Saving Account...", + "exporting_contacts": "Exporting Contacts...", + "saving_contacts": "Saving Contacts...", + "exporting_labels": "Exporting Labels...", + "saving_labels": "Saving Labels...", + "exporting_emails": "Exporting Emails...", + "saving_emails": "Saving Emails...", + "exporting_email_contacts": "Exporting Email Contacts...", + "saving_email_contacts": "Saving Email Contacts...", + "exporting_email_labels": "Exporting Email Labels...", + "saving_email_labels": "Saving Email Labels...", + "exporting_files": "Exporting Files...", + "saving_files": "Saving Files...", + "exporting_aliases": "Exporting Aliases...", + "saving_aliases": "Saving Aliases...", + "exporting_domains": "Exporting Custom Domains...", + "saving_domains": "Saving Custom Domains", + "success_backup": "Backup Success!!", + "failure_backup": "Backup Failed!" + }, "crash": { "title": "Hoppla! Es sieht so aus, als wäre etwas schiefgelaufen.", "counter": { diff --git a/email_mailbox/src/lang/en.json b/email_mailbox/src/lang/en.json index 0368e3326..0fb4e3275 100644 --- a/email_mailbox/src/lang/en.json +++ b/email_mailbox/src/lang/en.json @@ -109,6 +109,28 @@ } } }, + "backup": { + "starting_backup": "Starting Backup...", + "saving_account": "Saving Account...", + "exporting_contacts": "Exporting Contacts...", + "saving_contacts": "Saving Contacts...", + "exporting_labels": "Exporting Labels...", + "saving_labels": "Saving Labels...", + "exporting_emails": "Exporting Emails...", + "saving_emails": "Saving Emails...", + "exporting_email_contacts": "Exporting Email Contacts...", + "saving_email_contacts": "Saving Email Contacts...", + "exporting_email_labels": "Exporting Email Labels...", + "saving_email_labels": "Saving Email Labels...", + "exporting_files": "Exporting Files...", + "saving_files": "Saving Files...", + "exporting_aliases": "Exporting Aliases...", + "saving_aliases": "Saving Aliases...", + "exporting_domains": "Exporting Custom Domains...", + "saving_domains": "Saving Custom Domains", + "success_backup": "Backup Success!!", + "failure_backup": "Backup Failed!" + }, "crash": { "title": "Oops! It looks like something went wrong", "counter": { diff --git a/email_mailbox/src/lang/es.json b/email_mailbox/src/lang/es.json index 1d83bed2e..bfea74eae 100644 --- a/email_mailbox/src/lang/es.json +++ b/email_mailbox/src/lang/es.json @@ -109,6 +109,28 @@ } } }, + "backup": { + "starting_backup": "Starting Backup...", + "saving_account": "Saving Account...", + "exporting_contacts": "Exporting Contacts...", + "saving_contacts": "Saving Contacts...", + "exporting_labels": "Exporting Labels...", + "saving_labels": "Saving Labels...", + "exporting_emails": "Exporting Emails...", + "saving_emails": "Saving Emails...", + "exporting_email_contacts": "Exporting Email Contacts...", + "saving_email_contacts": "Saving Email Contacts...", + "exporting_email_labels": "Exporting Email Labels...", + "saving_email_labels": "Saving Email Labels...", + "exporting_files": "Exporting Files...", + "saving_files": "Saving Files...", + "exporting_aliases": "Exporting Aliases...", + "saving_aliases": "Saving Aliases...", + "exporting_domains": "Exporting Custom Domains...", + "saving_domains": "Saving Custom Domains", + "success_backup": "Backup Success!!", + "failure_backup": "Backup Failed!" + }, "crash": { "title": "¡Ups! Parece que algo falló", "counter": { diff --git a/email_mailbox/src/lang/fr.json b/email_mailbox/src/lang/fr.json index f87dfe6e1..4bc110171 100644 --- a/email_mailbox/src/lang/fr.json +++ b/email_mailbox/src/lang/fr.json @@ -109,6 +109,28 @@ } } }, + "backup": { + "starting_backup": "Starting Backup...", + "saving_account": "Saving Account...", + "exporting_contacts": "Exporting Contacts...", + "saving_contacts": "Saving Contacts...", + "exporting_labels": "Exporting Labels...", + "saving_labels": "Saving Labels...", + "exporting_emails": "Exporting Emails...", + "saving_emails": "Saving Emails...", + "exporting_email_contacts": "Exporting Email Contacts...", + "saving_email_contacts": "Saving Email Contacts...", + "exporting_email_labels": "Exporting Email Labels...", + "saving_email_labels": "Saving Email Labels...", + "exporting_files": "Exporting Files...", + "saving_files": "Saving Files...", + "exporting_aliases": "Exporting Aliases...", + "saving_aliases": "Saving Aliases...", + "exporting_domains": "Exporting Custom Domains...", + "saving_domains": "Saving Custom Domains", + "success_backup": "Backup Success!!", + "failure_backup": "Backup Failed!" + }, "crash": { "title": "Oops! On dirait que quelque chose s'est mal passé", "counter": { diff --git a/email_mailbox/src/lang/ru.json b/email_mailbox/src/lang/ru.json index 34306502b..7400b0318 100644 --- a/email_mailbox/src/lang/ru.json +++ b/email_mailbox/src/lang/ru.json @@ -109,6 +109,28 @@ } } }, + "backup": { + "starting_backup": "Starting Backup...", + "saving_account": "Saving Account...", + "exporting_contacts": "Exporting Contacts...", + "saving_contacts": "Saving Contacts...", + "exporting_labels": "Exporting Labels...", + "saving_labels": "Saving Labels...", + "exporting_emails": "Exporting Emails...", + "saving_emails": "Saving Emails...", + "exporting_email_contacts": "Exporting Email Contacts...", + "saving_email_contacts": "Saving Email Contacts...", + "exporting_email_labels": "Exporting Email Labels...", + "saving_email_labels": "Saving Email Labels...", + "exporting_files": "Exporting Files...", + "saving_files": "Saving Files...", + "exporting_aliases": "Exporting Aliases...", + "saving_aliases": "Saving Aliases...", + "exporting_domains": "Exporting Custom Domains...", + "saving_domains": "Saving Custom Domains", + "success_backup": "Backup Success!!", + "failure_backup": "Backup Failed!" + }, "crash": { "title": "К сожалению! Похоже, что-то пошло не так", "counter": { diff --git a/email_mailbox/src/utils/electronEventInterface.js b/email_mailbox/src/utils/electronEventInterface.js index 787a116c2..7faffe972 100644 --- a/email_mailbox/src/utils/electronEventInterface.js +++ b/email_mailbox/src/utils/electronEventInterface.js @@ -1508,6 +1508,10 @@ export const sendLoadEventsEvent = params => { emitter.emit(Event.LOAD_EVENTS, params); }; +ipcRenderer.on('backup-progress', (ev, data) => { + emitter.emit(Event.BACKUP_PROGRESS, data); +}); + ipcRenderer.on('socket-message', async (ev, message) => { const { cmd, recipientId, domain } = message; if (cmd === 400) { @@ -2137,6 +2141,7 @@ export const sendMailboxEvent = (eventName, eventData) => { export const Event = { ACCOUNT_DELETED: 'account-deleted', + BACKUP_PROGRESS: 'backup-progress', BIG_UPDATE_AVAILABLE: 'big-update-available', CHANGE_SET_TRUSTED_ACCOUNT: 'change-set-trusted-account', DEVICE_REMOVED: 'device-removed', @@ -2155,6 +2160,7 @@ export const Event = { LOCAL_BACKUP_EXPORT_FINISHED: 'local-backup-export-finished', LOCAL_BACKUP_ENCRYPT_FINISHED: 'local-backup-encrypt-finished', LOCAL_BACKUP_SUCCESS: 'local-backup-success', + LOCAL_BACKUP_FAILED: 'local-backup-failed', OPEN_PLUS: 'open-plus', OPEN_THREAD: 'open-thread', PASSWORD_CHANGED: 'password-changed', From 49114ccf5c4942378a81bad7905e04f913d78608 Mon Sep 17 00:00:00 2001 From: Pedro Aim Date: Wed, 10 Jun 2020 17:34:12 -0500 Subject: [PATCH 2/2] changing backing up ui --- electron_app/src/ipc/backup.js | 18 +++- email_mailbox/src/components/Loading.js | 25 ++++- email_mailbox/src/components/PanelWrapper.js | 37 ++++--- email_mailbox/src/components/Snackbar.js | 94 +++++++++-------- email_mailbox/src/components/loading.scss | 6 ++ email_mailbox/src/components/snackbar.scss | 105 +++++++------------ email_mailbox/src/lang/de.json | 22 +--- email_mailbox/src/lang/en.json | 22 +--- email_mailbox/src/lang/es.json | 22 +--- email_mailbox/src/lang/fr.json | 22 +--- email_mailbox/src/lang/ru.json | 22 +--- 11 files changed, 167 insertions(+), 228 deletions(-) diff --git a/electron_app/src/ipc/backup.js b/electron_app/src/ipc/backup.js index 15a5d005c..348093bf6 100644 --- a/electron_app/src/ipc/backup.js +++ b/electron_app/src/ipc/backup.js @@ -19,6 +19,7 @@ const { defineUnitToAppend, backupDateFormat } = require('./../utils/TimeUtils'); +const { APP_DOMAIN } = require('../utils/const'); const { updateAccount } = require('./../database'); const myAccount = require('../Account'); let autoBackupsTime = []; @@ -40,12 +41,17 @@ ipc.answerRenderer('create-default-backup-folder', () => createDefaultBackupFolder() ); -const handleProgressCallback = (progress, message, email, progressCallback) => { +const handleProgressCallback = ( + progress, + message, + userData, + progressCallback +) => { if (!progressCallback) return; progressCallback({ progress, message, - email + ...userData }); }; @@ -65,7 +71,12 @@ const doExportBackupUnencrypted = async params => { handleProgressCallback( -1, 'starting_backup', - `${recipientId}@${domain}`, + { + email: `${recipientId}@${domain || APP_DOMAIN}`, + username: recipientId, + domain: domain || APP_DOMAIN, + name: accountObj ? accountObj.name : myAccount.name + }, progressCallback ); @@ -97,7 +108,6 @@ const doExportBackupUnencrypted = async params => { } return backupSize; } catch (error) { - console.error(error); globalManager.windowsEvents.enable(); commitBackupStatus('local-backup-enable-events', null, { error }); commitBackupStatus('local-backup-failed', null, null); diff --git a/email_mailbox/src/components/Loading.js b/email_mailbox/src/components/Loading.js index f06ef946d..34fbf7837 100644 --- a/email_mailbox/src/components/Loading.js +++ b/email_mailbox/src/components/Loading.js @@ -4,10 +4,11 @@ import string from './../lang'; import './loading.scss'; // const messages = string.loading.messages; -const statusType = { +export const statusType = { RUNNING: 'running-animation', STOP: 'stop-animation', - COMPLETE: 'complete-animation' + COMPLETE: 'complete-animation', + ACTIVE: 'active-animation' }; const errorType = { @@ -34,6 +35,21 @@ const Loading = props => (
); +export const SingleLoading = props => ( +
+
+
+
+
+
+
+
+
+); + const dialogTitle = props => { if (props.animationClass === statusType.RUNNING) { return

{string.address.add.step3.running.title}

; @@ -143,4 +159,9 @@ Loading.propTypes = { decreaseStep: PropTypes.func }; +SingleLoading.propTypes = { + animationClass: PropTypes.string, + percent: PropTypes.number +}; + export default Loading; diff --git a/email_mailbox/src/components/PanelWrapper.js b/email_mailbox/src/components/PanelWrapper.js index f8533d72b..6c0c1228c 100644 --- a/email_mailbox/src/components/PanelWrapper.js +++ b/email_mailbox/src/components/PanelWrapper.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import Panel from './Panel'; import PropTypes from 'prop-types'; +import randomcolor from 'randomcolor'; import { addEvent, removeEvent, @@ -9,8 +10,12 @@ import { sendMailboxEvent } from '../utils/electronEventInterface'; import { checkForUpdates, processPendingEvents } from '../utils/ipc'; -import { LabelType, getPendingRestoreStatus } from '../utils/electronInterface'; -import { SectionType } from '../utils/const'; +import { + LabelType, + getPendingRestoreStatus, + mySettings +} from '../utils/electronInterface'; +import { SectionType, avatarBaseUrl } from '../utils/const'; import { addLabels, setAvatarUpdatedTimestamp, @@ -20,9 +25,6 @@ import { } from '../actions'; import { USER_GUIDE_STEPS } from './UserGuide'; import { TAB } from './Settings'; -import string from '../lang'; - -const backupString = string.backup; const MAILBOX_POPUP_TYPES = { ACCOUNT_DELETED: 'account-deleted', @@ -545,24 +547,33 @@ class PanelWrapper extends Component { handleBackupProgress = data => { const currentSnackbar = this.state.backupSnackbar || {}; - const newMessage = backupString[data.message] || currentSnackbar.message; + if (!currentSnackbar.color) { + currentSnackbar.color = randomcolor({ + seed: data.name || data.email, + luminosity: mySettings.theme === 'dark' ? 'dark' : 'bright' + }); + } + if (data.username && data.domain) { + currentSnackbar.avatarUrl = `${avatarBaseUrl}${data.domain}/${ + data.username + }`; + } this.setState({ backupSnackbar: { ...currentSnackbar, - ...data, - message: newMessage + ...data } }); }; handleBackupFinish = () => { - const currentSnackbar = this.state.backupSnackbar || {}; + if (!this.state.backupSnackbar) return; + const currentSnackbar = this.state.backupSnackbar; this.setState( { backupSnackbar: { ...currentSnackbar, - progress: 100, - message: backupString.success_backup + progress: 100 } }, () => { @@ -572,13 +583,13 @@ class PanelWrapper extends Component { }; handleBackupFailed = () => { + if (!this.state.backupSnackbar) return; const currentSnackbar = this.state.backupSnackbar || {}; this.setState( { backupSnackbar: { ...currentSnackbar, - progress: -2, - message: backupString.failure_backup + progress: -2 } }, () => { diff --git a/email_mailbox/src/components/Snackbar.js b/email_mailbox/src/components/Snackbar.js index e3cb5dcf7..e23a3dd2b 100644 --- a/email_mailbox/src/components/Snackbar.js +++ b/email_mailbox/src/components/Snackbar.js @@ -1,77 +1,83 @@ import React from 'react'; import PropTypes from 'prop-types'; import './snackbar.scss'; +import { SingleLoading, statusType } from './Loading'; +import AvatarImage from './AvatarImage'; +import string from '../lang'; -const Loading = () => ( -
-
-
-
-
-
-); +const backupString = string.backup; const Snackbar = props => (
- -
-
- {props.message} -
-
- {props.email} +
+

{backupString.title}

+
+ {backupString.hide}
- {props.progress < 100 && ( -
- +
+ +
+
+ +
+
+ {props.email} +
- )} +
); -const ProgressIndicator = props => { +const Loader = props => { switch (props.progress) { case -2: - return ( -
-
- -
-
- ); + return ; case -1: - return ( -
- -
- ); + return ; case 100: return ( -
-
- -
-
+ ); default: return ( -
- - {props.progress}% -
+ ); } }; +const AvatarIndicator = props => { + return ( +
+ +
+ ); +}; + Snackbar.propTypes = { email: PropTypes.string, - message: PropTypes.string, - progress: PropTypes.number, onDismissSnackbar: PropTypes.func }; -ProgressIndicator.propTypes = { +AvatarIndicator.propTypes = { + progress: PropTypes.number, + name: PropTypes.string, + color: PropTypes.string, + avatarUrl: PropTypes.string +}; + +Loader.propTypes = { progress: PropTypes.number }; diff --git a/email_mailbox/src/components/loading.scss b/email_mailbox/src/components/loading.scss index ef17d9fc0..885c784c8 100644 --- a/email_mailbox/src/components/loading.scss +++ b/email_mailbox/src/components/loading.scss @@ -78,6 +78,12 @@ animation: move 1s linear infinite; } + .active-animation { + width: 0%; + background-color: #0091ff; + animation: fadeDown 1s linear; + } + .stop-animation { width: 0%; background-color: red; diff --git a/email_mailbox/src/components/snackbar.scss b/email_mailbox/src/components/snackbar.scss index 7480b2b55..ea3cbbd68 100644 --- a/email_mailbox/src/components/snackbar.scss +++ b/email_mailbox/src/components/snackbar.scss @@ -7,40 +7,50 @@ border-radius: 5px; padding: 12px; width: 240px; - height: 30px; + height: 70px; display: flex; + flex-direction: column; z-index: 1000; } -.snackbar-loader-container { - position: relative; - width: 42px; - height: 100%; - margin-left: 8px; - - .loading-ring { - position: absolute; - left: -10px; - top: -5px; +.snackbar-title-container { + width: 100%; + height: 30px; + display: flex; + justify-content: space-between; + align-items: start; + font-size: 14px; - > div { - width: 35px; - height: 35px; - } + h4 { + margin: 0; } - span { - top: 8px; - left: -1px; - font-size: 11px; - position: absolute; + .snackbar-title-hide { + margin: 0; + margin-right: 8px; + color: #65bdff; + cursor: pointer; } } +.snackbar-info-container { + width: 100%; + height: 40px; + display: flex; +} + +.snackbar-loader-container { + position: relative; + width: 40px; + height: 40px; + margin-right: 12px; + flex-shrink: 0; +} + .snackbar-message-contianer { display: flex; flex-direction: column; - justify-content: center; + justify-content: space-evenly; .snackbar-message { font-size: 13px; @@ -48,52 +58,17 @@ .snackbar-account { font-size: 12px; + margin-top: 3px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 180px; } -} - -.snackbar-success-progress { - position: absolute; - width: 30px; - height: 100%; - background: #58a40b; - border-radius: 50%; - top: -1px; - left: -7px; - display: flex; - justify-content: center; - align-items: center; - font-size: 25px; - color: white; -} - -.snackbar-failure-progress { - position: absolute; - width: 30px; - height: 100%; - background: #ff3366; - border-radius: 50%; - top: -1px; - left: -7px; - display: flex; - justify-content: center; - align-items: center; - font-size: 25px; - color: white; -} - -.snackbar-close{ - position: absolute; - width: 40px; - height: 30px; - right: 0px; - display: flex; - justify-content: center; - align-items: center; - font-size: 25px; - color: #ff3366; - &:hover { - cursor: pointer; + #loading-container { + .dialog-content { + width: 180px; + } } } diff --git a/email_mailbox/src/lang/de.json b/email_mailbox/src/lang/de.json index 4f7d5a3de..07775a16d 100644 --- a/email_mailbox/src/lang/de.json +++ b/email_mailbox/src/lang/de.json @@ -110,26 +110,8 @@ } }, "backup": { - "starting_backup": "Starting Backup...", - "saving_account": "Saving Account...", - "exporting_contacts": "Exporting Contacts...", - "saving_contacts": "Saving Contacts...", - "exporting_labels": "Exporting Labels...", - "saving_labels": "Saving Labels...", - "exporting_emails": "Exporting Emails...", - "saving_emails": "Saving Emails...", - "exporting_email_contacts": "Exporting Email Contacts...", - "saving_email_contacts": "Saving Email Contacts...", - "exporting_email_labels": "Exporting Email Labels...", - "saving_email_labels": "Saving Email Labels...", - "exporting_files": "Exporting Files...", - "saving_files": "Saving Files...", - "exporting_aliases": "Exporting Aliases...", - "saving_aliases": "Saving Aliases...", - "exporting_domains": "Exporting Custom Domains...", - "saving_domains": "Saving Custom Domains", - "success_backup": "Backup Success!!", - "failure_backup": "Backup Failed!" + "title": "Backing Up Account", + "hide": "Hide" }, "crash": { "title": "Hoppla! Es sieht so aus, als wäre etwas schiefgelaufen.", diff --git a/email_mailbox/src/lang/en.json b/email_mailbox/src/lang/en.json index 0fb4e3275..d2b461a07 100644 --- a/email_mailbox/src/lang/en.json +++ b/email_mailbox/src/lang/en.json @@ -110,26 +110,8 @@ } }, "backup": { - "starting_backup": "Starting Backup...", - "saving_account": "Saving Account...", - "exporting_contacts": "Exporting Contacts...", - "saving_contacts": "Saving Contacts...", - "exporting_labels": "Exporting Labels...", - "saving_labels": "Saving Labels...", - "exporting_emails": "Exporting Emails...", - "saving_emails": "Saving Emails...", - "exporting_email_contacts": "Exporting Email Contacts...", - "saving_email_contacts": "Saving Email Contacts...", - "exporting_email_labels": "Exporting Email Labels...", - "saving_email_labels": "Saving Email Labels...", - "exporting_files": "Exporting Files...", - "saving_files": "Saving Files...", - "exporting_aliases": "Exporting Aliases...", - "saving_aliases": "Saving Aliases...", - "exporting_domains": "Exporting Custom Domains...", - "saving_domains": "Saving Custom Domains", - "success_backup": "Backup Success!!", - "failure_backup": "Backup Failed!" + "title": "Backing Up Account", + "hide": "Hide" }, "crash": { "title": "Oops! It looks like something went wrong", diff --git a/email_mailbox/src/lang/es.json b/email_mailbox/src/lang/es.json index bfea74eae..ffa7f5990 100644 --- a/email_mailbox/src/lang/es.json +++ b/email_mailbox/src/lang/es.json @@ -110,26 +110,8 @@ } }, "backup": { - "starting_backup": "Starting Backup...", - "saving_account": "Saving Account...", - "exporting_contacts": "Exporting Contacts...", - "saving_contacts": "Saving Contacts...", - "exporting_labels": "Exporting Labels...", - "saving_labels": "Saving Labels...", - "exporting_emails": "Exporting Emails...", - "saving_emails": "Saving Emails...", - "exporting_email_contacts": "Exporting Email Contacts...", - "saving_email_contacts": "Saving Email Contacts...", - "exporting_email_labels": "Exporting Email Labels...", - "saving_email_labels": "Saving Email Labels...", - "exporting_files": "Exporting Files...", - "saving_files": "Saving Files...", - "exporting_aliases": "Exporting Aliases...", - "saving_aliases": "Saving Aliases...", - "exporting_domains": "Exporting Custom Domains...", - "saving_domains": "Saving Custom Domains", - "success_backup": "Backup Success!!", - "failure_backup": "Backup Failed!" + "title": "Respaldando Cuenta", + "hide": "Ocultar" }, "crash": { "title": "¡Ups! Parece que algo falló", diff --git a/email_mailbox/src/lang/fr.json b/email_mailbox/src/lang/fr.json index 4bc110171..3a653d954 100644 --- a/email_mailbox/src/lang/fr.json +++ b/email_mailbox/src/lang/fr.json @@ -110,26 +110,8 @@ } }, "backup": { - "starting_backup": "Starting Backup...", - "saving_account": "Saving Account...", - "exporting_contacts": "Exporting Contacts...", - "saving_contacts": "Saving Contacts...", - "exporting_labels": "Exporting Labels...", - "saving_labels": "Saving Labels...", - "exporting_emails": "Exporting Emails...", - "saving_emails": "Saving Emails...", - "exporting_email_contacts": "Exporting Email Contacts...", - "saving_email_contacts": "Saving Email Contacts...", - "exporting_email_labels": "Exporting Email Labels...", - "saving_email_labels": "Saving Email Labels...", - "exporting_files": "Exporting Files...", - "saving_files": "Saving Files...", - "exporting_aliases": "Exporting Aliases...", - "saving_aliases": "Saving Aliases...", - "exporting_domains": "Exporting Custom Domains...", - "saving_domains": "Saving Custom Domains", - "success_backup": "Backup Success!!", - "failure_backup": "Backup Failed!" + "title": "Backing Up Account", + "hide": "Hide" }, "crash": { "title": "Oops! On dirait que quelque chose s'est mal passé", diff --git a/email_mailbox/src/lang/ru.json b/email_mailbox/src/lang/ru.json index 7400b0318..5e2758358 100644 --- a/email_mailbox/src/lang/ru.json +++ b/email_mailbox/src/lang/ru.json @@ -110,26 +110,8 @@ } }, "backup": { - "starting_backup": "Starting Backup...", - "saving_account": "Saving Account...", - "exporting_contacts": "Exporting Contacts...", - "saving_contacts": "Saving Contacts...", - "exporting_labels": "Exporting Labels...", - "saving_labels": "Saving Labels...", - "exporting_emails": "Exporting Emails...", - "saving_emails": "Saving Emails...", - "exporting_email_contacts": "Exporting Email Contacts...", - "saving_email_contacts": "Saving Email Contacts...", - "exporting_email_labels": "Exporting Email Labels...", - "saving_email_labels": "Saving Email Labels...", - "exporting_files": "Exporting Files...", - "saving_files": "Saving Files...", - "exporting_aliases": "Exporting Aliases...", - "saving_aliases": "Saving Aliases...", - "exporting_domains": "Exporting Custom Domains...", - "saving_domains": "Saving Custom Domains", - "success_backup": "Backup Success!!", - "failure_backup": "Backup Failed!" + "title": "Backing Up Account", + "hide": "Hide" }, "crash": { "title": "К сожалению! Похоже, что-то пошло не так",