[PE mobile] Changes for private branch
This commit is contained in:
parent
c49fc13b80
commit
fe1a9e16d3
|
@ -7,6 +7,7 @@ import { LocalStorage } from '../../../../common/mobile/utils/LocalStorage';
|
|||
import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu';
|
||||
import { idContextMenuElement } from '../../../../common/mobile/lib/view/ContextMenu';
|
||||
import { Device } from '../../../../common/mobile/utils/device';
|
||||
import EditorUIController from '../lib/patch';
|
||||
|
||||
@inject ( stores => ({
|
||||
isEdit: stores.storeAppOptions.isEdit,
|
||||
|
@ -57,10 +58,13 @@ class ContextMenu extends ContextMenuController {
|
|||
onMenuItemClick(action) {
|
||||
super.onMenuItemClick(action);
|
||||
|
||||
if ( EditorUIController.ContextMenu.handleMenuItemClick(this, action) )
|
||||
return;
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
switch (action) {
|
||||
case 'cut':
|
||||
if (!api.Cut() && !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
if ( !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
|
@ -70,29 +74,13 @@ class ContextMenu extends ContextMenuController {
|
|||
}
|
||||
break;
|
||||
case 'paste':
|
||||
if (!api.Paste() && !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
if ( !LocalStorage.getBool("pe-hide-copy-cut-paste-warning")) {
|
||||
this.showCopyCutPasteModal();
|
||||
}
|
||||
break;
|
||||
case 'addcomment':
|
||||
Common.Notifications.trigger('addcomment');
|
||||
break;
|
||||
case 'viewcomment':
|
||||
Common.Notifications.trigger('viewcomment');
|
||||
break;
|
||||
case 'delete':
|
||||
api.asc_Remove();
|
||||
break;
|
||||
case 'edit':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('edit');
|
||||
}, 0);
|
||||
break;
|
||||
case 'addlink':
|
||||
setTimeout(() => {
|
||||
this.props.openOptions('add', 'link');
|
||||
}, 400)
|
||||
break;
|
||||
case 'openlink':
|
||||
const stack = Common.EditorApi.get().getSelectedElements();
|
||||
let value;
|
||||
|
@ -104,8 +92,6 @@ class ContextMenu extends ContextMenuController {
|
|||
value && this.openLink(value);
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("click context menu item: " + action);
|
||||
}
|
||||
|
||||
showCopyCutPasteModal() {
|
||||
|
@ -154,152 +140,77 @@ class ContextMenu extends ContextMenuController {
|
|||
initMenuItems() {
|
||||
if ( !Common.EditorApi ) return [];
|
||||
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
const { isEdit } = this.props;
|
||||
|
||||
const { isEdit, canViewComments, isDisconnected } = this.props;
|
||||
if (isEdit) {
|
||||
return EditorUIController.ContextMenu.mapMenuItems(this);
|
||||
} else {
|
||||
const { t } = this.props;
|
||||
const _t = t("ContextMenu", { returnObjects: true });
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
const stack = api.getSelectedElements();
|
||||
const canCopy = api.can_CopyCut();
|
||||
const { canViewComments, isDisconnected } = this.props;
|
||||
|
||||
let itemsIcon = [],
|
||||
itemsText = [];
|
||||
const api = Common.EditorApi.get();
|
||||
const stack = api.getSelectedElements();
|
||||
const canCopy = api.can_CopyCut();
|
||||
|
||||
let isText = false,
|
||||
isTable = false,
|
||||
isImage = false,
|
||||
isChart = false,
|
||||
isShape = false,
|
||||
isLink = false,
|
||||
isSlide = false,
|
||||
isObject = false;
|
||||
let itemsIcon = [],
|
||||
itemsText = [];
|
||||
|
||||
stack.forEach(item => {
|
||||
const objectType = item.get_ObjectType(),
|
||||
objectValue = item.get_ObjectValue();
|
||||
let isText = false,
|
||||
isTable = false,
|
||||
isImage = false,
|
||||
isChart = false,
|
||||
isShape = false,
|
||||
isLink = false,
|
||||
isSlide = false,
|
||||
isObject = false;
|
||||
|
||||
if (objectType == Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||
isText = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Image) {
|
||||
isImage = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Chart) {
|
||||
isChart = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Shape) {
|
||||
isShape = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Table) {
|
||||
isTable = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
isLink = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Slide) {
|
||||
isSlide = true;
|
||||
}
|
||||
});
|
||||
stack.forEach(item => {
|
||||
const objectType = item.get_ObjectType(),
|
||||
objectValue = item.get_ObjectValue();
|
||||
|
||||
isObject = isText || isImage || isChart || isShape || isTable;
|
||||
|
||||
if (canCopy && isObject) {
|
||||
itemsIcon.push({
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
}
|
||||
if (canViewComments && this.isComments && !isEdit) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
|
||||
if ( stack.length > 0 ) {
|
||||
let topObject = stack[stack.length - 1],
|
||||
topObjectType = topObject.get_ObjectType(),
|
||||
topObjectValue = topObject.get_ObjectValue(),
|
||||
objectLocked = typeof topObjectValue.get_Locked === 'function' ? topObjectValue.get_Locked() : false;
|
||||
|
||||
!objectLocked && (objectLocked = typeof topObjectValue.get_LockDelete === 'function' ? topObjectValue.get_LockDelete() : false);
|
||||
|
||||
const swapItems = function(items, indexBefore, indexAfter) {
|
||||
items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0];
|
||||
};
|
||||
|
||||
if (!objectLocked && isEdit && !isDisconnected) {
|
||||
if (canCopy && isObject) {
|
||||
itemsIcon.push({
|
||||
event: 'cut',
|
||||
icon: 'icon-cut'
|
||||
});
|
||||
|
||||
// Swap 'Copy' and 'Cut'
|
||||
swapItems(itemsIcon, 0, 1);
|
||||
if (objectType == Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||
isText = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Image) {
|
||||
isImage = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Chart) {
|
||||
isChart = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Shape) {
|
||||
isShape = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Table) {
|
||||
isTable = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
isLink = true;
|
||||
} else if (objectType == Asc.c_oAscTypeSelectElement.Slide) {
|
||||
isSlide = true;
|
||||
}
|
||||
});
|
||||
|
||||
isObject = isText || isImage || isChart || isShape || isTable;
|
||||
|
||||
if (canCopy && isObject) {
|
||||
itemsIcon.push({
|
||||
event: 'paste',
|
||||
icon: 'icon-paste'
|
||||
event: 'copy',
|
||||
icon: 'icon-copy'
|
||||
});
|
||||
|
||||
if (isObject)
|
||||
itemsText.push({
|
||||
caption: _t.menuDelete,
|
||||
event: 'delete'
|
||||
});
|
||||
|
||||
itemsText.push({
|
||||
caption: _t.menuEdit,
|
||||
event: 'edit'
|
||||
});
|
||||
|
||||
if (!isLink && api.can_AddHyperlink() !== false) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddLink,
|
||||
event: 'addlink'
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isComments && canViewComments) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
|
||||
const hideAddComment = (isText && isChart) || api.can_AddQuotedComment() === false || !canViewComments;
|
||||
if (!hideAddComment) {
|
||||
itemsText.push({
|
||||
caption: _t.menuAddComment,
|
||||
event: 'addcomment'
|
||||
});
|
||||
}
|
||||
}
|
||||
if (canViewComments && this.isComments && !isEdit) {
|
||||
itemsText.push({
|
||||
caption: _t.menuViewComment,
|
||||
event: 'viewcomment'
|
||||
});
|
||||
}
|
||||
|
||||
if (isLink) {
|
||||
itemsText.push({
|
||||
caption: _t.menuOpenLink,
|
||||
event: 'openlink'
|
||||
});
|
||||
}
|
||||
|
||||
return itemsIcon.concat(itemsText);
|
||||
}
|
||||
|
||||
if (isLink) {
|
||||
itemsText.push({
|
||||
caption: _t.menuOpenLink,
|
||||
event: 'openlink'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if ( Device.phone && itemsText.length > 2 ) {
|
||||
this.extraItems = itemsText.splice(2,itemsText.length, {
|
||||
caption: _t.menuMore,
|
||||
event: 'showActionSheet'
|
||||
});
|
||||
}
|
||||
|
||||
return itemsIcon.concat(itemsText);
|
||||
// return [{
|
||||
// caption: 'Edit',
|
||||
// event: 'edit'
|
||||
// }, {
|
||||
// caption: 'View',
|
||||
// event: 'view'
|
||||
// }, {
|
||||
// icon: 'icon-paste',
|
||||
// event: 'review'
|
||||
// }];
|
||||
}
|
||||
|
||||
initExtraItems () {
|
||||
|
|
|
@ -144,6 +144,8 @@ class MainController extends Component {
|
|||
'translate': t('Controller.Main.SDK', {returnObjects:true})
|
||||
});
|
||||
|
||||
Common.EditorApi = {get: () => this.api};
|
||||
|
||||
this.appOptions = {};
|
||||
this.bindEvents();
|
||||
|
||||
|
@ -160,7 +162,6 @@ class MainController extends Component {
|
|||
Common.Gateway.appReady();
|
||||
|
||||
Common.Notifications.trigger('engineCreated', this.api);
|
||||
Common.EditorApi = {get: () => this.api};
|
||||
}, error => {
|
||||
console.log('promise failed ' + error);
|
||||
});
|
||||
|
@ -174,89 +175,30 @@ class MainController extends Component {
|
|||
}
|
||||
|
||||
bindEvents() {
|
||||
const me = this;
|
||||
|
||||
// me.api.asc_registerCallback('asc_onError', _.bind(me.onError, me));
|
||||
me.api.asc_registerCallback('asc_onDocumentContentReady', me._onDocumentContentReady.bind(me));
|
||||
me.api.asc_registerCallback('asc_onOpenDocumentProgress', me._onOpenDocumentProgress.bind(me));
|
||||
this.api.asc_registerCallback('asc_onDocumentContentReady', this._onDocumentContentReady.bind(this));
|
||||
this.api.asc_registerCallback('asc_onOpenDocumentProgress', this._onOpenDocumentProgress.bind(this));
|
||||
|
||||
const storePresentationSettings = this.props.storePresentationSettings;
|
||||
|
||||
me.api.asc_registerCallback('asc_onPresentationSize', (width, height) => {
|
||||
this.api.asc_registerCallback('asc_onPresentationSize', (width, height) => {
|
||||
storePresentationSettings.changeSizeIndex(width, height);
|
||||
});
|
||||
|
||||
me.api.asc_registerCallback('asc_onSendThemeColorSchemes', (arr) => {
|
||||
this.api.asc_registerCallback('asc_onSendThemeColorSchemes', (arr) => {
|
||||
storePresentationSettings.addSchemes(arr);
|
||||
});
|
||||
|
||||
// api.asc_registerCallback('asc_onSendThemeColorSchemes', _.bind(this.onSendThemeColorSchemes, this));
|
||||
// me.api.asc_registerCallback('asc_onDocumentUpdateVersion', _.bind(me.onUpdateVersion, me));
|
||||
// me.api.asc_registerCallback('asc_onServerVersion', _.bind(me.onServerVersion, me));
|
||||
// me.api.asc_registerCallback('asc_onAdvancedOptions', _.bind(me.onAdvancedOptions, me));
|
||||
// me.api.asc_registerCallback('asc_onDocumentName', _.bind(me.onDocumentName, me));
|
||||
// me.api.asc_registerCallback('asc_onPrintUrl', _.bind(me.onPrintUrl, me));
|
||||
// me.api.asc_registerCallback('asc_onThumbnailsShow', _.bind(me.onThumbnailsShow, me));
|
||||
// me.api.asc_registerCallback('asc_onMeta', _.bind(me.onMeta, me));
|
||||
EditorUIController.initFocusObjects(this.props.storeFocusObjects);
|
||||
|
||||
const storeFocusObjects = this.props.storeFocusObjects;
|
||||
const storeSlideSettings = this.props.storeSlideSettings;
|
||||
|
||||
this.api.asc_registerCallback('asc_onFocusObject', objects => {
|
||||
// console.log(objects);
|
||||
storeFocusObjects.resetFocusObjects(objects);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onInitEditorStyles', themes => {
|
||||
// console.log(themes);
|
||||
storeSlideSettings.addArrayThemes(themes);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onUpdateThemeIndex', themeId => {
|
||||
// console.log(themeId);
|
||||
storeSlideSettings.changeSlideThemeIndex(themeId);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onUpdateLayout', layouts => {
|
||||
// console.log(layouts);
|
||||
storeSlideSettings.addArrayLayouts(layouts);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onSendThemeColors', (colors, standart_colors) => {
|
||||
Common.Utils.ThemeColor.setColors(colors, standart_colors);
|
||||
});
|
||||
EditorUIController.initEditorStyles(this.props.storeSlideSettings);
|
||||
|
||||
// Text settings
|
||||
|
||||
const storeTextSettings = this.props.storeTextSettings;
|
||||
|
||||
this.api.asc_registerCallback('asc_onInitEditorFonts', (fonts, select) => {
|
||||
storeTextSettings.initEditorFonts(fonts, select);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onFontFamily', (font) => {
|
||||
storeTextSettings.resetFontName(font);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onFontSize', (size) => {
|
||||
storeTextSettings.resetFontSize(size);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onBold', (isBold) => {
|
||||
storeTextSettings.resetIsBold(isBold);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onItalic', (isItalic) => {
|
||||
storeTextSettings.resetIsItalic(isItalic);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onUnderline', (isUnderline) => {
|
||||
storeTextSettings.resetIsUnderline(isUnderline);
|
||||
});
|
||||
|
||||
this.api.asc_registerCallback('asc_onStrikeout', (isStrikeout) => {
|
||||
storeTextSettings.resetIsStrikeout(isStrikeout);
|
||||
});
|
||||
EditorUIController.initFonts(storeTextSettings);
|
||||
|
||||
this.api.asc_registerCallback('asc_onVerticalAlign', (typeBaseline) => {
|
||||
storeTextSettings.resetTypeBaseline(typeBaseline);
|
||||
|
@ -315,11 +257,7 @@ class MainController extends Component {
|
|||
|
||||
// Table settings
|
||||
|
||||
const storeTableSettings = this.props.storeTableSettings;
|
||||
|
||||
this.api.asc_registerCallback('asc_onInitTableTemplates', (templates) => {
|
||||
storeTableSettings.initTableTemplates(templates);
|
||||
});
|
||||
EditorUIController.initTableTemplates(this.props.storeTableSettings);
|
||||
|
||||
// Chart settings
|
||||
|
||||
|
|
|
@ -25,79 +25,15 @@ export class storeFocusObjects {
|
|||
}
|
||||
|
||||
get settings() {
|
||||
const _settings = [];
|
||||
let no_text = true;
|
||||
for (let object of this._focusObjects) {
|
||||
const type = object.get_ObjectType(),
|
||||
objectValue = object.get_ObjectValue();
|
||||
if (Asc.c_oAscTypeSelectElement.Paragraph == type) {
|
||||
if ( !objectValue.get_Locked() )
|
||||
no_text = false;
|
||||
} else if (Asc.c_oAscTypeSelectElement.Table == type) {
|
||||
if ( !objectValue.get_Locked() ) {
|
||||
_settings.push('table');
|
||||
no_text = false;
|
||||
}
|
||||
} else if (Asc.c_oAscTypeSelectElement.Slide == type) {
|
||||
if ( !(objectValue.get_LockLayout() || objectValue.get_LockBackground() || objectValue.get_LockTransition() || objectValue.get_LockTiming() ))
|
||||
_settings.push('slide');
|
||||
} else if (Asc.c_oAscTypeSelectElement.Image == type) {
|
||||
if ( !objectValue.get_Locked() )
|
||||
_settings.push('image');
|
||||
} else if (Asc.c_oAscTypeSelectElement.Chart == type) {
|
||||
if ( !objectValue.get_Locked() )
|
||||
_settings.push('chart');
|
||||
} else if (Asc.c_oAscTypeSelectElement.Shape == type && !objectValue.get_FromChart()) {
|
||||
if ( !objectValue.get_Locked() ) {
|
||||
_settings.push('shape');
|
||||
no_text = false;
|
||||
}
|
||||
} else if (Asc.c_oAscTypeSelectElement.Hyperlink == type) {
|
||||
_settings.push('hyperlink');
|
||||
}
|
||||
}
|
||||
if (!no_text && _settings.indexOf('image') < 0)
|
||||
_settings.unshift('text');
|
||||
const resultArr = _settings.filter((value, index, self) => self.indexOf(value) === index); //get uniq array
|
||||
// Exclude hyperlink if text is locked
|
||||
if (resultArr.indexOf('hyperlink') > -1 && resultArr.indexOf('text') < 0) {
|
||||
resultArr.splice(resultArr.indexOf('hyperlink'), 1);
|
||||
}
|
||||
// Exclude shapes if chart exist
|
||||
if (resultArr.indexOf('chart') > -1 && resultArr.indexOf('shape') > -1) {
|
||||
resultArr.splice(resultArr.indexOf('shape'), 1);
|
||||
}
|
||||
return resultArr;
|
||||
return !!this.intf ? this.intf.filterFocusObjects() : null;
|
||||
}
|
||||
|
||||
get slideObject() {
|
||||
const slides = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Slide) {
|
||||
slides.push(object);
|
||||
}
|
||||
}
|
||||
if (slides.length > 0) {
|
||||
const object = slides[slides.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getSlideObject() : null;
|
||||
}
|
||||
|
||||
get paragraphObject() {
|
||||
const paragraphs = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) {
|
||||
paragraphs.push(object);
|
||||
}
|
||||
}
|
||||
if (paragraphs.length > 0) {
|
||||
const object = paragraphs[paragraphs.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getParagraphObject() : null;
|
||||
}
|
||||
|
||||
get paragraphLocked() {
|
||||
|
@ -111,48 +47,15 @@ export class storeFocusObjects {
|
|||
}
|
||||
|
||||
get shapeObject() {
|
||||
const shapes = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Shape) {
|
||||
shapes.push(object);
|
||||
}
|
||||
}
|
||||
if (shapes.length > 0) {
|
||||
const object = shapes[shapes.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getShapeObject() : null;
|
||||
}
|
||||
|
||||
get imageObject() {
|
||||
const images = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image && object.get_ObjectValue()) {
|
||||
images.push(object);
|
||||
}
|
||||
}
|
||||
if (images.length > 0) {
|
||||
const object = images[images.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getImageObject() : null;
|
||||
}
|
||||
|
||||
get tableObject() {
|
||||
const tables = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
|
||||
tables.push(object);
|
||||
}
|
||||
}
|
||||
if (tables.length > 0) {
|
||||
const object = tables[tables.length - 1]; // get top table
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getTableObject() : null;
|
||||
}
|
||||
|
||||
get isTableInStack() {
|
||||
|
@ -165,34 +68,10 @@ export class storeFocusObjects {
|
|||
}
|
||||
|
||||
get chartObject() {
|
||||
const charts = [];
|
||||
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Chart) {
|
||||
charts.push(object);
|
||||
}
|
||||
}
|
||||
|
||||
if (charts.length > 0) {
|
||||
const object = charts[charts.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getChartObject() : null;
|
||||
}
|
||||
|
||||
get linkObject() {
|
||||
const links = [];
|
||||
for (let object of this._focusObjects) {
|
||||
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {
|
||||
links.push(object);
|
||||
}
|
||||
}
|
||||
if (links.length > 0) {
|
||||
const object = links[links.length - 1]; // get top
|
||||
return object.get_ObjectValue();
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return !!this.intf ? this.intf.getLinkObject() : null;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue