Merge pull request #1715 from ONLYOFFICE/feature/mobile-live-view
Feature/mobile live view
This commit is contained in:
commit
34574c079b
|
@ -46,6 +46,11 @@ class CollaborationController extends Component {
|
|||
api.asc_SetFastCollaborative(isFastCoauth);
|
||||
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);
|
||||
window.editorType === 'de' && api.SetCollaborativeMarksShowType(Asc.c_oAscCollaborativeMarksShowType.None);
|
||||
api.asc_setAutoSaveGap(1);
|
||||
} else {
|
||||
isFastCoauth = false;
|
||||
api.asc_SetFastCollaborative(isFastCoauth);
|
||||
|
|
|
@ -80,8 +80,8 @@ class MainController extends Component {
|
|||
};
|
||||
|
||||
const loadConfig = data => {
|
||||
const _t = this._t;
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
EditorUIController.isSupportEditFeature();
|
||||
|
||||
this.editorConfig = Object.assign({}, this.editorConfig, data.config);
|
||||
|
@ -133,18 +133,18 @@ class MainController extends Component {
|
|||
docInfo.put_Lang(this.editorConfig.lang);
|
||||
docInfo.put_Mode(this.editorConfig.mode);
|
||||
|
||||
// var coEditMode = !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
// this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
// this.editorConfig.coEditing.mode || 'fast';
|
||||
// docInfo.put_CoEditingMode(coEditMode);
|
||||
docInfo.put_CoEditingMode('strict'); // need to change!!!
|
||||
let type = /^(?:(pdf|djvu|xps|oxps))$/.exec(data.doc.fileType);
|
||||
let coEditMode = (type && typeof type[1] === 'string') ? 'strict' : // offline viewer for pdf|djvu|xps|oxps
|
||||
!(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
this.editorConfig.coEditing.mode || 'fast';
|
||||
docInfo.put_CoEditingMode(coEditMode);
|
||||
|
||||
let enable = !this.editorConfig.customization || (this.editorConfig.customization.macros !== false);
|
||||
docInfo.asc_putIsEnabledMacroses(!!enable);
|
||||
enable = !this.editorConfig.customization || (this.editorConfig.customization.plugins !== false);
|
||||
docInfo.asc_putIsEnabledPlugins(!!enable);
|
||||
|
||||
let type = /^(?:(pdf|djvu|xps|oxps))$/.exec(data.doc.fileType);
|
||||
if (type && typeof type[1] === 'string') {
|
||||
this.permissions.edit = this.permissions.review = false;
|
||||
}
|
||||
|
@ -183,13 +183,15 @@ class MainController extends Component {
|
|||
const onEditorPermissions = params => {
|
||||
const licType = params.asc_getLicenseType();
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
// 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
|
||||
title : _t.titleLicenseExp,
|
||||
text : _t.warnLicenseExp
|
||||
}).open();
|
||||
return;
|
||||
}
|
||||
|
@ -409,7 +411,9 @@ class MainController extends Component {
|
|||
this.api.asc_continueSaving();
|
||||
}, 500);
|
||||
|
||||
return this._t.leavePageText;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
return _t.leavePageText;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,6 +430,10 @@ class MainController extends Component {
|
|||
(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 (licType !== undefined && appOptions.canLiveView && (licType===Asc.c_oLicenseResult.ConnectionsLive || licType===Asc.c_oLicenseResult.ConnectionsLiveOS))
|
||||
this._state.licenseType = licType;
|
||||
|
||||
if (this._isDocReady && this._state.licenseType)
|
||||
this.applyLicense();
|
||||
}
|
||||
|
@ -457,7 +465,13 @@ class MainController extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._state.licenseType) {
|
||||
if (appOptions.config.mode === 'view') {
|
||||
if (appOptions.canLiveView && (this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLive || this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLiveOS)) {
|
||||
appOptions.canLiveView = false;
|
||||
this.api.asc_SetFastCollaborative(false);
|
||||
}
|
||||
Common.Notifications.trigger('toolbar:activatecontrols');
|
||||
} else if (this._state.licenseType) {
|
||||
let license = this._state.licenseType;
|
||||
let buttons = [{text: 'OK'}];
|
||||
if ((appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0 &&
|
||||
|
@ -526,7 +540,8 @@ class MainController extends Component {
|
|||
|
||||
onServerVersion (buildVersion) {
|
||||
if (this.changeServerVersion) return true;
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
|
||||
if (About.appVersion() !== buildVersion && !About.compareVersions()) {
|
||||
this.changeServerVersion = true;
|
||||
|
@ -797,7 +812,9 @@ class MainController extends Component {
|
|||
this.api.asc_OnSaveEnd(data.result);
|
||||
|
||||
if (data && data.result === false) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.errorProcessSaveResult : data.message,
|
||||
_t.criticalErrorTitle
|
||||
|
@ -814,7 +831,9 @@ class MainController extends Component {
|
|||
Common.Notifications.trigger('api:disconnect');
|
||||
|
||||
if (!old_rights) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.warnProcessRightsChange : data.message,
|
||||
_t.notcriticalErrorTitle,
|
||||
|
@ -827,7 +846,9 @@ class MainController extends Component {
|
|||
onDownloadAs () {
|
||||
const appOptions = this.props.storeAppOptions;
|
||||
if ( !appOptions.canDownload && !appOptions.canDownloadOrigin) {
|
||||
Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, this._t.errorAccessDeny);
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, _t.errorAccessDeny);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -854,7 +875,8 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
onUpdateVersion (callback) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
|
||||
this.needToUpdateVersion = true;
|
||||
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.LoadingDocument);
|
||||
|
@ -946,7 +968,8 @@ class MainController extends Component {
|
|||
if (value === 1) {
|
||||
this.api.asc_runAutostartMacroses();
|
||||
} else if (value === 0) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Main', {returnObjects:true});
|
||||
f7.dialog.create({
|
||||
title: _t.notcriticalErrorTitle,
|
||||
text: _t.textHasMacros,
|
||||
|
|
|
@ -145,6 +145,8 @@ export class storeAppOptions {
|
|||
this.canUseReviewPermissions && AscCommon.UserInfoParser.setReviewPermissions(permissions.reviewGroups, this.customization.reviewPermissions);
|
||||
this.canUseCommentPermissions && AscCommon.UserInfoParser.setCommentPermissions(permissions.commentGroups);
|
||||
this.canUseUserInfoPermissions && AscCommon.UserInfoParser.setUserInfoPermissions(permissions.userInfoGroups);
|
||||
|
||||
this.canLiveView = !!params.asc_getLiveViewerSupport() && (this.config.mode === 'view') && !(type && typeof type[1] === 'string') && isSupportEditFeature;
|
||||
}
|
||||
setCanViewReview (value) {
|
||||
this.canViewReview = value;
|
||||
|
|
|
@ -73,7 +73,8 @@ class MainController extends Component {
|
|||
};
|
||||
|
||||
const loadConfig = data => {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
EditorUIController.isSupportEditFeature();
|
||||
|
||||
|
@ -124,11 +125,10 @@ class MainController extends Component {
|
|||
docInfo.put_Lang(this.editorConfig.lang);
|
||||
docInfo.put_Mode(this.editorConfig.mode);
|
||||
|
||||
// var coEditMode = !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
// this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
// this.editorConfig.coEditing.mode || 'fast';
|
||||
// docInfo.put_CoEditingMode(coEditMode);
|
||||
docInfo.put_CoEditingMode('strict'); // need to change!!!
|
||||
let coEditMode = !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
this.editorConfig.coEditing.mode || 'fast';
|
||||
docInfo.put_CoEditingMode(coEditMode);
|
||||
|
||||
let enable = !this.editorConfig.customization || (this.editorConfig.customization.macros !== false);
|
||||
docInfo.asc_putIsEnabledMacroses(!!enable);
|
||||
|
@ -290,7 +290,9 @@ class MainController extends Component {
|
|||
this.api.asc_continueSaving();
|
||||
}, 500);
|
||||
|
||||
return this._t.leavePageText;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
return _t.leavePageText;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,6 +501,10 @@ class MainController extends Component {
|
|||
(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 (licType !== undefined && appOptions.canLiveView && (licType===Asc.c_oLicenseResult.ConnectionsLive || licType===Asc.c_oLicenseResult.ConnectionsLiveOS))
|
||||
this._state.licenseType = licType;
|
||||
|
||||
if (this._isDocReady && this._state.licenseType)
|
||||
this.applyLicense();
|
||||
}
|
||||
|
@ -530,7 +536,13 @@ class MainController extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._state.licenseType) {
|
||||
if (appOptions.config.mode === 'view') {
|
||||
if (appOptions.canLiveView && (this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLive || this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLiveOS)) {
|
||||
appOptions.canLiveView = false;
|
||||
this.api.asc_SetFastCollaborative(false);
|
||||
}
|
||||
Common.Notifications.trigger('toolbar:activatecontrols');
|
||||
} else if (this._state.licenseType) {
|
||||
let license = this._state.licenseType;
|
||||
let buttons = [{text: 'OK'}];
|
||||
if ((appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0 &&
|
||||
|
@ -598,7 +610,8 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
onUpdateVersion (callback) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
this.needToUpdateVersion = true;
|
||||
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.LoadingDocument);
|
||||
|
@ -617,7 +630,8 @@ class MainController extends Component {
|
|||
|
||||
onServerVersion (buildVersion) {
|
||||
if (this.changeServerVersion) return true;
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
if (About.appVersion() !== buildVersion && !window.compareVersions) {
|
||||
this.changeServerVersion = true;
|
||||
|
@ -765,7 +779,8 @@ class MainController extends Component {
|
|||
if (value === 1) {
|
||||
this.api.asc_runAutostartMacroses();
|
||||
} else if (value === 0) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.create({
|
||||
title: _t.notcriticalErrorTitle,
|
||||
text: _t.textHasMacros,
|
||||
|
@ -807,7 +822,8 @@ class MainController extends Component {
|
|||
this.api.asc_OnSaveEnd(data.result);
|
||||
|
||||
if (data && data.result === false) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.errorProcessSaveResult : data.message,
|
||||
_t.criticalErrorTitle
|
||||
|
@ -824,7 +840,8 @@ class MainController extends Component {
|
|||
Common.Notifications.trigger('api:disconnect');
|
||||
|
||||
if (!old_rights) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.warnProcessRightsChange : data.message,
|
||||
_t.notcriticalErrorTitle,
|
||||
|
|
|
@ -116,5 +116,7 @@ export class storeAppOptions {
|
|||
this.canUseReviewPermissions && AscCommon.UserInfoParser.setReviewPermissions(permissions.reviewGroups, this.customization.reviewPermissions);
|
||||
this.canUseCommentPermissions && AscCommon.UserInfoParser.setCommentPermissions(permissions.commentGroups);
|
||||
this.canUseUserInfoPermissions && AscCommon.UserInfoParser.setUserInfoPermissions(permissions.userInfoGroups);
|
||||
|
||||
this.canLiveView = !!params.asc_getLiveViewerSupport() && (this.config.mode === 'view') && isSupportEditFeature;
|
||||
}
|
||||
}
|
|
@ -91,7 +91,8 @@ class MainController extends Component {
|
|||
};
|
||||
|
||||
const loadConfig = data => {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
EditorUIController.isSupportEditFeature();
|
||||
|
||||
|
@ -171,11 +172,10 @@ class MainController extends Component {
|
|||
docInfo.put_Lang(this.editorConfig.lang);
|
||||
docInfo.put_Mode(this.editorConfig.mode);
|
||||
|
||||
// var coEditMode = !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
// this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
// this.editorConfig.coEditing.mode || 'fast';
|
||||
// docInfo.put_CoEditingMode(coEditMode);
|
||||
docInfo.put_CoEditingMode('strict'); // need to change!!!
|
||||
let coEditMode = !(this.editorConfig.coEditing && typeof this.editorConfig.coEditing == 'object') ? 'fast' : // fast by default
|
||||
this.editorConfig.mode === 'view' && this.editorConfig.coEditing.change!==false ? 'fast' : // if can change mode in viewer - set fast for using live viewer
|
||||
this.editorConfig.coEditing.mode || 'fast';
|
||||
docInfo.put_CoEditingMode(coEditMode);
|
||||
|
||||
const appOptions = this.props.storeAppOptions;
|
||||
let enable = !appOptions.customization || (appOptions.customization.macros !== false);
|
||||
|
@ -622,6 +622,9 @@ class MainController extends Component {
|
|||
|| licType === Asc.c_oLicenseResult.SuccessLimit && (appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0))
|
||||
this._state.licenseType = licType;
|
||||
|
||||
if (licType !== undefined && appOptions.canLiveView && (licType===Asc.c_oLicenseResult.ConnectionsLive || licType===Asc.c_oLicenseResult.ConnectionsLiveOS))
|
||||
this._state.licenseType = licType;
|
||||
|
||||
if (this._isDocReady && this._state.licenseType)
|
||||
this.applyLicense();
|
||||
}
|
||||
|
@ -653,7 +656,13 @@ class MainController extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._state.licenseType) {
|
||||
if (appOptions.config.mode === 'view') {
|
||||
if (appOptions.canLiveView && (this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLive || this._state.licenseType===Asc.c_oLicenseResult.ConnectionsLiveOS)) {
|
||||
appOptions.canLiveView = false;
|
||||
this.api.asc_SetFastCollaborative(false);
|
||||
}
|
||||
Common.Notifications.trigger('toolbar:activatecontrols');
|
||||
} else if (this._state.licenseType) {
|
||||
let license = this._state.licenseType;
|
||||
let buttons = [{text: 'OK'}];
|
||||
if ((appOptions.trialMode & Asc.c_oLicenseMode.Limited) !== 0 &&
|
||||
|
@ -741,7 +750,8 @@ class MainController extends Component {
|
|||
if (value === 1) {
|
||||
this.api.asc_runAutostartMacroses();
|
||||
} else if (value === 0) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.create({
|
||||
title: _t.notcriticalErrorTitle,
|
||||
text: _t.textHasMacros,
|
||||
|
@ -788,7 +798,8 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
onBeforeUnload () {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
LocalStorage.save();
|
||||
|
||||
|
@ -810,7 +821,8 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
onUpdateVersion (callback) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
this.needToUpdateVersion = true;
|
||||
Common.Notifications.trigger('preloader:endAction', Asc.c_oAscAsyncActionType['BlockInteraction'], this.LoadingDocument);
|
||||
|
@ -829,7 +841,8 @@ class MainController extends Component {
|
|||
|
||||
onServerVersion (buildVersion) {
|
||||
if (this.changeServerVersion) return true;
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
|
||||
if (About.appVersion() !== buildVersion && !About.compareVersions()) {
|
||||
this.changeServerVersion = true;
|
||||
|
@ -915,7 +928,8 @@ class MainController extends Component {
|
|||
this.api.asc_OnSaveEnd(data.result);
|
||||
|
||||
if (data && data.result === false) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.errorProcessSaveResult : data.message,
|
||||
_t.criticalErrorTitle
|
||||
|
@ -932,7 +946,8 @@ class MainController extends Component {
|
|||
Common.Notifications.trigger('api:disconnect');
|
||||
|
||||
if (!old_rights) {
|
||||
const _t = this._t;
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
f7.dialog.alert(
|
||||
(!data.message) ? _t.warnProcessRightsChange : data.message,
|
||||
_t.notcriticalErrorTitle,
|
||||
|
@ -944,7 +959,9 @@ class MainController extends Component {
|
|||
|
||||
onDownloadAs () {
|
||||
if ( this.props.storeAppOptions.canDownload) {
|
||||
Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, this._t.errorAccessDeny);
|
||||
const { t } = this.props;
|
||||
const _t = t('Controller.Main', {returnObjects:true});
|
||||
Common.Gateway.reportError(Asc.c_oAscError.ID.AccessDeny, _t.errorAccessDeny);
|
||||
return;
|
||||
}
|
||||
this._state.isFromGatewayDownloadAs = true;
|
||||
|
|
|
@ -111,5 +111,7 @@ export class storeAppOptions {
|
|||
this.canUseReviewPermissions && AscCommon.UserInfoParser.setReviewPermissions(permissions.reviewGroups, this.customization.reviewPermissions);
|
||||
this.canUseCommentPermissions && AscCommon.UserInfoParser.setCommentPermissions(permissions.commentGroups);
|
||||
this.canUseUserInfoPermissions && AscCommon.UserInfoParser.setUserInfoPermissions(permissions.userInfoGroups);
|
||||
|
||||
this.canLiveView = !!params.asc_getLiveViewerSupport() && (this.config.mode === 'view') && isSupportEditFeature;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue