diff --git a/apps/common/mobile/lib/view/About.jsx b/apps/common/mobile/lib/view/About.jsx index a78dd577d..cb6035fa7 100644 --- a/apps/common/mobile/lib/view/About.jsx +++ b/apps/common/mobile/lib/view/About.jsx @@ -119,5 +119,7 @@ const PageAbout = props => { }; const About = inject("storeAppOptions")(observer(PageAbout)); +About.appVersion = () => (__PRODUCT_VERSION__); + export default About; \ No newline at end of file diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index aecdb7ff9..e2d292591 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -26,7 +26,25 @@ "List Paragraph": "List Paragraph", "footnote text": "Footnote Text" }, - "leavePageText": "You have unsaved changes in this document. Click 'Stay on this Page' to await the autosave of the document. Click 'Leave this Page' to discard all the unsaved changes." + "leavePageText": "You have unsaved changes in this document. Click 'Stay on this Page' to await the autosave of the document. Click 'Leave this Page' to discard all the unsaved changes.", + "titleLicenseExp": "License expired", + "warnLicenseExp": "Your license has expired. Please update your license and refresh the page.", + "errorServerVersion": "The editor version has been updated. The page will be reloaded to apply the changes.", + "titleServerVersion": "Editor updated", + "notcriticalErrorTitle": "Warning", + "errorOpensource": "Using the free Community version you can open documents for viewing only. To access mobile web editors, a commercial license is required.", + "warnLicenseLimitedNoAccess": "License expired. You have no access to document editing functionality. Please contact your administrator.", + "warnLicenseLimitedRenewed": "License needs to be renewed. You have a limited access to document editing functionality.
Please contact your administrator to get full access", + "warnLicenseExceeded": "You've reached the limit for simultaneous connections to %1 editors. This document will be opened for viewing only. Contact your administrator to learn more.", + "warnLicenseUsersExceeded": "You've reached the user limit for %1 editors. Contact your administrator to learn more.", + "warnNoLicense": "You've reached the limit for simultaneous connections to %1 editors. This document will be opened for viewing only. Contact %1 sales team for personal upgrade terms.", + "warnNoLicenseUsers": "You've reached the user limit for %1 editors. Contact %1 sales team for personal upgrade terms.", + "textBuyNow": "Visit website", + "textContactUs": "Contact sales", + "textNoLicenseTitle": "License limit reached", + "textPaidFeature": "Paid feature", + "textCustomLoader": "Please note that according to the terms of the license you are not entitled to change the loader. Please contact our Sales Department to get a quote.", + "textClose": "Close" }, "Toolbar": { "dlgLeaveTitleText": "You leave the application", diff --git a/apps/documenteditor/mobile/src/controller/Main.jsx b/apps/documenteditor/mobile/src/controller/Main.jsx index 540ca4398..0051a04e5 100644 --- a/apps/documenteditor/mobile/src/controller/Main.jsx +++ b/apps/documenteditor/mobile/src/controller/Main.jsx @@ -13,6 +13,7 @@ import { EditCommentController, ViewCommentsController } from "../../../../common/mobile/lib/controller/collaboration/Comments"; +import About from '../../../../common/mobile/lib/view/About'; import patch from '../lib/patch' @@ -30,6 +31,13 @@ class MainController extends Component { constructor(props) { super(props); window.editorType = 'de'; + + this._state = { + licenseType: false + }; + + const { t } = this.props; + this._t = t('Main', {returnObjects:true}); } initSdk() { @@ -112,7 +120,7 @@ class MainController extends Component { this.api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions); this.api.asc_registerCallback('asc_onDocumentContentReady', onDocumentContentReady); - // this.api.asc_registerCallback('asc_onLicenseChanged', _.bind(this.onLicenseChanged, this)); + this.api.asc_registerCallback('asc_onLicenseChanged', this.onLicenseChanged.bind(this)); // this.api.asc_registerCallback('asc_onRunAutostartMacroses', _.bind(this.onRunAutostartMacroses, this)); this.api.asc_setDocInfo(docInfo); this.api.asc_getEditorPermissions(this.editorConfig.licenseUrl, this.editorConfig.customerId); @@ -138,6 +146,20 @@ class MainController extends Component { const licType = params.asc_getLicenseType(); // check licType + if (Asc.c_oLicenseResult.Expired === licType || + Asc.c_oLicenseResult.Error === licType || + Asc.c_oLicenseResult.ExpiredTrial === licType) { + f7.dialog.create({ + title : this._t.titleLicenseExp, + text : this._t.warnLicenseExp + }).open(); + return; + } + if (Asc.c_oLicenseResult.ExpiredLimited === licType) { + this._state.licenseType = licType; + } + + if ( this.onServerVersion(params.asc_getBuildVersion()) ) return; this.appOptions.canLicense = (licType === Asc.c_oLicenseResult.Success || licType === Asc.c_oLicenseResult.SuccessLimit); @@ -158,6 +180,8 @@ class MainController extends Component { f7.emit('resize'); Common.Notifications.trigger('document:ready'); + + this._isDocReady = true; }; const _process_array = (array, fn) => { @@ -241,9 +265,7 @@ class MainController extends Component { this.api.asc_continueSaving(); }, 500); - const { t } = this.props; - const _t = t('Main', {returnObjects:true}) - return _t.leavePageText; + return this._t.leavePageText; } } @@ -252,8 +274,118 @@ class MainController extends Component { clearTimeout(this.continueSavingTimer); } - applyLicense () { + onLicenseChanged (params) { + const appOptions = this.props.storeAppOptions; + const licType = params.asc_getLicenseType(); + if (licType !== undefined && appOptions.canEdit && appOptions.config.mode !== 'view' && + (licType === Asc.c_oLicenseResult.Connections || licType === Asc.c_oLicenseResult.UsersCount || licType === Asc.c_oLicenseResult.ConnectionsOS || licType === Asc.c_oLicenseResult.UsersCountOS + || licType === Asc.c_oLicenseResult.SuccessLimit && (appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0)) + this._state.licenseType = licType; + if (this._isDocReady && this._state.licenseType) + this.applyLicense(); + } + applyLicense () { + const _t = this._t; + const appOptions = this.props.storeAppOptions; + if (appOptions.config.mode !== 'view' && !patch.isSupportEditFeature()) { + let value = LocalStorage.getItem("de-opensource-warning"); + value = (value !== null) ? parseInt(value) : 0; + const now = (new Date).getTime(); + if (now - value > 86400000) { + LocalStorage.setItem("de-opensource-warning", now); + f7.dialog.create({ + title: _t.notcriticalErrorTitle, + text : _t.errorOpensource, + buttons: [{text: 'OK'}] + }).open(); + } + Common.Notifications.trigger('toolbar:activatecontrols'); + return; + } + + if (this._state.licenseType) { + let license = this._state.licenseType; + let buttons = [{text: 'OK'}]; + if ((appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0 && + (license === Asc.c_oLicenseResult.SuccessLimit || + license === Asc.c_oLicenseResult.ExpiredLimited || + appOptions.permissionsLicense === Asc.c_oLicenseResult.SuccessLimit) + ) { + license = (license === Asc.c_oLicenseResult.ExpiredLimited) ? _t.warnLicenseLimitedNoAccess : _t.warnLicenseLimitedRenewed; + } else if (license === Asc.c_oLicenseResult.Connections || license === Asc.c_oLicenseResult.UsersCount) { + license = (license===Asc.c_oLicenseResult.Connections) ? _t.warnLicenseExceeded : _t.warnLicenseUsersExceeded; + } else { + license = (license === Asc.c_oLicenseResult.ConnectionsOS) ? _t.warnNoLicense : _t.warnNoLicenseUsers; + buttons = [{ + text: _t.textBuyNow, + bold: true, + onClick: function() { + window.open(`${__PUBLISHER_URL__}`, "_blank"); + } + }, + { + text: _t.textContactUs, + onClick: function() { + window.open(`mailto:${__SALES_EMAIL__}`, "_blank"); + } + }]; + } + if (this._state.licenseType === Asc.c_oLicenseResult.SuccessLimit) { + Common.Notifications.trigger('toolbar:activatecontrols'); + } else { + Common.Notifications.trigger('toolbar:activatecontrols'); + Common.Notifications.trigger('toolbar:deactivateeditcontrols'); + Common.Notifications.trigger('api:disconnect'); + } + + let value = LocalStorage.getItem("de-license-warning"); + value = (value !== null) ? parseInt(value) : 0; + const now = (new Date).getTime(); + + if (now - value > 86400000) { + LocalStorage.setItem("de-license-warning", now); + f7.dialog.create({ + title: _t.textNoLicenseTitle, + text : license, + buttons: buttons + }).open(); + } + } else { + if (!appOptions.isDesktopApp && !appOptions.canBrandingExt && + appOptions.config && appOptions.config.customization && (appOptions.config.customization.loaderName || appOptions.config.customization.loaderLogo)) { + f7.dialog.create({ + title: _t.textPaidFeature, + text : _t.textCustomLoader, + buttons: [{ + text: _t.textContactUs, + bold: true, + onClick: () => { + window.open(`mailto:${__SALES_EMAIL__}`, "_blank"); + } + }, + { text: _t.textClose }] + }).open(); + } + Common.Notifications.trigger('toolbar:activatecontrols'); + } + } + + onServerVersion (buildVersion) { + if (this.changeServerVersion) return true; + const _t = this._t; + + if (About.appVersion() !== buildVersion && !window.compareVersions) { + this.changeServerVersion = true; + f7.dialog.alert( + _t.errorServerVersion, + _t.titleServerVersion, + () => { + setTimeout(() => {Common.Gateway.updateVersion()}, 0); + }); + return true; + } + return false; } bindEvents() { diff --git a/apps/documenteditor/mobile/src/controller/Toolbar.jsx b/apps/documenteditor/mobile/src/controller/Toolbar.jsx index 53c8683d5..609c072fe 100644 --- a/apps/documenteditor/mobile/src/controller/Toolbar.jsx +++ b/apps/documenteditor/mobile/src/controller/Toolbar.jsx @@ -22,6 +22,8 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeReview')(prop api.asc_registerCallback('asc_onFocusObject', onApiFocusObject); api.asc_registerCallback('asc_onCoAuthoringDisconnect', onCoAuthoringDisconnect); Common.Notifications.on('api:disconnect', onCoAuthoringDisconnect); + Common.Notifications.on('toolbar:activatecontrols', activateControls); + Common.Notifications.on('toolbar:deactivateeditcontrols', deactivateEditControls); }; if ( !Common.EditorApi ) { Common.Notifications.on('document:ready', onDocumentReady); @@ -35,6 +37,8 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeReview')(prop Common.Notifications.off('document:ready', onDocumentReady); Common.Notifications.off('setdoctitle', setDocTitle); Common.Notifications.off('api:disconnect', onCoAuthoringDisconnect); + Common.Notifications.off('toolbar:activatecontrols', activateControls); + Common.Notifications.off('toolbar:deactivateeditcontrols', deactivateEditControls); const api = Common.EditorApi.get(); api.asc_unregisterCallback('asc_onCanUndo', onApiCanUndo); @@ -163,6 +167,11 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeReview')(prop f7.popup.close(); }; + const [disabledControls, setDisabledControls] = useState(true); + const activateControls = () => { + setDisabledControls(false); + }; + return ( { return ( - {props.isShowBack && } + {props.isShowBack && } {!Device.phone && {props.docTitle}} - props.openOptions('edit')}> - props.openOptions('add')}> - { Device.phone ? null : } - {props.displayCollaboration && props.openOptions('coauth')}>} - props.openOptions('settings')}> + props.openOptions('edit')}> + props.openOptions('add')}> + { Device.phone ? null : } + {props.displayCollaboration && props.openOptions('coauth')}>} + props.openOptions('settings')}> ) diff --git a/vendor/framework7-react/build/webpack.config.js b/vendor/framework7-react/build/webpack.config.js index ea3bc262f..fd4ef23c5 100644 --- a/vendor/framework7-react/build/webpack.config.js +++ b/vendor/framework7-react/build/webpack.config.js @@ -156,7 +156,7 @@ module.exports = { new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(env), 'process.env.TARGET': JSON.stringify(target), - __PRODUCT_VERSION__: JSON.stringify(process.env.PRODUCT_VERSION ? process.env.PRODUCT_VERSION : '0.0.1'), + __PRODUCT_VERSION__: JSON.stringify(process.env.PRODUCT_VERSION ? process.env.PRODUCT_VERSION : '6.2.0'), __PUBLISHER_ADDRESS__: JSON.stringify('20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050'), __SUPPORT_EMAIL__: JSON.stringify('support@onlyoffice.com'), __PUBLISHER_PHONE__: JSON.stringify('+371 633-99867'),