[PE mobile] Added the ability insert links
This commit is contained in:
parent
3e6f6bc964
commit
6998771d0c
|
@ -165,10 +165,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.inputs-list {
|
&.inputs-list {
|
||||||
.item-input {
|
.item-input, .item-link {
|
||||||
.item-inner {
|
.item-inner {
|
||||||
display: block;
|
display: block;
|
||||||
.item-label {
|
.item-title, .item-label {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,21 @@
|
||||||
"textTableSize": "Table Size",
|
"textTableSize": "Table Size",
|
||||||
"textColumns": "Columns",
|
"textColumns": "Columns",
|
||||||
"textRows": "Rows",
|
"textRows": "Rows",
|
||||||
"textCancel": "Cancel"
|
"textCancel": "Cancel",
|
||||||
|
"textLink": "Link",
|
||||||
|
"textLinkType": "Link Type",
|
||||||
|
"textExternalLink": "External Link",
|
||||||
|
"textSlideInThisPresentation": "Slide in this Presentation",
|
||||||
|
"textLinkTo": "Link to",
|
||||||
|
"textNextSlide": "Next Slide",
|
||||||
|
"textPreviousSlide": "Previous Slide",
|
||||||
|
"textFirstSlide": "First Slide",
|
||||||
|
"textLastSlide": "Last Slide",
|
||||||
|
"textSlideNumber": "Slide Number",
|
||||||
|
"textDisplay": "Display",
|
||||||
|
"textDefault": "Selected text",
|
||||||
|
"textScreenTip": "Screen Tip",
|
||||||
|
"textInsert": "Insert"
|
||||||
},
|
},
|
||||||
"Edit": {
|
"Edit": {
|
||||||
"textText": "Text",
|
"textText": "Text",
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { f7 } from "framework7-react";
|
||||||
import { withTranslation } from 'react-i18next';
|
import { withTranslation } from 'react-i18next';
|
||||||
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
|
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
|
||||||
|
|
||||||
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings", "storeTableSettings")
|
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings", "storeTableSettings", "storeLinkSettings")
|
||||||
class MainController extends Component {
|
class MainController extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -304,6 +304,12 @@ class MainController extends Component {
|
||||||
this.api.asc_registerCallback('asc_onInitTableTemplates', (templates) => {
|
this.api.asc_registerCallback('asc_onInitTableTemplates', (templates) => {
|
||||||
storeTableSettings.initTableTemplates(templates);
|
storeTableSettings.initTableTemplates(templates);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//link settings
|
||||||
|
const storeLinkSettings = this.props.storeLinkSettings;
|
||||||
|
this.api.asc_registerCallback('asc_onCanAddHyperlink', (value) => {
|
||||||
|
storeLinkSettings.canAddHyperlink(value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDocumentContentReady() {
|
_onDocumentContentReady() {
|
||||||
|
|
112
apps/presentationeditor/mobile/src/controller/add/AddLink.jsx
Normal file
112
apps/presentationeditor/mobile/src/controller/add/AddLink.jsx
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import { f7 } from 'framework7-react';
|
||||||
|
import {Device} from '../../../../../common/mobile/utils/device';
|
||||||
|
import { withTranslation} from 'react-i18next';
|
||||||
|
|
||||||
|
import {PageLink} from '../../view/add/AddLink';
|
||||||
|
|
||||||
|
class AddLinkController extends Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
this.onInsertLink = this.onInsertLink.bind(this);
|
||||||
|
this.getTextDisplay = this.getTextDisplay.bind(this);
|
||||||
|
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
this.textDisplay = api.can_AddHyperlink();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal () {
|
||||||
|
if ( Device.phone ) {
|
||||||
|
f7.sheet.close('.add-popup', true);
|
||||||
|
} else {
|
||||||
|
f7.popover.close('#add-popover');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onInsertLink (type, linkInfo) {
|
||||||
|
const api = Common.EditorApi.get();
|
||||||
|
const { t } = this.props;
|
||||||
|
const _t = t("View.Add", { returnObjects: true });
|
||||||
|
|
||||||
|
const c_oHyperlinkType = {
|
||||||
|
InternalLink: 0,
|
||||||
|
WebLink: 1
|
||||||
|
};
|
||||||
|
const display = linkInfo.display;
|
||||||
|
const tip = linkInfo.tip;
|
||||||
|
const props = new Asc.CHyperlinkProperty();
|
||||||
|
let def_display = '';
|
||||||
|
|
||||||
|
if (type == c_oHyperlinkType.WebLink) {
|
||||||
|
let url = linkInfo.url;
|
||||||
|
const urltype = api.asc_getUrlType(url.trim());
|
||||||
|
const isEmail = (urltype == 2);
|
||||||
|
if (urltype < 1) {
|
||||||
|
f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = url.replace(/^\s+|\s+$/g, '');
|
||||||
|
if (!/(((^https?)|(^ftp)):\/\/)|(^mailto:)/i.test(url))
|
||||||
|
url = (isEmail ? 'mailto:' : 'http://' ) + url;
|
||||||
|
url = url.replace(new RegExp("%20", 'g'), " ");
|
||||||
|
|
||||||
|
props.put_Value(url);
|
||||||
|
props.put_ToolTip(tip);
|
||||||
|
def_display = url;
|
||||||
|
} else {
|
||||||
|
let url = "ppaction://hlink";
|
||||||
|
let slidetip = '';
|
||||||
|
switch (linkInfo.linkTo) {
|
||||||
|
case 0:
|
||||||
|
url = url + "showjump?jump=nextslide";
|
||||||
|
slidetip = _t.textNextSlide;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
url = url + "showjump?jump=previousslide";
|
||||||
|
slidetip = _t.textPrevSlide;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
url = url + "showjump?jump=firstslide";
|
||||||
|
slidetip = _t.textFirstSlide;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
url = url + "showjump?jump=lastslide";
|
||||||
|
slidetip = _t.textLastSlide;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
url = url + "sldjumpslide" + linkInfo.numberTo;
|
||||||
|
slidetip = _t.textSlide + ' ' + (linkInfo.numberTo + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
props.put_Value(url);
|
||||||
|
props.put_ToolTip(!tip ? slidetip : tip);
|
||||||
|
def_display = slidetip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!linkInfo.displayDisabled) {
|
||||||
|
props.put_Text(!display ? def_display : display);
|
||||||
|
} else
|
||||||
|
props.put_Text(null);
|
||||||
|
|
||||||
|
api.add_Hyperlink(props);
|
||||||
|
|
||||||
|
this.closeModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTextDisplay () {
|
||||||
|
return this.textDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<PageLink onInsertLink={this.onInsertLink}
|
||||||
|
getTextDisplay={this.getTextDisplay}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddLinkWithTranslation = withTranslation()(AddLinkController);
|
||||||
|
|
||||||
|
export {AddLinkWithTranslation as AddLinkController};
|
|
@ -83,6 +83,16 @@ export class storeFocusObjects {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed get paragraphLocked() {
|
||||||
|
let _paragraphLocked = false;
|
||||||
|
for (let object of this._focusObjects) {
|
||||||
|
if (Asc.c_oAscTypeSelectElement.Paragraph == object.get_ObjectType()) {
|
||||||
|
_paragraphLocked = object.get_ObjectValue().get_Locked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _paragraphLocked;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get shapeObject() {
|
@computed get shapeObject() {
|
||||||
const shapes = [];
|
const shapes = [];
|
||||||
for (let object of this._focusObjects) {
|
for (let object of this._focusObjects) {
|
||||||
|
|
8
apps/presentationeditor/mobile/src/store/linkSettings.js
Normal file
8
apps/presentationeditor/mobile/src/store/linkSettings.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import {action, observable, computed} from 'mobx';
|
||||||
|
|
||||||
|
export class storeLinkSettings {
|
||||||
|
@observable canAddLink;
|
||||||
|
@action canAddHyperlink (value) {
|
||||||
|
this.canAddLink = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import { storeShapeSettings } from './shapeSettings';
|
||||||
// import {storeImageSettings} from "./imageSettings";
|
// import {storeImageSettings} from "./imageSettings";
|
||||||
import {storeTableSettings} from "./tableSettings";
|
import {storeTableSettings} from "./tableSettings";
|
||||||
// import {storeChartSettings} from "./chartSettings";
|
// import {storeChartSettings} from "./chartSettings";
|
||||||
|
import {storeLinkSettings} from "./linkSettings";
|
||||||
|
|
||||||
export const stores = {
|
export const stores = {
|
||||||
storeAppOptions: new storeAppOptions(),
|
storeAppOptions: new storeAppOptions(),
|
||||||
|
@ -33,6 +34,7 @@ export const stores = {
|
||||||
// storeParagraphSettings: new storeParagraphSettings(),
|
// storeParagraphSettings: new storeParagraphSettings(),
|
||||||
// storeShapeSettings: new storeShapeSettings(),
|
// storeShapeSettings: new storeShapeSettings(),
|
||||||
// storeChartSettings: new storeChartSettings(),
|
// storeChartSettings: new storeChartSettings(),
|
||||||
storeTableSettings: new storeTableSettings()
|
storeTableSettings: new storeTableSettings(),
|
||||||
|
storeLinkSettings: new storeLinkSettings()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ import {AddImageController} from "../../controller/add/AddImage";
|
||||||
import {PageImageLinkSettings} from "./AddImage";
|
import {PageImageLinkSettings} from "./AddImage";
|
||||||
import {AddOtherController} from "../../controller/add/AddOther";
|
import {AddOtherController} from "../../controller/add/AddOther";
|
||||||
import {PageAddTable} from "./AddOther";
|
import {PageAddTable} from "./AddOther";
|
||||||
|
import {AddLinkController} from "../../controller/add/AddLink";
|
||||||
|
import {PageTypeLink, PageLinkTo} from "./AddLink";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// Image
|
// Image
|
||||||
|
@ -22,6 +24,18 @@ const routes = [
|
||||||
{
|
{
|
||||||
path: '/add-table/',
|
path: '/add-table/',
|
||||||
component: PageAddTable
|
component: PageAddTable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/add-link/',
|
||||||
|
component: AddLinkController
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/add-link-type/',
|
||||||
|
component: PageTypeLink
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/add-link-to/',
|
||||||
|
component: PageLinkTo
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
154
apps/presentationeditor/mobile/src/view/add/AddLink.jsx
Normal file
154
apps/presentationeditor/mobile/src/view/add/AddLink.jsx
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
import React, {useState} from 'react';
|
||||||
|
import {observer, inject} from "mobx-react";
|
||||||
|
import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, Segmented, Button} from 'framework7-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {Device} from "../../../../../common/mobile/utils/device";
|
||||||
|
|
||||||
|
const PageTypeLink = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const _t = t('View.Add', {returnObjects: true});
|
||||||
|
const [typeLink, setTypeLink] = useState(props.curType);
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<Navbar title={_t.textLinkType} backLink={_t.textBack}/>
|
||||||
|
<List>
|
||||||
|
<ListItem title={_t.textExternalLink} radio checked={typeLink === 1} onClick={() => {setTypeLink(1); props.changeType(1);}}></ListItem>
|
||||||
|
<ListItem title={_t.textSlideInThisPresentation} radio checked={typeLink === 0} onClick={() => {setTypeLink(0); props.changeType(0);}}></ListItem>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageLinkTo = props => {
|
||||||
|
const isAndroid = Device.android;
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const _t = t('View.Add', {returnObjects: true});
|
||||||
|
|
||||||
|
const [stateTypeTo, setTypeTo] = useState(props.curTo);
|
||||||
|
const changeTypeTo = (type) => {
|
||||||
|
setTypeTo(type);
|
||||||
|
props.changeTo(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [stateNumberTo, setNumberTo] = useState(0);
|
||||||
|
const changeNumber = (curNumber, isDecrement) => {
|
||||||
|
setTypeTo(4);
|
||||||
|
let value;
|
||||||
|
if (isDecrement) {
|
||||||
|
value = curNumber - 1;
|
||||||
|
} else {
|
||||||
|
value = curNumber + 1;
|
||||||
|
}
|
||||||
|
setNumberTo(value);
|
||||||
|
props.changeTo(4, value);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<Navbar title={_t.textLinkTo} backLink={_t.textBack}/>
|
||||||
|
<List>
|
||||||
|
<ListItem title={_t.textNextSlide} radio checked={stateTypeTo === 0} onClick={() => {changeTypeTo(0)}}></ListItem>
|
||||||
|
<ListItem title={_t.textPreviousSlide} radio checked={stateTypeTo === 1} onClick={() => {changeTypeTo(1)}}></ListItem>
|
||||||
|
<ListItem title={_t.textFirstSlide} radio checked={stateTypeTo === 2} onClick={() => {changeTypeTo(2)}}></ListItem>
|
||||||
|
<ListItem title={_t.textLastSlide} radio checked={stateTypeTo === 3} onClick={() => {changeTypeTo(3)}}></ListItem>
|
||||||
|
<ListItem title={_t.textSlideNumber}>
|
||||||
|
{!isAndroid && <div slot='after-start'>{stateNumberTo + 1}</div>}
|
||||||
|
<div slot='after'>
|
||||||
|
<Segmented>
|
||||||
|
<Button outline className='decrement item-link' onClick={() => {changeNumber(stateNumberTo, true);}}>
|
||||||
|
{isAndroid ? <Icon icon="icon-expand-down"></Icon> : ' - '}
|
||||||
|
</Button>
|
||||||
|
{isAndroid && <label>{stateNumberTo + 1}</label>}
|
||||||
|
<Button outline className='increment item-link' onClick={() => {changeNumber(stateNumberTo, false);}}>
|
||||||
|
{isAndroid ? <Icon icon="icon-expand-up"></Icon> : ' + '}
|
||||||
|
</Button>
|
||||||
|
</Segmented>
|
||||||
|
</div>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const PageLink = props => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const _t = t('View.Add', {returnObjects: true});
|
||||||
|
|
||||||
|
const [typeLink, setTypeLink] = useState(1);
|
||||||
|
const textType = typeLink === 1 ? _t.textExternalLink : _t.textSlideInThisPresentation;
|
||||||
|
const changeType = (newType) => {
|
||||||
|
setTypeLink(newType);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [link, setLink] = useState('');
|
||||||
|
|
||||||
|
const [linkTo, setLinkTo] = useState(0);
|
||||||
|
const [displayTo, setDisplayTo] = useState(_t.textNextSlide);
|
||||||
|
const [numberTo, setNumberTo] = useState(0);
|
||||||
|
const changeTo = (type, number) => {
|
||||||
|
setLinkTo(type);
|
||||||
|
switch (type) {
|
||||||
|
case 0 : setDisplayTo(_t.textNextSlide); break;
|
||||||
|
case 1 : setDisplayTo(_t.textPreviousSlide); break;
|
||||||
|
case 2 : setDisplayTo(_t.textFirstSlide); break;
|
||||||
|
case 3 : setDisplayTo(_t.textLastSlide); break;
|
||||||
|
case 4 : setDisplayTo(`${_t.textSlide} ${number + 1}`); setNumberTo(number); break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const display = props.getTextDisplay();
|
||||||
|
const displayDisabled = display !== false && display === null;
|
||||||
|
const [stateDisplay, setDisplay] = useState(display !== false ? ((display !== null) ? display : _t.textDefault) : "");
|
||||||
|
|
||||||
|
const [screenTip, setScreenTip] = useState('');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page>
|
||||||
|
<Navbar title={_t.textLink} backLink={_t.textBack}/>
|
||||||
|
<List inlineLabels className='inputs-list'>
|
||||||
|
<ListItem link={'/add-link-type/'} title={_t.textLinkType} after={textType} routeProps={{
|
||||||
|
changeType: changeType,
|
||||||
|
curType: typeLink
|
||||||
|
}}/>
|
||||||
|
{typeLink === 1 ?
|
||||||
|
<ListInput label={_t.textLink}
|
||||||
|
type="text"
|
||||||
|
placeholder={_t.textLink}
|
||||||
|
value={link}
|
||||||
|
onChange={(event) => {setLink(event.target.value)}}
|
||||||
|
/> :
|
||||||
|
<ListItem link={'/add-link-to/'} title={_t.textLinkTo} after={displayTo} routeProps={{
|
||||||
|
changeTo: changeTo,
|
||||||
|
curTo: linkTo
|
||||||
|
}}/>
|
||||||
|
}
|
||||||
|
<ListInput label={_t.textDisplay}
|
||||||
|
type="text"
|
||||||
|
placeholder={_t.textDisplay}
|
||||||
|
value={stateDisplay}
|
||||||
|
disabled={displayDisabled}
|
||||||
|
onChange={(event) => {setDisplay(event.target.value)}}
|
||||||
|
/>
|
||||||
|
<ListInput label={_t.textScreenTip}
|
||||||
|
type="text"
|
||||||
|
placeholder={_t.textScreenTip}
|
||||||
|
value={screenTip}
|
||||||
|
onChange={(event) => {setScreenTip(event.target.value)}}
|
||||||
|
/>
|
||||||
|
</List>
|
||||||
|
<List>
|
||||||
|
<ListButton title={_t.textInsert}
|
||||||
|
className={`button-fill button-raised${typeLink === 1 && link.length < 1 && ' disabled'}`}
|
||||||
|
onClick={() => {
|
||||||
|
props.onInsertLink(typeLink, (typeLink === 1 ?
|
||||||
|
{url: link, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled } :
|
||||||
|
{linkTo: linkTo, numberTo: numberTo, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</List>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export {PageLink,
|
||||||
|
PageLinkTo,
|
||||||
|
PageTypeLink}
|
|
@ -29,10 +29,10 @@ const PageTable = props => {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const AddOther = props => {
|
const AddOther = props => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const _t = t('View.Add', {returnObjects: true});
|
const _t = t('View.Add', {returnObjects: true});
|
||||||
|
const showInsertLink = props.storeLinkSettings.canAddLink && !props.storeFocusObjects.paragraphLocked;
|
||||||
return (
|
return (
|
||||||
<List>
|
<List>
|
||||||
<ListItem title={_t.textTable} link={'/add-table/'} routeProps={{
|
<ListItem title={_t.textTable} link={'/add-table/'} routeProps={{
|
||||||
|
@ -44,11 +44,17 @@ const AddOther = props => {
|
||||||
<ListItem title={_t.textComment}>
|
<ListItem title={_t.textComment}>
|
||||||
<Icon slot="media" icon="icon-insert-comment"></Icon>
|
<Icon slot="media" icon="icon-insert-comment"></Icon>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
{showInsertLink &&
|
||||||
|
<ListItem title={_t.textLink} link={'/add-link/'}>
|
||||||
|
<Icon slot="media" icon="icon-link"></Icon>
|
||||||
|
</ListItem>
|
||||||
|
}
|
||||||
</List>
|
</List>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const PageAddTable = inject("storeTableSettings")(observer(PageTable));
|
const PageAddTable = inject("storeTableSettings")(observer(PageTable));
|
||||||
|
const AddOtherContainer = inject("storeFocusObjects", "storeLinkSettings")(observer(AddOther));
|
||||||
|
|
||||||
export {AddOther,
|
export {AddOtherContainer as AddOther,
|
||||||
PageAddTable};
|
PageAddTable};
|
Loading…
Reference in a new issue