diff --git a/apps/common/main/resources/less/colors-table-night.less b/apps/common/main/resources/less/colors-table-night.less
index 959a2b590a..a265b6d2b6 100644
--- a/apps/common/main/resources/less/colors-table-night.less
+++ b/apps/common/main/resources/less/colors-table-night.less
@@ -233,8 +233,8 @@
--background-fill-input-disabled: var(--background-normal);
--background-fill-input-readonly: var(--background-normal);
- --highlight-category-button-hover: rgba(18, 132, 238, 0.05);
- --highlight-category-button-pressed: rgba(18, 132, 238, 0.12);
+ --highlight-category-button-hover: #585858;
+ --highlight-category-button-pressed: #2d2d2d;
--highlight-header-input-hover: var(--highlight-header-button-hover);
--highlight-header-input-pressed: var(--background-fill-input);
diff --git a/apps/common/main/resources/less/colors-table-white.less b/apps/common/main/resources/less/colors-table-white.less
index 566d620d5a..facfecd5d2 100644
--- a/apps/common/main/resources/less/colors-table-white.less
+++ b/apps/common/main/resources/less/colors-table-white.less
@@ -235,8 +235,8 @@
--background-fill-input-disabled: var(--background-normal);
--background-fill-input-readonly: var(--background-normal);
- --highlight-category-button-hover: rgba(18, 132, 238, 0.05);
- --highlight-category-button-pressed: rgba(18, 132, 238, 0.12);
+ --highlight-category-button-hover: #EAEAEA;
+ --highlight-category-button-pressed: #d8d8d8;
--highlight-header-input-hover: var(--highlight-header-button-hover);
--highlight-header-input-pressed: var(--background-fill-input);
diff --git a/apps/common/mobile/lib/controller/collaboration/Collaboration.jsx b/apps/common/mobile/lib/controller/collaboration/Collaboration.jsx
index f7eee5b16d..1be49c4e50 100644
--- a/apps/common/mobile/lib/controller/collaboration/Collaboration.jsx
+++ b/apps/common/mobile/lib/controller/collaboration/Collaboration.jsx
@@ -43,9 +43,11 @@ class CollaborationController extends Component {
}
} else if (!appOptions.isEdit && appOptions.isRestrictedEdit) {
isFastCoauth = true;
- api.asc_SetFastCollaborative(isFastCoauth);
+ const lsvalue = LocalStorage.getItem(`${window.editorType}-mobile-autosave`),
+ intvalue = lsvalue != null ? parseInt(lsvalue) : 1;
+ api.asc_setAutoSaveGap(intvalue);
+ api.asc_SetFastCollaborative(intvalue == 1);
window.editorType === 'de' && api.SetCollaborativeMarksShowType(Asc.c_oAscCollaborativeMarksShowType.None);
- api.asc_setAutoSaveGap(1);
} else if (appOptions.canLiveView) { // viewer
isFastCoauth = !(appOptions.config.coEditing && appOptions.config.coEditing.mode==='strict');
api.asc_SetFastCollaborative(isFastCoauth);
@@ -62,10 +64,18 @@ class CollaborationController extends Component {
if (window.editorType === 'sse') {
value = appOptions.canAutosave ? 1 : 0; // FORCE AUTOSAVE
} else {
- value = isFastCoauth; // Common.localStorage.getItem("de-settings-autosave");
- value = (!isFastCoauth && value !== null) ? parseInt(value) : (appOptions.canCoAuthoring ? 1 : 0);
+ value = appOptions.canCoAuthoring && isFastCoauth ? 1 : 0;
+ }
+
+ if ( !value ) {
+ api.asc_SetFastCollaborative(false);
+ api.asc_setAutoSaveGap(0);
+ } else {
+ const lsvalue = LocalStorage.getItem(`${window.editorType}-mobile-autosave`),
+ intvalue = lsvalue != null ? parseInt(lsvalue) : 1;
+ api.asc_setAutoSaveGap(intvalue);
+ api.asc_SetFastCollaborative(intvalue == 1);
}
- api.asc_setAutoSaveGap(value);
}
/** coauthoring end **/
}
diff --git a/apps/common/mobile/resources/less/colors-table-dark.less b/apps/common/mobile/resources/less/colors-table-dark.less
index c1e3e859d3..e6a71f4b2f 100644
--- a/apps/common/mobile/resources/less/colors-table-dark.less
+++ b/apps/common/mobile/resources/less/colors-table-dark.less
@@ -6,6 +6,7 @@
--background-tertiary: #131313;
--background-menu-divider: fade(#545458, 50%);
--background-button: #333333;
+ --background-notification-badge: #F4D804;
--text-normal: fade(#FFF, 87%);
--text-secondary: fade(#FFF, 60%);
diff --git a/apps/common/mobile/resources/less/colors-table.less b/apps/common/mobile/resources/less/colors-table.less
index da8490f437..6552359df0 100644
--- a/apps/common/mobile/resources/less/colors-table.less
+++ b/apps/common/mobile/resources/less/colors-table.less
@@ -14,6 +14,7 @@
--background-tertiary: #EFF0F5;
--background-menu-divider: fade(#3C3C43, 15%);
--background-button: #EFF0F5;
+ --background-notification-badge: #F4D804;
--text-normal: #000000;
--text-secondary: fade(#000, 60%);
@@ -97,6 +98,7 @@
@background-tertiary: var(--background-tertiary);
@background-menu-divider: var(--background-menu-divider);
@background-button: var(--background-button);
+@background-notification-badge: var(--background-notification-badge);
@text-normal: var(--text-normal);
@text-secondary: var(--text-secondary);
diff --git a/apps/common/mobile/resources/less/common-ios.less b/apps/common/mobile/resources/less/common-ios.less
index b6db7dd911..a308fa9a63 100644
--- a/apps/common/mobile/resources/less/common-ios.less
+++ b/apps/common/mobile/resources/less/common-ios.less
@@ -92,6 +92,16 @@
}
}
+ .title {
+ .subtitle {
+ color: inherit;
+ margin-bottom: 16px;
+ margin-top: -10px;
+ font-size: 12px;
+ color: @text-secondary;
+ }
+ }
+
.subnavbar {
.icon-back {
color: @brandColor;
diff --git a/apps/common/mobile/resources/less/common-material.less b/apps/common/mobile/resources/less/common-material.less
index 5bd1b63f51..cb7008c9f5 100644
--- a/apps/common/mobile/resources/less/common-material.less
+++ b/apps/common/mobile/resources/less/common-material.less
@@ -440,6 +440,14 @@
}
}
+ .title {
+ .subtitle {
+ color: inherit;
+ margin-bottom: 5px;
+ margin-top: 3px;
+ }
+ }
+
.subnavbar .title {
font-size: 14px;
font-weight: normal;
diff --git a/apps/common/mobile/resources/less/common.less b/apps/common/mobile/resources/less/common.less
index 0415edf2bc..286239cdcb 100644
--- a/apps/common/mobile/resources/less/common.less
+++ b/apps/common/mobile/resources/less/common.less
@@ -83,6 +83,20 @@
.icon-back {
color: @toolbar-icons;
}
+ .link {
+ &.notify {
+ &::before {
+ content: ' ';
+ position: absolute;
+ width: 10px;
+ height: 10px;
+ bottom: 8px;
+ right: 10px;
+ background-color: @background-notification-badge;
+ border-radius: 6px;
+ }
+ }
+ }
}
.page.page-with-subnavbar {
@@ -153,6 +167,21 @@
}
}
}
+
+ &.notify {
+ .item-media {
+ &::before {
+ content: ' ';
+ position: absolute;
+ width: 10px;
+ height: 10px;
+ bottom: 8px;
+ right: 1px;
+ background-color: @background-notification-badge;
+ border-radius: 6px;
+ }
+ }
+ }
}
.item-text {
text-overflow: initial;
diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json
index d40522f7dd..3e34528504 100644
--- a/apps/documenteditor/mobile/locale/en.json
+++ b/apps/documenteditor/mobile/locale/en.json
@@ -533,7 +533,8 @@
"txtEditingMode": "Set editing mode...",
"uploadImageTextText": "Uploading image...",
"uploadImageTitleText": "Uploading Image",
- "waitText": "Please, wait..."
+ "waitText": "Please, wait...",
+ "changesSaved": "All changes saved"
},
"Main": {
"criticalErrorTitle": "Error",
@@ -744,6 +745,8 @@
"textFind": "Find",
"textFindAndReplace": "Find and Replace",
"textFindAndReplaceAll": "Find and Replace All",
+ "textSaveDocument": "Save",
+ "textAutoSaveDocument": "Autosave",
"textFormat": "Format",
"textHelp": "Help",
"textHiddenTableBorders": "Hidden Table Borders",
diff --git a/apps/documenteditor/mobile/src/controller/LongActions.jsx b/apps/documenteditor/mobile/src/controller/LongActions.jsx
index 0842b121e1..10a66d171e 100644
--- a/apps/documenteditor/mobile/src/controller/LongActions.jsx
+++ b/apps/documenteditor/mobile/src/controller/LongActions.jsx
@@ -74,7 +74,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
let action = {id: id, type: type};
stackLongActions.pop(action);
- //this.updateWindowTitle(true);
+ Common.Notifications.trigger('update:windowtitle', true);
action = stackLongActions.get({type: Asc.c_oAscAsyncActionType.Information}) || stackLongActions.get({type: Asc.c_oAscAsyncActionType.BlockInteraction});
@@ -87,6 +87,9 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
}
if (id===Asc.c_oAscAsyncAction['Submit'] && !submitFail) {
Common.Gateway.submitForm();
+ } else if ((id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton'])) {
+ storeAppOptions.changeSavingDocStatusText(_t.changesSaved);
+ storeAppOptions.isSaveBadgeShown && storeAppOptions.changeIsSaveBadgeShown(false);
}
};
@@ -104,6 +107,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
case Asc.c_oAscAsyncAction['Save']:
title = _t.saveTitleText;
// text = _t.saveTextText;
+ storeAppOptions.changeSavingDocStatusText(_t.saveTextText);
break;
case Asc.c_oAscAsyncAction['LoadDocumentFonts']:
@@ -206,7 +210,6 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
loadMask = f7.dialog.preloader(title);
}
}
-
};
const onConfirmAction = (id, apiCallback, data) => {
diff --git a/apps/documenteditor/mobile/src/controller/Main.jsx b/apps/documenteditor/mobile/src/controller/Main.jsx
index 9a2d6e9a1e..7257fa0e88 100644
--- a/apps/documenteditor/mobile/src/controller/Main.jsx
+++ b/apps/documenteditor/mobile/src/controller/Main.jsx
@@ -382,6 +382,8 @@ class MainController extends Component {
this.updateWindowTitle(true);
+ appOptions.changeAutosave(LocalStorage.itemExists('de-mobile-autosave') ? LocalStorage.getBool("de-mobile-autosave") : true);
+
value = LocalStorage.getBool("de-mobile-no-characters");
appSettings.changeNoCharacters(value);
this.api.put_ShowParaMarks(value);
@@ -638,6 +640,7 @@ class MainController extends Component {
this.api.asc_registerCallback('asc_onDocumentModifiedChanged', this.onDocumentModifiedChanged.bind(this));
this.api.asc_registerCallback('asc_onDocumentCanSaveChanged', this.onDocumentCanSaveChanged.bind(this));
+ this.api.asc_registerCallback('asc_onCollaborativeChanges', this.onCollaborativeChanges.bind(this));
Common.Notifications.trigger('preloader:close');
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.ApplyEditRights);
@@ -661,7 +664,14 @@ class MainController extends Component {
}
onDocumentCanSaveChanged (isCanSave) {
- //
+ const storeAppOptions = this.props.storeAppOptions;
+ storeAppOptions.changeIsSaveBadgeShown(isCanSave);
+ }
+
+ onCollaborativeChanges () {
+ const storeAppOptions = this.props.storeAppOptions;
+ if (!storeAppOptions.isSaveBadgeShown) storeAppOptions.changeIsSaveBadgeShown(true);
+ storeAppOptions.changeSavingDocStatusText('');
}
onBeforeUnload () {
@@ -1037,6 +1047,7 @@ class MainController extends Component {
});
Common.Notifications.on('markfavorite', this.markFavorite.bind(this));
+ Common.Notifications.on('update:windowtitle', force => this.updateWindowTitle(force));
}
insertImageFromStorage(data) {
@@ -1449,6 +1460,9 @@ class MainController extends Component {
window.document.title = title;
}
+ if (isModified)
+ this.props.storeAppOptions.changeSavingDocStatusText('');
+
this._isDocReady && (this._state.isDocModified !== isModified) && Common.Gateway.setDocumentModified(isModified);
this._state.isDocModified = isModified;
}
diff --git a/apps/documenteditor/mobile/src/controller/Toolbar.jsx b/apps/documenteditor/mobile/src/controller/Toolbar.jsx
index 8b37e48672..5f48b62e6b 100644
--- a/apps/documenteditor/mobile/src/controller/Toolbar.jsx
+++ b/apps/documenteditor/mobile/src/controller/Toolbar.jsx
@@ -465,6 +465,7 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeReview', 'sto
canSubmitForms={appOptions.canSubmitForms}
forceDesktopMode={forceDesktopMode}
isHiddenFileName={appOptions.config?.customization?.toolbarHideFileName ?? false}
+ isSaveBadgeShown={appOptions.isSaveBadgeShown}
disableForceDesktop={appOptions.disableForceDesktop !== false}
/>
)
diff --git a/apps/documenteditor/mobile/src/controller/settings/Settings.jsx b/apps/documenteditor/mobile/src/controller/settings/Settings.jsx
index 46c9b564d4..043a7737e5 100644
--- a/apps/documenteditor/mobile/src/controller/settings/Settings.jsx
+++ b/apps/documenteditor/mobile/src/controller/settings/Settings.jsx
@@ -191,6 +191,17 @@ const SettingsController = props => {
Common.Notifications.trigger('markfavorite', !isFavorite);
};
+ const switchAutosave = (value) => {
+ const api = Common.EditorApi.get();
+ LocalStorage.setBool("de-mobile-autosave", value);
+ api.asc_SetFastCollaborative(value);
+ api.asc_setAutoSaveGap(value ? 1 : 0);
+ };
+
+ const tryToSave = () => {
+ Common.EditorApi.get().asc_Save();
+ };
+
const saveAsPdf = () => {
const api = Common.EditorApi.get();
@@ -221,6 +232,8 @@ const SettingsController = props => {
closeModal,
clearAllFields,
toggleFavorite,
+ switchAutosave,
+ tryToSave,
saveAsPdf,
submitForm
}}>
diff --git a/apps/documenteditor/mobile/src/store/appOptions.js b/apps/documenteditor/mobile/src/store/appOptions.js
index d86b8c2ab7..3f60d2d324 100644
--- a/apps/documenteditor/mobile/src/store/appOptions.js
+++ b/apps/documenteditor/mobile/src/store/appOptions.js
@@ -46,6 +46,15 @@ export class storeAppOptions {
isFavorite: observable,
setFavorite: action,
+ isAutosave: observable,
+ changeAutosave: action,
+
+ isSaveBadgeShown: observable,
+ changeIsSaveBadgeShown: action,
+
+ savingDocStatusText: observable,
+ changeSavingDocStatusText: action,
+
customization: observable,
});
}
@@ -110,6 +119,21 @@ export class storeAppOptions {
this.isDocReady = value;
}
+ isAutosave = true;
+ changeAutosave (value) {
+ this.isAutosave = value;
+ }
+
+ isSaveBadgeShown = false;
+ changeIsSaveBadgeShown (value) {
+ this.isSaveBadgeShown = value;
+ }
+
+ savingDocStatusText = '';
+ changeSavingDocStatusText (value) {
+ this.savingDocStatusText = value;
+ }
+
config = {};
customization;
diff --git a/apps/documenteditor/mobile/src/view/Toolbar.jsx b/apps/documenteditor/mobile/src/view/Toolbar.jsx
index 69837a4e37..ad94703445 100644
--- a/apps/documenteditor/mobile/src/view/Toolbar.jsx
+++ b/apps/documenteditor/mobile/src/view/Toolbar.jsx
@@ -135,7 +135,7 @@ const ToolbarView = props => {
: null),
- props.openOptions('settings')}>
+ props.openOptions('settings')}>
{Device.ios ?
:
diff --git a/apps/documenteditor/mobile/src/view/settings/SettingsPage.jsx b/apps/documenteditor/mobile/src/view/settings/SettingsPage.jsx
index a246bf64ae..132020fafe 100644
--- a/apps/documenteditor/mobile/src/view/settings/SettingsPage.jsx
+++ b/apps/documenteditor/mobile/src/view/settings/SettingsPage.jsx
@@ -46,7 +46,10 @@ const SettingsPage = inject("storeAppOptions", "storeReview", "storeDocumentInfo
const isHistoryDisabled = docExt && (docExt === 'xps' || docExt === 'djvu' || docExt === 'pdf');
const navbar =
- {docTitle}
+
+ {docTitle}
+ {appOptions.savingDocStatusText}
+
{Device.phone && {_t.textDone}}
;
const isSignatureForm = props.storeToolbarSettings.isSignatureForm;
@@ -67,6 +70,7 @@ const SettingsPage = inject("storeAppOptions", "storeReview", "storeDocumentInfo
const canUseHistory = appOptions.canUseHistory;
const gobackTitle = appOptions.customization?.goback?.text || _t.textOpenLocation;
const isShowBack = props.storeToolbarSettings.isShowBack;
+ const isAutosave = appOptions.isAutosave;
let _isEdit = false,
_canDownload = false,
@@ -104,131 +108,158 @@ const SettingsPage = inject("storeAppOptions", "storeReview", "storeDocumentInfo
return (
{navbar}
-
- {isShowBack &&
- Common.Notifications.trigger('goback')}>
- {Device.ios ?
- :
-
- }
-
- }
- {isEditableForms ? [
- (isFavorite !== undefined && isFavorite !== null ?
-
- {isFavorite ?
-
- :
-
+ <>
+
+ {isShowBack &&
+ Common.Notifications.trigger('goback')}>
+ {Device.ios ?
+ :
+
}
- : ''),
-
-
+ }
+ {isEditableForms ? [
+ (isFavorite !== undefined && isFavorite !== null ?
+
+ {isFavorite ?
+
+ :
+
+ }
+
+ : ''),
+
+
+
+ ] : null}
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+ {
+ appOptions.changeAutosave(!isAutosave);
+ settingsContext.switchAutosave(!isAutosave);
+ }}
+ />
+
+ }
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+
+
+ {(Device.phone || isEditableForms) &&
+
+
+
+ }
+ {(_isEdit && canProtect) &&
+
+
+
+ }
+ {_isEdit && !isHistoryDisabled && canUseHistory &&
+ {
+ if(Device.phone) {
+ onOpenOptions('history');
+ }
+ }}>
+
+
+ }
+ {!isEditableForms ?
+ {
+ if(Device.phone) {
+ onOpenOptions('navigation');
+ }
+ }}>
+
+
+ : null}
+ {window.matchMedia("(max-width: 359px)").matches ?
+ {
+ onOpenOptions('coauth');
+ }} className='no-indicator'>
+
+
+ : null}
+ {Device.sailfish && _isEdit &&
+ settingsContext.onOrthographyCheck()} className='no-indicator' link="#">
+
+
+ }
+ {(appOptions.isMobileViewAvailable && ((Device.phone && !isViewer) || isEditableForms)) &&
+
+
+ {
+ onOpenOptions('snackbar');
+ settingsContext.onChangeMobileView();
+ }} />
+
+ }
+ {(_isEdit && !isViewer) &&
+
+
+
+ }
+
+
- ] : null}
- {(Device.phone || isEditableForms) &&
-
-
-
- }
- {(_isEdit && canProtect) &&
-
-
-
- }
- {_isEdit && !isHistoryDisabled && canUseHistory &&
- {
- if(Device.phone) {
- onOpenOptions('history');
- }
- }}>
-
-
- }
- {!isEditableForms ?
- {
- if(Device.phone) {
- onOpenOptions('navigation');
- }
- }}>
-
-
- : null}
- {window.matchMedia("(max-width: 359px)").matches ?
- {
- onOpenOptions('coauth');
- }} className='no-indicator'>
-
-
- : null}
- {Device.sailfish && _isEdit &&
- settingsContext.onOrthographyCheck()} className='no-indicator' link="#">
-
-
- }
- {(appOptions.isMobileViewAvailable && ((Device.phone && !isViewer) || isEditableForms)) &&
-
-
- {
- onOpenOptions('snackbar');
- settingsContext.onChangeMobileView();
- }} />
-
- }
- {(_isEdit && !isViewer) &&
-
-
-
- }
-
-
-
- {_canDownload &&
-
- {isEditableForms ?
- :
+ {_canDownload &&
+
+ {isEditableForms ?
+ :
+
+ }
+
+ }
+ {_canDownloadOrigin &&
+
- }
-
- }
- {_canDownloadOrigin &&
-
-
-
- }
- {_canPrint &&
-
-
-
- }
- {!(!_canDisplayInfo && isBranding) &&
-
-
-
- }
- {_canHelp &&
-
-
-
- }
- {_canAbout &&
-
-
-
- }
- {_canFeedback &&
-
- {Device.ios ?
- :
-
- }
-
- }
- {canCloseEditor &&
- Common.Notifications.trigger('close')}>
- }
-
+
+ }
+ {_canPrint &&
+
+
+
+ }
+ {!(!_canDisplayInfo && isBranding) &&
+
+
+
+ }
+ {_canHelp &&
+
+
+
+ }
+ {_canAbout &&
+
+
+
+ }
+ {_canFeedback &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+ {canCloseEditor &&
+ Common.Notifications.trigger('close')}>
+ }
+
+ >
+
)
}));
diff --git a/apps/presentationeditor/mobile/locale/en.json b/apps/presentationeditor/mobile/locale/en.json
index 96ee375d05..43aed553f8 100644
--- a/apps/presentationeditor/mobile/locale/en.json
+++ b/apps/presentationeditor/mobile/locale/en.json
@@ -278,7 +278,8 @@
"txtEditingMode": "Set editing mode...",
"uploadImageTextText": "Uploading image...",
"uploadImageTitleText": "Uploading Image",
- "waitText": "Please, wait..."
+ "waitText": "Please, wait...",
+ "changesSaved": "All changes saved"
},
"Toolbar": {
"btnRestartNow": "Restart now",
@@ -580,6 +581,8 @@
"textFind": "Find",
"textFindAndReplace": "Find and Replace",
"textFindAndReplaceAll": "Find and Replace All",
+ "textSaveDocument": "Save",
+ "textAutoSaveDocument": "Autosave",
"textHelp": "Help",
"textHighlight": "Highlight Results",
"textInch": "Inch",
diff --git a/apps/presentationeditor/mobile/src/controller/LongActions.jsx b/apps/presentationeditor/mobile/src/controller/LongActions.jsx
index 346764ff5b..2d7ddf24d6 100644
--- a/apps/presentationeditor/mobile/src/controller/LongActions.jsx
+++ b/apps/presentationeditor/mobile/src/controller/LongActions.jsx
@@ -68,7 +68,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
let action = {id: id, type: type};
stackLongActions.pop(action);
- //this.updateWindowTitle(true);
+ Common.Notifications.trigger('update:windowtitle', true);
action = stackLongActions.get({type: Asc.c_oAscAsyncActionType.Information}) || stackLongActions.get({type: Asc.c_oAscAsyncActionType.BlockInteraction});
@@ -79,6 +79,11 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
f7.dialog.close(loadMask.el) :
f7.dialog.close($$('.dialog-preloader'));
}
+
+ if ((id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton'])) {
+ storeAppOptions.changeSavingDocStatusText(_t.changesSaved);
+ storeAppOptions.isSaveBadgeShown && storeAppOptions.changeIsSaveBadgeShown(false);
+ }
};
const setLongActionView = (action) => {
@@ -94,6 +99,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
case Asc.c_oAscAsyncAction['Save']:
title = _t.saveTitleText;
// text = _t.saveTextText;
+ storeAppOptions.changeSavingDocStatusText(_t.saveTextText);
break;
case Asc.c_oAscAsyncAction['LoadDocumentFonts']:
diff --git a/apps/presentationeditor/mobile/src/controller/Main.jsx b/apps/presentationeditor/mobile/src/controller/Main.jsx
index 17929691ca..c71fb1f82f 100644
--- a/apps/presentationeditor/mobile/src/controller/Main.jsx
+++ b/apps/presentationeditor/mobile/src/controller/Main.jsx
@@ -326,6 +326,7 @@ class MainController extends Component {
this.api.asc_registerCallback('asc_onDocumentModifiedChanged', this.onDocumentModifiedChanged.bind(this));
this.api.asc_registerCallback('asc_onDocumentCanSaveChanged', this.onDocumentCanSaveChanged.bind(this));
+ this.api.asc_registerCallback('asc_onCollaborativeChanges', this.onCollaborativeChanges.bind(this));
Common.Notifications.trigger('preloader:close');
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.ApplyEditRights);
@@ -379,7 +380,14 @@ class MainController extends Component {
}
onDocumentCanSaveChanged (isCanSave) {
- //
+ const storeAppOptions = this.props.storeAppOptions;
+ storeAppOptions.changeIsSaveBadgeShown(isCanSave);
+ }
+
+ onCollaborativeChanges () {
+ const storeAppOptions = this.props.storeAppOptions;
+ if (!storeAppOptions.isSaveBadgeShown) storeAppOptions.changeIsSaveBadgeShown(true);
+ storeAppOptions.changeSavingDocStatusText('');
}
onBeforeUnload () {
@@ -542,6 +550,8 @@ class MainController extends Component {
storePresentationInfo.changeTitle(meta.title);
}
});
+
+ Common.Notifications.on('update:windowtitle', force => this.updateWindowTitle(force));
}
insertImageFromStorage(data) {
@@ -582,6 +592,8 @@ class MainController extends Component {
appSettings.changeSpellCheck(value);
this.api.asc_setSpellCheck(value);
+ appOptions.changeAutosave(LocalStorage.itemExists('pe-mobile-autosave') ? LocalStorage.getBool("pe-mobile-autosave") : true);
+
this.updateWindowTitle(true);
if (appOptions.isEdit && this.needToUpdateVersion) {
@@ -883,6 +895,9 @@ class MainController extends Component {
window.document.title = title;
}
+ if (isModified)
+ this.props.storeAppOptions.changeSavingDocStatusText('');
+
this._isDocReady && (this._state.isDocModified !== isModified) && Common.Gateway.setDocumentModified(isModified);
this._state.isDocModified = isModified;
}
diff --git a/apps/presentationeditor/mobile/src/controller/Toolbar.jsx b/apps/presentationeditor/mobile/src/controller/Toolbar.jsx
index aab03127f2..cd149160fc 100644
--- a/apps/presentationeditor/mobile/src/controller/Toolbar.jsx
+++ b/apps/presentationeditor/mobile/src/controller/Toolbar.jsx
@@ -296,6 +296,7 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeFocusObjects'
changeTitleHandler={changeTitleHandler}
forceDesktopMode={forceDesktopMode}
isHiddenFileName={appOptions.config?.customization?.toolbarHideFileName ?? false}
+ isSaveBadgeShown={appOptions.isSaveBadgeShown}
/>
)
}));
diff --git a/apps/presentationeditor/mobile/src/controller/settings/Settings.jsx b/apps/presentationeditor/mobile/src/controller/settings/Settings.jsx
index f9b69b9f23..9ee7cb479f 100644
--- a/apps/presentationeditor/mobile/src/controller/settings/Settings.jsx
+++ b/apps/presentationeditor/mobile/src/controller/settings/Settings.jsx
@@ -4,6 +4,7 @@ import SettingsView from '../../view/settings/Settings';
import { f7 } from 'framework7-react';
import { observer, inject } from "mobx-react";
import { useTranslation } from 'react-i18next';
+import { LocalStorage } from "../../../../../common/mobile/utils/LocalStorage.mjs";
export const SettingsContext = createContext();
@@ -160,6 +161,17 @@ const SettingsController = props => {
}
}
+ const switchAutosave = (value) => {
+ const api = Common.EditorApi.get();
+ LocalStorage.setBool("pe-mobile-autosave", value);
+ api.asc_SetFastCollaborative(value);
+ api.asc_setAutoSaveGap(value ? 1 : 0);
+ };
+
+ const tryToSave = () => {
+ Common.EditorApi.get().asc_Save();
+ };
+
return (
{
showFeedback,
onDownloadOrigin,
closeModal,
- changeTitleHandler
+ changeTitleHandler,
+ switchAutosave,
+ tryToSave,
}}>
diff --git a/apps/presentationeditor/mobile/src/store/appOptions.js b/apps/presentationeditor/mobile/src/store/appOptions.js
index e77564c534..a64353fdff 100644
--- a/apps/presentationeditor/mobile/src/store/appOptions.js
+++ b/apps/presentationeditor/mobile/src/store/appOptions.js
@@ -20,6 +20,15 @@ export class storeAppOptions {
isDocReady: observable,
changeDocReady: action,
+ isAutosave: observable,
+ changeAutosave: action,
+
+ isSaveBadgeShown: observable,
+ changeIsSaveBadgeShown: action,
+
+ savingDocStatusText: observable,
+ changeSavingDocStatusText: action,
+
customization: observable,
});
}
@@ -46,6 +55,21 @@ export class storeAppOptions {
this.isDocReady = value;
}
+ isAutosave = true;
+ changeAutosave (value) {
+ this.isAutosave = value;
+ }
+
+ isSaveBadgeShown = false;
+ changeIsSaveBadgeShown (value) {
+ this.isSaveBadgeShown = value;
+ }
+
+ savingDocStatusText = '';
+ changeSavingDocStatusText (value) {
+ this.savingDocStatusText = value;
+ }
+
setConfigOptions (config, _t) {
this.config = config;
this.customization = config.customization;
diff --git a/apps/presentationeditor/mobile/src/view/Toolbar.jsx b/apps/presentationeditor/mobile/src/view/Toolbar.jsx
index aa259b3c6e..57e7563f4d 100644
--- a/apps/presentationeditor/mobile/src/view/Toolbar.jsx
+++ b/apps/presentationeditor/mobile/src/view/Toolbar.jsx
@@ -93,7 +93,7 @@ const ToolbarView = props => {
{Device.phone ? null : }
{props.displayCollaboration && window.matchMedia("(min-width: 375px)").matches && !isVersionHistoryMode ? props.openOptions('coauth')}> : null}
{isVersionHistoryMode ? props.openOptions('history')}> : null}
- props.openOptions('settings')}>
+ props.openOptions('settings')}>
{Device.ios ?
:
diff --git a/apps/presentationeditor/mobile/src/view/settings/SettingsPage.jsx b/apps/presentationeditor/mobile/src/view/settings/SettingsPage.jsx
index 0f44d173d3..baee931230 100644
--- a/apps/presentationeditor/mobile/src/view/settings/SettingsPage.jsx
+++ b/apps/presentationeditor/mobile/src/view/settings/SettingsPage.jsx
@@ -1,5 +1,5 @@
import React, { useContext } from 'react';
-import { Page, Navbar, NavRight, Link, Icon, ListItem, List, f7 } from 'framework7-react';
+import { Page, Navbar, NavRight, Link, Icon, ListItem, List, f7, Toggle } from 'framework7-react';
import { useTranslation } from 'react-i18next';
import { Device } from '../../../../../common/mobile/utils/device';
import { observer, inject } from "mobx-react";
@@ -36,9 +36,13 @@ const SettingsPage = inject('storeAppOptions', 'storeToolbarSettings', 'storePre
const closeButtonText = canCloseEditor && appOptions.customization.close.text;
const gobackTitle = appOptions.customization?.goback?.text || _t.textOpenLocation;
const isShowBack = props.storeToolbarSettings.isShowBack;
+ const isAutosave = appOptions.isAutosave;
const navbar =
- {docTitle}
+
+ {docTitle}
+ {appOptions.savingDocStatusText}
+
{Device.phone && {_t.textDone}}
;
@@ -83,84 +87,110 @@ const SettingsPage = inject('storeAppOptions', 'storeToolbarSettings', 'storePre
return (
{navbar}
-
- {isShowBack &&
- Common.Notifications.trigger('goback')}>
- {Device.ios ?
- :
-
- }
+ <>
+
+ {isShowBack &&
+ Common.Notifications.trigger('goback')}>
+ {Device.ios ?
+ :
+
+ }
+
+ }
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+ {
+ appOptions.changeAutosave(!isAutosave);
+ settingsContext.switchAutosave(!isAutosave);
+ }}
+ />
+
+ }
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+
+
+ {!props.inPopover &&
+
+
+
+ }
+ {window.matchMedia("(max-width: 374px)").matches ?
+ onOpenOptions('coauth')} className='no-indicator'>
+
+
+ : null}
+ {_isEdit &&
+
+
+
+ }
+
+
- }
- {!props.inPopover &&
-
-
-
- }
- {window.matchMedia("(max-width: 374px)").matches ?
- onOpenOptions('coauth')} className='no-indicator'>
-
-
- : null}
- {_isEdit &&
-
-
-
- }
-
-
-
- {_isEdit && canUseHistory &&
- {
- if(Device.phone) {
- onOpenOptions('history');
- }
- }}>
-
-
- }
- {_canDownload &&
-
-
-
- }
- {_canDownloadOrigin &&
-
-
-
- }
- {_canPrint &&
-
-
-
- }
- {!(!_canDisplayInfo && isBranding) &&
-
-
-
- }
- {_canHelp &&
-
-
-
- }
- {_canAbout &&
-
-
-
- }
- {_canFeedback &&
-
- {Device.ios ?
- :
-
- }
-
- }
- {canCloseEditor &&
- Common.Notifications.trigger('close')}>
- }
-
+ {_isEdit && canUseHistory &&
+ {
+ if(Device.phone) {
+ onOpenOptions('history');
+ }
+ }}>
+
+
+ }
+ {_canDownload &&
+
+
+
+ }
+ {_canDownloadOrigin &&
+
+
+
+ }
+ {_canPrint &&
+
+
+
+ }
+ {!(!_canDisplayInfo && isBranding) &&
+
+
+
+ }
+ {_canHelp &&
+
+
+
+ }
+ {_canAbout &&
+
+
+
+ }
+ {_canFeedback &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+ {canCloseEditor &&
+ Common.Notifications.trigger('close')}>
+ }
+
+ >
)
}));
diff --git a/apps/spreadsheeteditor/mobile/locale/en.json b/apps/spreadsheeteditor/mobile/locale/en.json
index a7ae15495e..5a5a543f44 100644
--- a/apps/spreadsheeteditor/mobile/locale/en.json
+++ b/apps/spreadsheeteditor/mobile/locale/en.json
@@ -426,7 +426,8 @@
"txtEditingMode": "Set editing mode...",
"uploadImageTextText": "Uploading image...",
"uploadImageTitleText": "Uploading Image",
- "waitText": "Please, wait..."
+ "waitText": "Please, wait...",
+ "changesSaved": "All changes saved"
},
"Statusbar": {
"notcriticalErrorTitle": "Warning",
@@ -792,6 +793,8 @@
"textFind": "Find",
"textFindAndReplace": "Find and Replace",
"textFindAndReplaceAll": "Find and Replace All",
+ "textSaveDocument": "Save",
+ "textAutoSaveDocument": "Autosave",
"textFormat": "Format",
"textFormulaLanguage": "Formula Language",
"textFormulas": "Formulas",
diff --git a/apps/spreadsheeteditor/mobile/src/controller/LongActions.jsx b/apps/spreadsheeteditor/mobile/src/controller/LongActions.jsx
index 9a0b19282a..883eba280d 100644
--- a/apps/spreadsheeteditor/mobile/src/controller/LongActions.jsx
+++ b/apps/spreadsheeteditor/mobile/src/controller/LongActions.jsx
@@ -93,7 +93,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
let action = {id: id, type: type};
stackLongActions.pop(action);
- //this.updateWindowTitle(true);
+ Common.Notifications.trigger('update:windowtitle', true);
action = stackLongActions.get({type: Asc.c_oAscAsyncActionType.Information}) || stackLongActions.get({type: Asc.c_oAscAsyncActionType.BlockInteraction});
@@ -104,6 +104,11 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
f7.dialog.close(loadMask.el) :
f7.dialog.close($$('.dialog-preloader'));
}
+
+ if ((id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton'])) {
+ storeAppOptions.changeSavingDocStatusText(_t.changesSaved);
+ storeAppOptions.isSaveBadgeShown && storeAppOptions.changeIsSaveBadgeShown(false);
+ }
};
const setLongActionView = (action) => {
@@ -119,6 +124,7 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
case Asc.c_oAscAsyncAction['Save']:
title = _t.saveTitleText;
// text = _t.saveTextText;
+ storeAppOptions.changeSavingDocStatusText(_t.saveTextText);
break;
case Asc.c_oAscAsyncAction['LoadDocumentFonts']:
@@ -214,7 +220,6 @@ const LongActionsController = inject('storeAppOptions')(({storeAppOptions}) => {
loadMask = showLoadMask(title, action.id === Asc.c_oAscAsyncAction['Open']);
}
}
-
};
const onConfirmAction = (id, apiCallback, data) => {
diff --git a/apps/spreadsheeteditor/mobile/src/controller/Main.jsx b/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
index 33617ab30e..78d19a066f 100644
--- a/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
+++ b/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
@@ -602,6 +602,8 @@ class MainController extends Component {
});
this.api.asc_registerCallback('asc_onNeedUpdateExternalReferenceOnOpen', this.onNeedUpdateExternalReference.bind(this));
+
+ Common.Notifications.on('update:windowtitle', force => this.updateWindowTitle(force));
}
insertImageFromStorage (data) {
@@ -764,6 +766,8 @@ class MainController extends Component {
appSettings.changeRefStyle(value);
this.api.asc_setR1C1Mode(value);
+ appOptions.changeAutosave(LocalStorage.itemExists('sse-mobile-autosave') ? LocalStorage.getBool("sse-mobile-autosave") : true);
+
Common.Gateway.documentReady();
f7.emit('resize');
@@ -813,6 +817,7 @@ class MainController extends Component {
this.api.asc_registerCallback('asc_onDocumentModifiedChanged', this.onDocumentModifiedChanged.bind(this));
this.api.asc_registerCallback('asc_onDocumentCanSaveChanged', this.onDocumentCanSaveChanged.bind(this));
+ this.api.asc_registerCallback('asc_onCollaborativeChanges', this.onCollaborativeChanges.bind(this));
Common.Notifications.trigger('preloader:close');
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.ApplyEditRights);
@@ -1189,6 +1194,9 @@ class MainController extends Component {
window.document.title = title;
}
+ if (isModified)
+ this.props.storeAppOptions.changeSavingDocStatusText('');
+
this._isDocReady && (this._state.isDocModified !== isModified) && Common.Gateway.setDocumentModified(isModified);
this._state.isDocModified = isModified;
}
@@ -1204,7 +1212,14 @@ class MainController extends Component {
}
onDocumentCanSaveChanged (isCanSave) {
- //
+ const storeAppOptions = this.props.storeAppOptions;
+ storeAppOptions.changeIsSaveBadgeShown(isCanSave);
+ }
+
+ onCollaborativeChanges () {
+ const storeAppOptions = this.props.storeAppOptions;
+ if (!storeAppOptions.isSaveBadgeShown) storeAppOptions.changeIsSaveBadgeShown(true);
+ storeAppOptions.changeSavingDocStatusText('');
}
onPrint () {
diff --git a/apps/spreadsheeteditor/mobile/src/controller/Toolbar.jsx b/apps/spreadsheeteditor/mobile/src/controller/Toolbar.jsx
index d41c59c8d8..0b5bf9f818 100644
--- a/apps/spreadsheeteditor/mobile/src/controller/Toolbar.jsx
+++ b/apps/spreadsheeteditor/mobile/src/controller/Toolbar.jsx
@@ -317,6 +317,7 @@ const ToolbarController = inject('storeAppOptions', 'users', 'storeSpreadsheetIn
changeTitleHandler={changeTitleHandler}
forceDesktopMode={forceDesktopMode}
isHiddenFileName={appOptions.config?.customization?.toolbarHideFileName ?? false}
+ isSaveBadgeShown={appOptions.isSaveBadgeShown}
/>
)
}));
diff --git a/apps/spreadsheeteditor/mobile/src/controller/settings/Settings.jsx b/apps/spreadsheeteditor/mobile/src/controller/settings/Settings.jsx
index dc28c8c03b..d5fb8d7748 100644
--- a/apps/spreadsheeteditor/mobile/src/controller/settings/Settings.jsx
+++ b/apps/spreadsheeteditor/mobile/src/controller/settings/Settings.jsx
@@ -4,6 +4,7 @@ import { Device } from '../../../../../common/mobile/utils/device';
import SettingsView from "../../view/settings/Settings";
import { f7 } from 'framework7-react';
import { useTranslation } from 'react-i18next';
+import { LocalStorage } from "../../../../../common/mobile/utils/LocalStorage.mjs";
export const SettingsContext = createContext();
@@ -177,6 +178,17 @@ const SettingsController = inject('storeAppOptions', 'storeSpreadsheetInfo')(obs
}
}
+ const switchAutosave = (value) => {
+ const api = Common.EditorApi.get();
+ LocalStorage.setBool("sse-mobile-autosave", value);
+ api.asc_SetFastCollaborative(value);
+ api.asc_setAutoSaveGap(value ? 1 : 0);
+ };
+
+ const tryToSave = () => {
+ Common.EditorApi.get().asc_Save();
+ };
+
return (
diff --git a/apps/spreadsheeteditor/mobile/src/store/appOptions.js b/apps/spreadsheeteditor/mobile/src/store/appOptions.js
index 497d8ff286..6adee182c7 100644
--- a/apps/spreadsheeteditor/mobile/src/store/appOptions.js
+++ b/apps/spreadsheeteditor/mobile/src/store/appOptions.js
@@ -21,6 +21,15 @@ export class storeAppOptions {
isDocReady: observable,
changeDocReady: action,
+ isAutosave: observable,
+ changeAutosave: action,
+
+ isSaveBadgeShown: observable,
+ changeIsSaveBadgeShown: action,
+
+ savingDocStatusText: observable,
+ changeSavingDocStatusText: action,
+
customization: observable,
});
}
@@ -52,6 +61,21 @@ export class storeAppOptions {
this.isDocReady = value;
}
+ isAutosave = true;
+ changeAutosave (value) {
+ this.isAutosave = value;
+ }
+
+ isSaveBadgeShown = false;
+ changeIsSaveBadgeShown (value) {
+ this.isSaveBadgeShown = value;
+ }
+
+ savingDocStatusText = '';
+ changeSavingDocStatusText (value) {
+ this.savingDocStatusText = value;
+ }
+
setConfigOptions (config, _t) {
this.config = config;
this.customization = config.customization;
diff --git a/apps/spreadsheeteditor/mobile/src/view/Toolbar.jsx b/apps/spreadsheeteditor/mobile/src/view/Toolbar.jsx
index f1b063ea9e..4e7b6df372 100644
--- a/apps/spreadsheeteditor/mobile/src/view/Toolbar.jsx
+++ b/apps/spreadsheeteditor/mobile/src/view/Toolbar.jsx
@@ -84,7 +84,7 @@ const ToolbarView = props => {
{Device.phone ? null : }
{!props.isDrawMode && props.displayCollaboration && window.matchMedia("(min-width: 360px)").matches && !isVersionHistoryMode ? props.openOptions('coauth')}> : null}
{isVersionHistoryMode ? props.openOptions('history')}> : null}
- props.openOptions('settings')}> {Device.ios ?
+ props.openOptions('settings')}> {Device.ios ?
:
}
diff --git a/apps/spreadsheeteditor/mobile/src/view/settings/SettingsPage.jsx b/apps/spreadsheeteditor/mobile/src/view/settings/SettingsPage.jsx
index 893243219a..a34b3c46f1 100644
--- a/apps/spreadsheeteditor/mobile/src/view/settings/SettingsPage.jsx
+++ b/apps/spreadsheeteditor/mobile/src/view/settings/SettingsPage.jsx
@@ -1,5 +1,5 @@
import React, { useContext } from 'react';
-import { Page, Navbar, NavRight, Link, Icon, ListItem, List, f7 } from 'framework7-react';
+import { Page, Navbar, NavRight, Link, Icon, ListItem, List, f7, Toggle } from 'framework7-react';
import { useTranslation } from 'react-i18next';
import { Device } from '../../../../../common/mobile/utils/device';
import { observer, inject } from "mobx-react";
@@ -34,9 +34,13 @@ const SettingsPage = inject('storeAppOptions', 'storeSpreadsheetInfo', 'storeToo
const closeButtonText = canCloseEditor && appOptions.customization.close.text;
const gobackTitle = appOptions.customization?.goback?.text || _t.textOpenLocation;
const isShowBack = props.storeToolbarSettings.isShowBack;
+ const isAutosave = appOptions.isAutosave;
const navbar =
- {docTitle}
+
+ {docTitle}
+ {appOptions.savingDocStatusText}
+
{Device.phone &&
{_t.textDone}
}
@@ -83,84 +87,110 @@ const SettingsPage = inject('storeAppOptions', 'storeSpreadsheetInfo', 'storeToo
return (
{navbar}
-
- {isShowBack &&
- Common.Notifications.trigger('goback')}>
- {Device.ios ?
- :
-
- }
+ <>
+
+ {isShowBack &&
+ Common.Notifications.trigger('goback')}>
+ {Device.ios ?
+ :
+
+ }
+
+ }
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+ {
+ appOptions.changeAutosave(!isAutosave);
+ settingsContext.switchAutosave(!isAutosave);
+ }}
+ />
+
+ }
+ {!appOptions.canLiveView &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+
+
+ {!props.inPopover &&
+
+
+
+ }
+ {window.matchMedia("(max-width: 359px)").matches ?
+ onOpenOptions('coauth')} className='no-indicator'>
+
+
+ : null}
+ {_isEdit &&
+
+
+
+ }
+
+
- }
- {!props.inPopover &&
-
-
-
- }
- {window.matchMedia("(max-width: 359px)").matches ?
- onOpenOptions('coauth')} className='no-indicator'>
-
-
- : null}
- {_isEdit &&
-
-
-
- }
-
-
-
- {_isEdit && canUseHistory &&
- {
- if(Device.phone) {
- onOpenOptions('history');
- }
- }}>
-
-
- }
- {_canDownload &&
-
-
-
- }
- {_canDownloadOrigin &&
-
-
-
- }
- {_canPrint &&
-
-
-
- }
- {!(!_canDisplayInfo && isBranding) &&
-
-
-
- }
- {_canHelp &&
-
-
-
- }
- {_canAbout &&
-
-
-
- }
- {_canFeedback &&
-
- {Device.ios ?
- :
-
- }
-
- }
- {canCloseEditor &&
- Common.Notifications.trigger('close')}>
- }
-
+ {_isEdit && canUseHistory &&
+ {
+ if(Device.phone) {
+ onOpenOptions('history');
+ }
+ }}>
+
+
+ }
+ {_canDownload &&
+
+
+
+ }
+ {_canDownloadOrigin &&
+
+
+
+ }
+ {_canPrint &&
+
+
+
+ }
+ {!(!_canDisplayInfo && isBranding) &&
+
+
+
+ }
+ {_canHelp &&
+
+
+
+ }
+ {_canAbout &&
+
+
+
+ }
+ {_canFeedback &&
+
+ {Device.ios ?
+ :
+
+ }
+
+ }
+ {canCloseEditor &&
+ Common.Notifications.trigger('close')}>
+ }
+
+ >
)
}));