diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 07e4c97919..7fda50a177 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -679,6 +679,9 @@ "textSave": "Save", "textRequired": "Required", "textPasswordNotMatched": "Passwords Don’t Match", + "textEncryptFile": "Encrypt File", + "textRequirePassword": "Require Password", + "textChangePassword": "Change Password", "textShowNotification": "Show Notification", "textSpaces": "Spaces", "textSpellcheck": "Spell Checking", diff --git a/apps/documenteditor/mobile/src/controller/Main.jsx b/apps/documenteditor/mobile/src/controller/Main.jsx index 2630dfc775..8100e5426e 100644 --- a/apps/documenteditor/mobile/src/controller/Main.jsx +++ b/apps/documenteditor/mobile/src/controller/Main.jsx @@ -756,9 +756,12 @@ class MainController extends Component { // Downloaded Advanced Options this.api.asc_registerCallback('asc_onAdvancedOptions', (type, advOptions, mode, formatOptions) => { - const {t} = this.props; + const { t } = this.props; const _t = t("Settings", { returnObjects: true }); + const storeAppOptions = this.props.storeAppOptions; + if(type == Asc.c_oAscAdvancedOptionsID.DRM) { + storeAppOptions.setEncryptionFile(true); onAdvancedOptions(type, _t, this._isDocReady, this.props.storeAppOptions.canRequestClose, this.isDRM); this.isDRM = true; } diff --git a/apps/documenteditor/mobile/src/controller/settings/FileEncryption.jsx b/apps/documenteditor/mobile/src/controller/settings/FileEncryption.jsx new file mode 100644 index 0000000000..ae80c5b4bb --- /dev/null +++ b/apps/documenteditor/mobile/src/controller/settings/FileEncryption.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { observer, inject } from "mobx-react"; +import EncryptionView from '../../view/settings/FileEncryption'; +import { withTranslation } from 'react-i18next'; +import { f7 } from "framework7-react"; +import { Device } from '../../../../../common/mobile/utils/device'; + +class FileEncryptionController extends React.Component { + constructor(props) { + super(props); + + this.deletePassword = this.deletePassword.bind(this); + this.setPassword = this.setPassword.bind(this); + } + + closeModal() { + if (Device.phone) { + f7.sheet.close('.settings-popup', false); + } else { + f7.popover.close('#settings-popover', false); + } + } + + setPassword(passwordValue) { + const api = Common.EditorApi.get(); + + api.asc_setCurrentPassword(passwordValue); + this.closeModal(); + } + + deletePassword() { + const api = Common.EditorApi.get(); + const appOptions = this.props.storeAppOptions; + + appOptions.setEncryptionFile(false); + api.asc_resetPassword(); + this.closeModal(); + } + + render() { + return ( + + ) + } +} + +export default inject('storeAppOptions')(observer(withTranslation()(FileEncryptionController))); \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/store/appOptions.js b/apps/documenteditor/mobile/src/store/appOptions.js index 29d1d9bc1a..d633d96fd7 100644 --- a/apps/documenteditor/mobile/src/store/appOptions.js +++ b/apps/documenteditor/mobile/src/store/appOptions.js @@ -35,12 +35,20 @@ export class storeAppOptions { setProtection: action, typeProtection: observable, - setTypeProtection: action + setTypeProtection: action, + + isFileEncrypted: observable, + setEncryptionFile: action }); } isEdit = false; + isFileEncrypted = false; + setEncryptionFile(value) { + this.isFileEncrypted = value; + } + isProtected = false; setProtection(value) { this.isProtected = value; diff --git a/apps/documenteditor/mobile/src/view/settings/FileEncryption.jsx b/apps/documenteditor/mobile/src/view/settings/FileEncryption.jsx new file mode 100644 index 0000000000..947cb1c44f --- /dev/null +++ b/apps/documenteditor/mobile/src/view/settings/FileEncryption.jsx @@ -0,0 +1,89 @@ +import React, { useState } from 'react'; +import { observer, inject } from "mobx-react"; +import { Device } from '../../../../../common/mobile/utils/device'; +import { Page, Navbar, List, ListItem, BlockTitle, Toggle, NavRight, f7, Link, ListInput, Icon, Block } from "framework7-react"; +import { useTranslation } from "react-i18next"; + +const EncryptionView = inject("storeAppOptions")(observer(props => { + const { t } = useTranslation(); + const _t = t("Settings", { returnObjects: true }); + const isIos = Device.ios; + const appOptions = props.storeAppOptions; + const isFileEncrypted = appOptions.isFileEncrypted; + const [isRequiredPassword, setRequirePassword] = useState(isFileEncrypted); + const [password, changePassword] = useState(''); + const [passwordRepeat, repeatPassword] = useState(''); + const isDisabledEncryption = isFileEncrypted && !isRequiredPassword ? false : !password.length || !passwordRepeat.length; + + const showErrorDialog = () => { + f7.dialog.create({ + title: t('Settings.textPasswordNotMatched'), + buttons: [ + { + text: t('Settings.textOk') + } + ] + }).open(); + }; + + const changeHanlder = () => { + if(isFileEncrypted && !isRequiredPassword) { + props.deletePassword(); + } else if(password !== passwordRepeat) { + showErrorDialog(); + } else { + props.setPassword(password); + } + } + + return ( + + + + + {Device.android && } + + + + {isFileEncrypted && + <> + + + { + setRequirePassword(!isRequiredPassword); + }} /> + + + + } + {(isFileEncrypted && isRequiredPassword || !isFileEncrypted) && + <> + {t('Settings.textChangePassword')} + + changePassword(e.target.value)} + className={isIos ? 'list-input-right' : ''} + /> + repeatPassword(e.target.value)} + className={isIos ? 'list-input-right' : ''} + /> + + +

If the password is forgotten or lost, it cannot be recovered.

+
+ + } +
+ ) +})); + +export default EncryptionView; \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/view/settings/Protection.jsx b/apps/documenteditor/mobile/src/view/settings/Protection.jsx index 02c3749e4e..2c08af3d52 100644 --- a/apps/documenteditor/mobile/src/view/settings/Protection.jsx +++ b/apps/documenteditor/mobile/src/view/settings/Protection.jsx @@ -16,6 +16,9 @@ const ProtectionView = inject("storeAppOptions")(observer(props => { props.onProtectClick()} link="#"> + + + ) diff --git a/apps/documenteditor/mobile/src/view/settings/Settings.jsx b/apps/documenteditor/mobile/src/view/settings/Settings.jsx index 1b45e799d6..99064ac597 100644 --- a/apps/documenteditor/mobile/src/view/settings/Settings.jsx +++ b/apps/documenteditor/mobile/src/view/settings/Settings.jsx @@ -15,6 +15,7 @@ import NavigationController from '../../controller/settings/Navigation'; import SharingSettings from "../../../../../common/mobile/lib/view/SharingSettings"; import ProtectionDocumentController from '../../controller/settings/DocumentProtection'; import ProtectionController from '../../controller/settings/Protection'; +import FileEncryptionController from '../../controller/settings/FileEncryption'; const routes = [ { @@ -85,6 +86,12 @@ const routes = [ { path: '/protect', component: ProtectionDocumentController + }, + + // Encryption + { + path: '/encrypt', + component: FileEncryptionController } ];