import React, {Fragment} from 'react'; import {Link} from 'framework7-react'; import { Device } from '../../web-apps/apps/common/mobile/utils/device'; import { AddCommentController, EditCommentController, } from "../../web-apps/apps/common/mobile/lib/controller/collaboration/Comments"; const EditorUIController = () => { return null }; EditorUIController.isSupportEditFeature = () => { return true; }; /** This is the file where the magic happens. Try to figure out a working version from the old commits and my hunches from hacking around in the old webapp editor */ // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/0277ac930611db0637100a2c5e6891ea495610a8#diff-755ea3df479f23211982e28466b363be9df22cb92f4a5cf9126ec9e227d6909bL66-L72 EditorUIController.getToolbarOptions = (options) => { // console.log('EditorUIController.getToolbarOptions' ,options); return ( options.onEditClick()}> options.onAddClick()}> ); }; // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/0277ac930611db0637100a2c5e6891ea495610a8 EditorUIController.getUndoRedo = (options) => { // console.log('EditorUIController.getUndoRedo', options); return ( options.onUndoClick()}> options.onRedoClick()}> ); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/45a9058da461a9da67ccb389faad08bce8cbda55#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL307-L308 EditorUIController.getEditCommentControllers = () => { // console.log('EditorUIController.getEditCommentControllers'); return ( ); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL233-L259 EditorUIController.initFonts = (storeTextSettings) => { // console.log('EditorUIController.initFonts', storeTextSettings); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onInitEditorFonts', (fonts, select) => { // console.log('asc_onInitEditorFonts', fonts, select); storeTextSettings.initEditorFonts(fonts, select); }); api.asc_registerCallback('asc_onFontFamily', (font) => { // console.log('asc_onFontFamily', font); storeTextSettings.resetFontName(font); }); api.asc_registerCallback('asc_onFontSize', (size) => { // console.log('asc_onFontSize', size); storeTextSettings.resetFontSize(size); }); api.asc_registerCallback('asc_onBold', (isBold) => { // console.log('asc_onBold', isBold); storeTextSettings.resetIsBold(isBold); }); api.asc_registerCallback('asc_onItalic', (isItalic) => { // console.log('asc_onItalic', isItalic); storeTextSettings.resetIsItalic(isItalic); }); api.asc_registerCallback('asc_onUnderline', (isUnderline) => { // console.log('asc_onUnderline', isUnderline); storeTextSettings.resetIsUnderline(isUnderline); }); api.asc_registerCallback('asc_onStrikeout', (isStrikeout) => { // console.log('asc_onStrikeout', isStrikeout); storeTextSettings.resetIsStrikeout(isStrikeout); }); }; // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL210-L223 EditorUIController.initEditorStyles = (storeSlideSettings) => { // console.log('EditorUIController.initEditorStyles', storeSlideSettings); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onInitEditorStyles', themes => { // themes is an array of array with index 0 representing defaultThemes and 1 representing documentThemes // Inspired by what's done in /view/edit/EditSlide.jsx let defaultThemes = themes[0]; let docThemes = themes[1]; let arrayThemes = []; defaultThemes.forEach(function(theme, index) { arrayThemes.push({ themeId : theme.get_Index(), tip : theme.get_Name(), offsety : index * 40 }); }); docThemes.forEach(function(theme) { arrayThemes.push({ imageUrl: theme.get_Image(), themeId : theme.get_Index(), tip : theme.get_Name(), offsety : 0 }); }); storeSlideSettings.addArrayThemes(arrayThemes); }); api.asc_registerCallback('asc_onUpdateThemeIndex', themeId => { // console.log(themeId); storeSlideSettings.changeSlideThemeIndex(themeId); }); api.asc_registerCallback('asc_onUpdateLayout', layouts => { // console.log(layouts); storeSlideSettings.addArrayLayouts(layouts); }); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL202-L208 EditorUIController.initFocusObjects = (storeFocusObjects) => { storeFocusObjects.intf = EditorUIController.Intf(storeFocusObjects); // console.log('EditorUIController.initFocusObjects', storeFocusObjects); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onFocusObject', objects => { // console.log('asc_onFocusObject', objects); storeFocusObjects.resetFocusObjects(objects); }); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL318-L322 EditorUIController.initTableTemplates = (storeTableSettings) => { // console.log('EditorUIController.initTableTemplates', storeTableSettings); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onInitTableTemplates', (templates) => { // console.log('asc_onInitTableTemplates', templates); storeTableSettings.initTableTemplates(templates); }); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL225-L227 EditorUIController.initThemeColors = () => { // console.log('EditorUIController.initThemeColors'); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onSendThemeColors', (colors, standart_colors) => { // console.log('asc_onSendThemeColors', colors, standart_colors); Common.Utils.ThemeColor.setColors(colors, standart_colors); }); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/45a9058da461a9da67ccb389faad08bce8cbda55#diff-1d89c904c6cd5147fb6942c09c4d12a2f3a3200a61b3e29b1a42a1263e57848bL264-L270 EditorUIController.updateChartStyles = (storeChartSettings, storeFocusObjects) => { // console.log('EditorUIController.updateChartStyles', storeChartSettings, storeFocusObjects); const api = Common.EditorApi.get(); api.asc_registerCallback('asc_onUpdateChartStyles', () => { // console.log('asc_onUpdateChartStyles', storeFocusObjects.chartObject); if (storeFocusObjects.chartObject && storeFocusObjects.chartObject.get_ChartProperties()) { // console.log('we in'); storeChartSettings.updateChartStyles(api.asc_getChartPreviews(storeFocusObjects.chartObject.get_ChartProperties().getType())); } }); } // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-f711cbc9449c97e0d6394cf70e9c04eeca1d9e520a1f2e7b390b1a5bc5acd82d EditorUIController.ContextMenu = { mapMenuItems: (contextMenu) => { // console.log('EditorUIController.ContextMenu.mapMenuItems', contextMenu); if ( !Common.EditorApi ) return []; const { t } = contextMenu.props; const _t = t("ContextMenu", { returnObjects: true }); const { isEdit, canViewComments, canReview, isDisconnected } = contextMenu.props; const { isViewer, isProtected } = contextMenu.props; // This probably needs to be refired if(!isEdit || isViewer || isProtected) return EditorUIController.ContextMenu.mapMenuItemsReadOnly(contextMenu); const api = Common.EditorApi.get(); const stack = api.getSelectedElements(); const canCopy = api.can_CopyCut(); let itemsIcon = [], itemsText = []; if ( canCopy ) { itemsIcon.push({ event: 'copy', icon: 'icon-copy' }); } if ( canViewComments && contextMenu.isComments && !isEdit ) { itemsText.push({ caption: _t.menuViewComment, event: 'viewcomment' }); } let isText = false, isTable = false, isImage = false, isChart = false, isShape = false, isLink = false, lockedText = false, lockedTable = false, lockedImage = false, lockedHeader = false; stack.forEach(item => { const objectType = item.get_ObjectType(), objectValue = item.get_ObjectValue(); if ( objectType == Asc.c_oAscTypeSelectElement.Header ) { lockedHeader = objectValue.get_Locked(); } else if ( objectType == Asc.c_oAscTypeSelectElement.Paragraph ) { lockedText = objectValue.get_Locked(); isText = true; } else if ( objectType == Asc.c_oAscTypeSelectElement.Image ) { lockedImage = objectValue.get_Locked(); if ( objectValue && objectValue.get_ChartProperties() ) { isChart = true; } else if ( objectValue && objectValue.get_ShapeProperties() ) { isShape = true; } else { isImage = true; } } else if ( objectType == Asc.c_oAscTypeSelectElement.Table ) { lockedTable = objectValue.get_Locked(); isTable = true; } else if ( objectType == Asc.c_oAscTypeSelectElement.Hyperlink ) { isLink = true; } }); if ( stack.length > 0 ) { const swapItems = function(items, indexBefore, indexAfter) { items[indexAfter] = items.splice(indexBefore, 1, items[indexAfter])[0]; }; if ( isEdit && !isDisconnected ) { if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader && canCopy ) { itemsIcon.push({ event: 'cut', icon: 'icon-cut' }); // Swap 'Copy' and 'Cut' swapItems(itemsIcon, 0, 1); } if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) { itemsIcon.push({ event: 'paste', icon: 'icon-paste' }); } if ( isTable && api.CheckBeforeMergeCells() && !lockedTable && !lockedHeader) { itemsText.push({ caption: _t.menuMerge, event: 'merge' }); } if ( isTable && api.CheckBeforeSplitCells() && !lockedTable && !lockedHeader ) { itemsText.push({ caption: _t.menuSplit, event: 'split' }); } if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) { itemsText.push({ caption: _t.menuDelete, event: 'delete' }); } if ( isTable && !lockedTable && !lockedText && !lockedHeader ) { itemsText.push({ caption: _t.menuDeleteTable, event: 'deletetable' }); } if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ){ itemsText.push({ caption: _t.menuEdit, event: 'edit' }); } if ( !!api.can_AddHyperlink() && !lockedHeader) { itemsText.push({ caption: _t.menuAddLink, event: 'addlink' }); } if(isLink && !lockedHeader) { itemsText.push({ caption: _t.menuEditLink, event: 'editlink' }); } if ( canReview ) { if (contextMenu.inRevisionChange) { itemsText.push({ caption: _t.menuReviewChange, event: 'reviewchange' }); } else { itemsText.push({ caption: _t.menuReview, event: 'review' }); } } if ( contextMenu.isComments && canViewComments ) { itemsText.push({ caption: _t.menuViewComment, event: 'viewcomment' }); } const isObject = isShape || isChart || isImage || isTable; const hideAddComment = !canViewComments || api.can_AddQuotedComment() === false || lockedText || lockedTable || lockedImage || lockedHeader || (!isText && isObject); if ( !hideAddComment ) { itemsText.push({ caption: _t.menuAddComment, event: 'addcomment' }); } } } if ( isLink ) { itemsText.push({ caption: _t.menuOpenLink, event: 'openlink' }); } if ( Device.phone && itemsText.length > 2 ) { contextMenu.extraItems = itemsText.splice(2,itemsText.length, { caption: _t.menuMore, event: 'showActionSheet' }); } const menuItems = itemsIcon.concat(itemsText); // console.log('EditorUIController.ContextMenu.mapMenuItems', menuItems); return menuItems; } , handleMenuItemClick: (contextMenu, action) => { // console.log('EditorUIController.ContextMenu.handleMenuItemClick', contextMenu, action); const api = Common.EditorApi.get(); switch (action) { case 'edit': setTimeout(() => { contextMenu.props.openOptions('edit'); }, 0); return true; case 'addcomment': Common.Notifications.trigger('addcomment'); return true; case 'merge': api.MergeCells(); return true; case 'delete': api.asc_Remove(); return true; case 'deletetable': api.remTable(); return true; case 'editlink': setTimeout(() => { contextMenu.props.openOptions('edit', 'link'); }, 400) return true; } return false; }, // This method handles the menu items shown when the user is in edit mode but // can't edit the form i.e: in viewer mode or when the document is protected // This is mostly a copy of the else statement of ContextMenu.initMenuItems // with the bare minimum modifications so it can execute. // It is done that way on purpose even if some code ends up duplicated // This should make noticing and following Onlyoffice changes easier mapMenuItemsReadOnly: (contextMenu) => { const { t } = contextMenu.props; const _t = t("ContextMenu", { returnObjects: true }); const { isEdit, isDisconnected, isVersionHistoryMode } = contextMenu.props; const { isComments, canViewComments, canCoAuthoring, canComments } = contextMenu.props; const api = Common.EditorApi.get(); const stack = api.getSelectedElements(); const canCopy = api.can_CopyCut(); let itemsIcon = [], itemsText = []; let isText = false, isTable = false, isImage = false, isChart = false, isShape = false, isLink = false, isSlide = false, isObject, locked = false; stack.forEach(item => { const objectType = item.get_ObjectType(), objectValue = item.get_ObjectValue(); locked = typeof objectValue.get_Locked === 'function' ? objectValue.get_Locked() : 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; } }); isObject = isText || isImage || isChart || isShape || isTable; if (canCopy && isObject) { itemsIcon.push({ event: 'copy', icon: 'icon-copy' }); } if(!isDisconnected && !isVersionHistoryMode) { if (canViewComments && isComments && !isEdit) { itemsText.push({ caption: _t.menuViewComment, event: 'viewcomment' }); } if (!isChart && api.can_AddQuotedComment() !== false && canCoAuthoring && canComments && !locked) { itemsText.push({ caption: _t.menuAddComment, event: 'addcomment' }); } } if (isLink) { itemsText.push({ caption: _t.menuOpenLink, event: 'openlink' }); } return itemsIcon.concat(itemsText); } }; // This objects holds the mysterious functions in focusObjects.js inside the intf object // These for now are based on the latest valid implementation from the mobile editor // Code taken from // https://github.com/ONLYOFFICE/web-apps/commit/fe1a9e16d3c18cb5e9c2cc1aa512649c348aa283#diff-1a8252788e3c9baa4e6bcdd6a91d4718fcf3ac90f0f12b4e3263f9cccba53f8d EditorUIController.Intf = function (storeFocusObjects) { var obj = {}; obj.filterFocusObjects = () => { const _settings = []; let no_text = true; for (let object of storeFocusObjects._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; } obj.getSlideObject = () => { const slides = []; for (let object of storeFocusObjects._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; } } obj.getParagraphObject = () => { const paragraphs = []; for (let object of storeFocusObjects._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; } } obj.getShapeObject = () => { const shapes = []; for (let object of storeFocusObjects._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; } } obj.getImageObject = () => { const images = []; for (let object of storeFocusObjects._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; } } obj.getTableObject = () => { const tables = []; for (let object of storeFocusObjects._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; } } obj.getChartObject = () => { const charts = []; for (let object of storeFocusObjects._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; } } obj.getLinkObject = () => { const links = []; for (let object of storeFocusObjects._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 obj; } export default EditorUIController;