diff --git a/apps/common/mobile/lib/view/collaboration/Comments.jsx b/apps/common/mobile/lib/view/collaboration/Comments.jsx index de88658f7..eb520b3e3 100644 --- a/apps/common/mobile/lib/view/collaboration/Comments.jsx +++ b/apps/common/mobile/lib/view/collaboration/Comments.jsx @@ -583,46 +583,48 @@ const pickLink = (message) => { }); if (message.length<1000 || message.search(/\S{255,}/)<0) - message.replace(Common.Utils.hostnameStrongRe, function(subStr) { - let result = /[\.,\?\+;:=!\(\)]+$/.exec(subStr); - if (result) - subStr = subStr.substring(0, result.index); - let ref = (! /(((^https?)|(^ftp)):\/\/)/i.test(subStr) ) ? ('http://' + subStr) : subStr; - offset = arguments[arguments.length-2]; - len = subStr.length; - let elem = arrayComment.find(function(item){ - return ( (offset>=item.start) && (offset<item.end) || - (offset<=item.start) && (offset+len>item.start)); - }); - if (!elem) + message.replace(Common.Utils.hostnameStrongRe, function(subStr) { + let result = /[\.,\?\+;:=!\(\)]+$/.exec(subStr); + if (result) + subStr = subStr.substring(0, result.index); + let ref = (! /(((^https?)|(^ftp)):\/\/)/i.test(subStr) ) ? ('http://' + subStr) : subStr; + offset = arguments[arguments.length-2]; + len = subStr.length; + let elem = arrayComment.find(function(item){ + return ( (offset>=item.start) && (offset<item.end) || + (offset<=item.start) && (offset+len>item.start)); + }); + if (!elem) arrayComment.push({start: offset, end: len+offset, str: <a onClick={() => window.open(ref)} href={ref} target="_blank" data-can-copy="true">{subStr}</a>}); - return ''; - }); + return ''; + }); - message.replace(Common.Utils.emailStrongRe, function(subStr) { - let ref = (! /((^mailto:)\/\/)/i.test(subStr) ) ? ('mailto:' + subStr) : subStr; - offset = arguments[arguments.length-2]; - len = subStr.length; - let elem = arrayComment.find(function(item){ - return ( (offset>=item.start) && (offset<item.end) || - (offset<=item.start) && (offset+len>item.start)); - }); - if (!elem) - arrayComment.push({start: offset, end: len+offset, str: <a onClick={() => window.open(ref)} href={ref}>{subStr}</a>}); - return ''; - }); + message.replace(Common.Utils.emailStrongRe, function(subStr) { + let ref = (! /((^mailto:)\/\/)/i.test(subStr) ) ? ('mailto:' + subStr) : subStr; + offset = arguments[arguments.length-2]; + len = subStr.length; + let elem = arrayComment.find(function(item){ + return ( (offset>=item.start) && (offset<item.end) || + (offset<=item.start) && (offset+len>item.start)); + }); + if (!elem) + arrayComment.push({start: offset, end: len+offset, str: <a onClick={() => window.open(ref)} href={ref}>{subStr}</a>}); + return ''; + }); - arrayComment = arrayComment.sort(function(item1,item2){ return item1.start - item2.start; }); - - let str_res = (arrayComment.length>0) ? <label>{Common.Utils.String.htmlEncode(message.substring(0, arrayComment[0].start))}{arrayComment[0].str}</label> : <label>{Common.Utils.String.htmlEncode(message)}</label>; - for (var i=1; i<arrayComment.length; i++) { - str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, arrayComment[i].start))}{arrayComment[i].str}</label>; - } - if (arrayComment.length>0) { - str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, message.length))}</label>; - } - return str_res; - + arrayComment = arrayComment.sort(function(item1,item2){ return item1.start - item2.start; }); + + let str_res = (arrayComment.length>0) ? <label>{Common.Utils.String.htmlEncode(message.substring(0, arrayComment[0].start))}{arrayComment[0].str}</label> : <label>{message}</label>; + + for (var i=1; i<arrayComment.length; i++) { + str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, arrayComment[i].start))}{arrayComment[i].str}</label>; + } + + if (arrayComment.length>0) { + str_res = <label>{str_res}{Common.Utils.String.htmlEncode(message.substring(arrayComment[i-1].end, message.length))}</label>; + } + + return str_res; } // View comments diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 4d0ad3a70..4fe976ee1 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -6,6 +6,9 @@ "X Axis": "X Axis XAS", "Y Axis": "Y Axis", "Your text here": "Your text here", + "Error! Bookmark not defined": "Error! Bookmark not defined.", + "above": "above", + "below": "below", "Footer": "Footer", "Header": "Header", "Normal": "Normal", @@ -24,7 +27,40 @@ "Quote": "Quote", "Intense Quote": "Intense Quote", "List Paragraph": "List Paragraph", - "footnote text": "Footnote Text" + "footnote text": "Footnote Text", + "Caption": "Caption", + "endnote text": "Endnote Text", + " -Section ": " -Section ", + "First Page ": "First Page ", + "Even Page ": "Even Page ", + "Odd Page ": "Odd Page ", + "Same as Previous": "Same as Previous", + "Current Document": "Current Document", + "No table of contents entries found.": "There are no headings in the document. Apply a heading style to the text so that it appears in the table of contents.", + "Table of Contents": "Table of Contents", + "Syntax Error": "Syntax Error", + "Missing Operator": "Missing Operator", + "Missing Argument": "Missing Argument", + "Number Too Large To Format": "Number Too Large To Format", + "Zero Divide": "Zero Divide", + "Is Not In Table": "Is Not In Table", + "Index Too Large": "Index Too Large", + "The Formula Not In Table": "The Formula Not In Table", + "Table Index Cannot be Zero": "Table Index Cannot be Zero", + "Undefined Bookmark": "Undefined Bookmark", + "Unexpected End of Formula": "Unexpected End of Formula", + "Hyperlink": "Hyperlink", + "Error! Main Document Only.": "Error! Main Document Only.", + "Error! Not a valid bookmark self-reference.": "Error! Not a valid bookmark self-reference.", + "Error! No text of specified style in document.": "Error! No text of specified style in document.", + "Choose an item": "Choose an item", + "Enter a date": "Enter a date", + "Type equation here": "Type equation here", + "Click to load image": "Click to load image", + "None": "None", + "No table of figures entries found.": "No table of figures entries found.", + "table of figures": "Table of figures", + "TOC Heading": "TOC Heading" }, "textGuest": "Guest", "textAnonymous": "Anonymous", diff --git a/apps/documenteditor/mobile/src/controller/Main.jsx b/apps/documenteditor/mobile/src/controller/Main.jsx index 4bf67dcf4..471070499 100644 --- a/apps/documenteditor/mobile/src/controller/Main.jsx +++ b/apps/documenteditor/mobile/src/controller/Main.jsx @@ -26,7 +26,8 @@ import PluginsController from '../../../../common/mobile/lib/controller/Plugins. "storeTableSettings", "storeDocumentInfo", "storeChartSettings", - "storeApplicationSettings" + "storeApplicationSettings", + "storeLinkSettings" ) class MainController extends Component { constructor(props) { @@ -572,6 +573,12 @@ class MainController extends Component { storeTextSettings.resetBackgroundColor(color); }); + // link settings + const storeLinkSettings = this.props.storeLinkSettings; + this.api.asc_registerCallback('asc_onCanAddHyperlink', (value) => { + storeLinkSettings.canAddHyperlink(value); + }); + //paragraph settings EditorUIController.initEditorStyles && EditorUIController.initEditorStyles(this.props.storeParagraphSettings); diff --git a/apps/documenteditor/mobile/src/controller/add/AddOther.jsx b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx index 3d5ff6b15..e4de3e84f 100644 --- a/apps/documenteditor/mobile/src/controller/add/AddOther.jsx +++ b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx @@ -242,16 +242,25 @@ class AddOtherController extends Component { render () { return ( - <AddOther closeModal={this.closeModal} - onInsertPageNumber={this.onInsertPageNumber} - onPageBreak={this.onPageBreak} - onColumnBreak={this.onColumnBreak} - onInsertSectionBreak={this.onInsertSectionBreak} - getFootnoteProps={this.getFootnoteProps} - getFootnoteStartAt={this.getFootnoteStartAt} - onFootnoteStartAt={this.onFootnoteStartAt} - onInsertFootnote={this.onInsertFootnote} - initFootnoteStartAt={this.initFootnoteStartAt} + <AddOther + closeModal={this.closeModal} + onInsertPageNumber={this.onInsertPageNumber} + onPageBreak={this.onPageBreak} + onColumnBreak={this.onColumnBreak} + onInsertSectionBreak={this.onInsertSectionBreak} + getFootnoteProps={this.getFootnoteProps} + getFootnoteStartAt={this.getFootnoteStartAt} + onFootnoteStartAt={this.onFootnoteStartAt} + onInsertFootnote={this.onInsertFootnote} + initFootnoteStartAt={this.initFootnoteStartAt} + inFootnote={this.props.inFootnote} + inControl={this.props.inControl} + paragraphLocked={this.props.paragraphLocked} + controlPlain={this.props.controlPlain} + richDelLock={this.props.richDelLock} + richEditLock={this.props.richEditLock} + plainDelLock={this.props.plainDelLock} + plainEditLock={this.props.plainEditLock} /> ) } diff --git a/apps/documenteditor/mobile/src/store/linkSettings.js b/apps/documenteditor/mobile/src/store/linkSettings.js new file mode 100644 index 000000000..42e10d243 --- /dev/null +++ b/apps/documenteditor/mobile/src/store/linkSettings.js @@ -0,0 +1,16 @@ +import {action, observable, makeObservable} from 'mobx'; + +export class storeLinkSettings { + constructor() { + makeObservable(this, { + canAddLink: observable, + canAddHyperlink: action + }); + } + + canAddLink; + + canAddHyperlink (value) { + this.canAddLink = value; + } +} diff --git a/apps/documenteditor/mobile/src/store/mainStore.js b/apps/documenteditor/mobile/src/store/mainStore.js index 57fa6ee88..d9a85af99 100644 --- a/apps/documenteditor/mobile/src/store/mainStore.js +++ b/apps/documenteditor/mobile/src/store/mainStore.js @@ -9,6 +9,7 @@ import {storeImageSettings} from "./imageSettings"; import {storeTableSettings} from "./tableSettings"; import {storeChartSettings} from "./chartSettings"; import {storeDocumentInfo} from "./documentInfo"; +import {storeLinkSettings} from './linkSettings'; import {storeApplicationSettings} from './applicationSettings'; import {storeAppOptions} from "./appOptions"; import {storePalette} from "./palette"; @@ -21,6 +22,7 @@ export const stores = { storeDocumentSettings: new storeDocumentSettings(), users: new storeUsers(), storeTextSettings: new storeTextSettings(), + storeLinkSettings: new storeLinkSettings(), storeParagraphSettings: new storeParagraphSettings(), storeShapeSettings: new storeShapeSettings(), storeChartSettings: new storeChartSettings(), diff --git a/apps/documenteditor/mobile/src/view/add/Add.jsx b/apps/documenteditor/mobile/src/view/add/Add.jsx index c09a2690a..6538f5a21 100644 --- a/apps/documenteditor/mobile/src/view/add/Add.jsx +++ b/apps/documenteditor/mobile/src/view/add/Add.jsx @@ -79,38 +79,97 @@ const AddLayoutContent = ({ tabs }) => { const AddTabs = inject("storeFocusObjects")(observer(({storeFocusObjects, showPanels, style, inPopover}) => { const { t } = useTranslation(); const _t = t('Add', {returnObjects: true}); + const api = Common.EditorApi.get(); const tabs = []; const options = storeFocusObjects.settings; + const paragraphObj = storeFocusObjects.paragraphObject; + + let needDisable = false, + canAddTable = true, + canAddImage = true, + paragraphLocked = false, + inFootnote = false, + inControl = false, + controlProps = false, + lockType = false, + controlPlain = false, + contentLocked = false, + richDelLock = false, + richEditLock = false, + plainDelLock = false, + plainEditLock = false; + + if(paragraphObj) { + canAddTable = paragraphObj.get_CanAddTable(); + canAddImage = paragraphObj.get_CanAddImage(); + paragraphLocked = paragraphObj.get_Locked(); + + inFootnote = api.asc_IsCursorInFootnote() || api.asc_IsCursorInEndnote(); + inControl = api.asc_IsContentControl(); + + controlProps = inControl ? api.asc_GetContentControlProperties() : null; + lockType = (inControl && controlProps) ? controlProps.get_Lock() : Asc.c_oAscSdtLockType.Unlocked; + controlPlain = (inControl && controlProps) ? (controlProps.get_ContentControlType() == Asc.c_oAscSdtLevelType.Inline) : false; + contentLocked = lockType == Asc.c_oAscSdtLockType.SdtContentLocked || lockType == Asc.c_oAscSdtLockType.ContentLocked; + + richDelLock = paragraphObj ? !paragraphObj.can_DeleteBlockContentControl() : false; + richEditLock = paragraphObj ? !paragraphObj.can_EditBlockContentControl() : false; + plainDelLock = paragraphObj ? !paragraphObj.can_DeleteInlineContentControl() : false; + plainEditLock = paragraphObj ? !paragraphObj.can_EditInlineContentControl() : false; + } + if (!showPanels && options.indexOf('text') > -1) { - tabs.push({ - caption: _t.textTable, - id: 'add-table', - icon: 'icon-add-table', - component: <AddTableController/> - }); + needDisable = !canAddTable || controlPlain || richEditLock || plainEditLock || richDelLock || plainDelLock; + + if(!needDisable) { + tabs.push({ + caption: _t.textTable, + id: 'add-table', + icon: 'icon-add-table', + component: <AddTableController/> + }); + } } if(!showPanels) { - tabs.push({ - caption: _t.textShape, - id: 'add-shape', - icon: 'icon-add-shape', - component: <AddShapeController/> - }); + needDisable = paragraphLocked || controlPlain || contentLocked || inFootnote; + + if(!needDisable) { + tabs.push({ + caption: _t.textShape, + id: 'add-shape', + icon: 'icon-add-shape', + component: <AddShapeController/> + }); + } } if(!showPanels) { - tabs.push({ - caption: _t.textImage, - id: 'add-image', - icon: 'icon-add-image', - component: <AddImageController/> - }); + needDisable = paragraphLocked || paragraphObj && !canAddImage || controlPlain || richDelLock || plainDelLock || contentLocked; + + if(!needDisable) { + tabs.push({ + caption: _t.textImage, + id: 'add-image', + icon: 'icon-add-image', + component: <AddImageController/> + }); + } } if(!showPanels) { tabs.push({ caption: _t.textOther, id: 'add-other', icon: 'icon-add-other', - component: <AddOtherController/> + component: + <AddOtherController + inFootnote={inFootnote} + inControl={inControl} + paragraphLocked={paragraphLocked} + controlPlain={controlPlain} + richDelLock={richDelLock} + richEditLock={richEditLock} + plainDelLock={plainDelLock} + plainEditLock={plainEditLock} + /> }); } if (showPanels && showPanels === 'link') { diff --git a/apps/documenteditor/mobile/src/view/add/AddOther.jsx b/apps/documenteditor/mobile/src/view/add/AddOther.jsx index 240e27521..7823f05e9 100644 --- a/apps/documenteditor/mobile/src/view/add/AddOther.jsx +++ b/apps/documenteditor/mobile/src/view/add/AddOther.jsx @@ -153,40 +153,63 @@ const PageFootnote = props => { const AddOther = props => { const { t } = useTranslation(); const _t = t('Add', {returnObjects: true}); - const storeFocusObjects = props.storeFocusObjects; + const storeLinkSettings = props.storeLinkSettings; + const canAddLink = storeLinkSettings.canAddLink; + let isShape = storeFocusObjects.settings.indexOf('shape') > -1, isText = storeFocusObjects.settings.indexOf('text') > -1, isChart = storeFocusObjects.settings.indexOf('chart') > -1; + let disabledAddLink = false, + disabledAddBreak = false, + disabledAddFootnote = false, + disabledAddPageNumber = false, + inFootnote = props.inFootnote, + inControl = props.inControl, + paragraphLocked = props.paragraphLocked, + controlPlain = props.controlPlain, + richDelLock = props.richDelLock, + richEditLock = props.richEditLock, + plainDelLock = props.plainDelLock, + plainEditLock = props.plainEditLock; + + disabledAddBreak = paragraphLocked || inFootnote || inControl || richEditLock || plainEditLock || richDelLock || plainDelLock; + disabledAddFootnote = paragraphLocked || controlPlain || richEditLock || plainEditLock; + disabledAddLink = paragraphLocked || !canAddLink; + disabledAddPageNumber = controlPlain; + return ( <List> - {isText &&<ListItem title={_t.textComment} onClick={() => { + {isText && <ListItem title={_t.textComment} onClick={() => { props.closeModal(); Common.Notifications.trigger('addcomment'); }}> <Icon slot="media" icon="icon-insert-comment"></Icon> </ListItem>} - {isText && <ListItem title={_t.textLink} link={'/add-link/'} routeProps={{ + {(isText && !disabledAddLink) && <ListItem title={_t.textLink} link={'/add-link/'} routeProps={{ onInsertLink: props.onInsertLink, getDisplayLinkText: props.getDisplayLinkText }}> <Icon slot="media" icon="icon-link"></Icon> </ListItem>} - <ListItem title={_t.textPageNumber} link={'/add-page-number/'} routeProps={{ - onInsertPageNumber: props.onInsertPageNumber - }}> - <Icon slot="media" icon="icon-pagenumber"></Icon> - </ListItem> - {(isShape || isChart) ? null : - [ <ListItem key='break' title={_t.textBreak} link={'/add-break/'} routeProps={{ + {!disabledAddPageNumber && + <ListItem title={_t.textPageNumber} link={'/add-page-number/'} routeProps={{ + onInsertPageNumber: props.onInsertPageNumber + }}> + <Icon slot="media" icon="icon-pagenumber"></Icon> + </ListItem> + } + {(isShape || isChart) || (isText && disabledAddBreak) ? null : + <ListItem key='break' title={_t.textBreak} link={'/add-break/'} routeProps={{ onPageBreak: props.onPageBreak, onColumnBreak: props.onColumnBreak, onInsertSectionBreak: props.onInsertSectionBreak }}> <Icon slot="media" icon="icon-sectionbreak"></Icon> - </ListItem>, - + </ListItem> + } + {(isShape || isChart) || (isText && disabledAddFootnote) ? null : <ListItem key='footnote' title={_t.textFootnote} link={'/add-footnote/'} routeProps={{ getFootnoteProps: props.getFootnoteProps, getFootnoteStartAt: props.getFootnoteStartAt, @@ -195,13 +218,13 @@ const AddOther = props => { initFootnoteStartAt: props.initFootnoteStartAt }}> <Icon slot="media" icon="icon-footnote"></Icon> - </ListItem> ] + </ListItem> } </List> ) }; -const AddOtherContainer = inject("storeComments","storeFocusObjects")(observer(AddOther)); +const AddOtherContainer = inject("storeComments","storeFocusObjects", "storeLinkSettings")(observer(AddOther)); export {AddOtherContainer as AddOther, PageNumber as PageAddNumber, diff --git a/apps/presentationeditor/mobile/locale/en.json b/apps/presentationeditor/mobile/locale/en.json index 8b114090e..5424aece7 100644 --- a/apps/presentationeditor/mobile/locale/en.json +++ b/apps/presentationeditor/mobile/locale/en.json @@ -20,7 +20,11 @@ "Slide number": "Slide number", "Slide subtitle": "Slide subtitle", "Table": "Table", - "Slide title": "Slide title" + "Slide title": "Slide title", + "Loading": "Loading", + "Click to add notes": "Click to add notes", + "Click to add first slide": "Click to add first slide", + "None": "None" }, "textGuest": "Guest", "textAnonymous": "Anonymous",