[DE mobile] Add navigation and correct a table of contents
This commit is contained in:
parent
98ffebb52d
commit
c90c0ac259
|
@ -640,7 +640,10 @@
|
|||
"txtScheme6": "Concourse",
|
||||
"txtScheme7": "Equity",
|
||||
"txtScheme8": "Flow",
|
||||
"txtScheme9": "Foundry"
|
||||
"txtScheme9": "Foundry",
|
||||
"textNavigation": "Navigation",
|
||||
"textEmptyScreens": "There are no headings in the document. Apply a headings style to the text so that it appeas in the table of cotents.",
|
||||
"textBeginningDocument": "Beginning of document"
|
||||
},
|
||||
"Toolbar": {
|
||||
"dlgLeaveMsgText": "You have unsaved changes. Click 'Stay on this Page' to wait for autosave. Click 'Leave this Page' to discard all the unsaved changes.",
|
||||
|
|
|
@ -27,7 +27,6 @@ class EditTableContentsController extends Component {
|
|||
const propsTableContents = api.asc_GetTableOfContentsPr();
|
||||
|
||||
propsTableContents.put_ShowPageNumbers(value);
|
||||
propsTableContents.put_RightAlignTab(value);
|
||||
api.asc_SetTableOfContentsPr(propsTableContents);
|
||||
}
|
||||
|
||||
|
@ -80,6 +79,8 @@ class EditTableContentsController extends Component {
|
|||
}
|
||||
});
|
||||
|
||||
console.log(styles);
|
||||
|
||||
if(props) {
|
||||
let start = props.get_OutlineStart(),
|
||||
end = props.get_OutlineEnd(),
|
||||
|
@ -190,43 +191,22 @@ class EditTableContentsController extends Component {
|
|||
disableOutlines,
|
||||
checkStyles
|
||||
}
|
||||
|
||||
// this.stylesLevels.reset(styles);
|
||||
// if (checkStyles) {
|
||||
// this._forceUpdateOutlineLevels = true;
|
||||
// this.radioStyles.setValue(true);
|
||||
// this.stylesList.scroller.update({alwaysVisibleY: true});
|
||||
// var rec = this.stylesLevels.findWhere({checked: true});
|
||||
// if (rec)
|
||||
// this.stylesList.scrollToRecord(rec);
|
||||
// }
|
||||
}
|
||||
|
||||
addStyles(styleName, value) {
|
||||
const api = Common.EditorApi.get();
|
||||
const propsTableContents = api.asc_GetTableOfContentsPr();
|
||||
|
||||
// propsTableContents.clear_Styles();
|
||||
propsTableContents.add_Style(styleName, value);
|
||||
|
||||
if (propsTableContents.get_StylesCount() > 0) {
|
||||
propsTableContents.put_OutlineRange(-1, -1);
|
||||
} else {
|
||||
propsTableContents.put_OutlineRange(1, 9);
|
||||
}
|
||||
// if (propsTableContents.get_StylesCount() > 0)
|
||||
// propsTableContents.put_OutlineRange(-1, -1);
|
||||
// else
|
||||
// propsTableContents.put_OutlineRange(1, 9);
|
||||
|
||||
// api.asc_SetTableOfContentsPr(propsTableContents);
|
||||
}
|
||||
|
||||
changeCaption(value) {
|
||||
const api = Common.EditorApi.get();
|
||||
const propsTableContents = api.asc_GetTableOfContentsPr();
|
||||
|
||||
if(record) {
|
||||
propsTableContents.put_Caption(value);
|
||||
properties.clear_Styles();
|
||||
api.asc_SetTableOfContentsPr(propsTableContents);
|
||||
}
|
||||
}
|
||||
|
||||
onTableContentsUpdate(type, currentTOC) {
|
||||
const api = Common.EditorApi.get();
|
||||
|
@ -259,7 +239,6 @@ class EditTableContentsController extends Component {
|
|||
onLeader={this.onLeader}
|
||||
onLevelsChange={this.onLevelsChange}
|
||||
fillTOCProps={this.fillTOCProps}
|
||||
changeCaption={this.changeCaption}
|
||||
addStyles={this.addStyles}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import React, { Component } from "react";
|
||||
import Navigation from "../../view/settings/Navigation";
|
||||
import { Device } from '../../../../../common/mobile/utils/device';
|
||||
import { f7, Sheet } from 'framework7-react';
|
||||
|
||||
class NavigationController extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
if (Device.phone) {
|
||||
f7.sheet.close('.settings-popup', false);
|
||||
} else {
|
||||
f7.popover.close('#settings-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onSelectItem(index) {
|
||||
const api = Common.EditorApi.get();
|
||||
const navigationObject = api.asc_ShowDocumentOutline();
|
||||
|
||||
if (navigationObject) {
|
||||
navigationObject.goto(index);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Navigation onSelectItem={this.onSelectItem} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NavigationController
|
|
@ -163,4 +163,21 @@
|
|||
padding: 0 16px;
|
||||
}
|
||||
|
||||
// Navigation
|
||||
|
||||
.empty-screens {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
&__icon {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
&__text {
|
||||
margin: 0 32px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -81,6 +81,16 @@
|
|||
height: 22px;
|
||||
.encoded-svg-mask('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-1 7 22 22" fill="@{brandColor}"><g><path d="M21,18.5c0-0.3-0.1-0.6-0.7-0.9l-2.6-1.2l2.6-1.2c0.6-0.3,0.7-0.6,0.7-0.9c0-0.3-0.1-0.6-0.7-0.9l-8.9-4.1c-0.7-0.4-1.9-0.4-2.8,0l-8.9,4.1C-0.9,13.8-1,14.1-1,14.3s0.1,0.6,0.7,0.9l2.6,1.2l-2.6,1.2C-0.9,18-1,18.4-1,18.5c0,0.2,0.1,0.6,0.7,0.9l2.5,1.2l-2.5,1.2C-0.9,22.1-1,22.5-1,22.7c0,0.3,0.1,0.6,0.7,0.9l8.9,4.1c0.5,0.2,0.8,0.3,1.4,0.3s1-0.1,1.4-0.3l8.9-4.1c0.6-0.4,0.7-0.6,0.7-0.9c0-0.3-0.1-0.6-0.7-0.9l-2.5-1.2l2.5-1.2C20.9,19.2,21,18.8,21,18.5z M-0.2,14.3L-0.2,14.3c0,0,0.1-0.1,0.3-0.2L9,10c0.6-0.3,1.5-0.3,2,0l8.9,4.1c0.2,0.1,0.3,0.2,0.3,0.2l0,0c0,0-0.1,0.1-0.3,0.2L11,18.6c-0.6,0.3-1.5,0.3-2,0l-8.9-4.1C-0.1,14.4-0.2,14.3-0.2,14.3z M20.2,22.7L20.2,22.7c0,0-0.1,0.1-0.3,0.2L11,27.1c-0.6,0.3-1.5,0.3-2,0l-8.9-4.1c-0.2-0.1-0.3-0.2-0.3-0.2l0,0c0,0,0.1-0.1,0.3-0.2l3-1.5l5.5,2.6c0.7,0.4,1.9,0.4,2.8,0l5.5-2.6l3,1.5C20.1,22.7,20.2,22.7,20.2,22.7z M19.9,18.7L11,22.8c-0.6,0.3-1.5,0.3-2,0l-8.9-4.1c-0.2-0.1-0.3-0.2-0.3-0.2l0,0c0,0,0.1-0.1,0.3-0.2l3-1.5l5.5,2.6c0.7,0.4,1.9,0.4,2.8,0l5.5-2.6l3,1.5c0.2,0.1,0.3,0.2,0.3,0.2l0,0C20.2,18.5,20.1,18.6,19.9,18.7z"/></g></svg>');
|
||||
}
|
||||
&.icon-navigation {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
.encoded-svg-mask('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M16 4H2V5H16V4Z" fill="@{brandColor}"/><path d="M19 9H5V10H19V9Z" fill="@{brandColor}"/><path d="M23 14V15H9V14H23Z" fill="@{brandColor}" /><path d="M16 20V19H2V20H16Z" fill="@{brandColor}"/></svg>')
|
||||
}
|
||||
&.icon-empty-screens {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
.encoded-svg-background('<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_876_40308)"><path d="M176.406 41.5727V47.1081M179.247 44.3397H173.566M193.447 82.6943V86.6484M195.477 84.6716H191.418M149.804 13.5V21.4068M153.861 17.4542H145.746M43.3426 37.0267V43.3521M46.5888 40.1895H40.0967M33.7747 50.4702V55.2143M36.2084 52.843H31.3394M15.1078 89.0626V92.2253M16.7309 90.644H13.4849M4.55885 97.762V105.669M8.6156 101.716H0.500488" stroke="#3C3C43" stroke-opacity="0.3" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round"/><rect x="4" y="188" width="4" height="2" rx="1" fill="#3C3C43" fill-opacity="0.3"/><rect x="10" y="188" width="12" height="2" rx="1" fill="#3C3C43" fill-opacity="0.3"/><rect x="183" y="188" width="10" height="2" rx="1" fill="#3C3C43" fill-opacity="0.3"/><rect x="196" y="188" width="10" height="2" rx="1" fill="#3C3C43" fill-opacity="0.3"/><rect x="26" y="188" width="152" height="2" rx="1" fill="#3C3C43" fill-opacity="0.3"/><rect x="68" y="71" width="64" height="4" fill="#3C3C43" fill-opacity="0.3"/><rect x="68" y="160" width="64" height="4" fill="#3C3C43" fill-opacity="0.3"/><circle cx="100" cy="174" r="6.5" stroke="#3C3C43" stroke-opacity="0.3" stroke-width="3"/><rect x="88" y="64" width="14" height="3" rx="1.5" fill="#3C3C43" fill-opacity="0.3"/><rect x="104" y="64" width="8" height="3" rx="1.5" fill="#3C3C43" fill-opacity="0.3"/><path d="M77 95.5C77 94.6716 77.6716 94 78.5 94H115.5C116.328 94 117 94.6716 117 95.5C117 96.3284 116.328 97 115.5 97H78.5C77.6716 97 77 96.3284 77 95.5Z" fill="#3C3C43" fill-opacity="0.3"/><path d="M77 105.5C77 104.672 77.6716 104 78.5 104H99.5C100.328 104 101 104.672 101 105.5C101 106.328 100.328 107 99.5 107H78.5C77.6716 107 77 106.328 77 105.5Z" fill="#3C3C43" fill-opacity="0.3"/><path d="M77 115.5C77 114.672 77.6716 114 78.5 114H115.5C116.328 114 117 114.672 117 115.5C117 116.328 116.328 117 115.5 117H78.5C77.6716 117 77 116.328 77 115.5Z" fill="#3C3C43" fill-opacity="0.3"/><path d="M77 125.5C77 124.672 77.6716 124 78.5 124H107.5C108.328 124 109 124.672 109 125.5C109 126.328 108.328 127 107.5 127H78.5C77.6716 127 77 126.328 77 125.5Z" fill="#3C3C43" fill-opacity="0.3"/><circle cx="121.5" cy="95.5" r="1.5" fill="#3C3C43" fill-opacity="0.3"/><circle cx="121.5" cy="105.5" r="1.5" fill="#3C3C43" fill-opacity="0.3"/><circle cx="121.5" cy="115.5" r="1.5" fill="#3C3C43" fill-opacity="0.3"/><circle cx="121.5" cy="125.5" r="1.5" fill="#3C3C43" fill-opacity="0.3"/><rect x="66" y="58" width="68" height="128" rx="8" stroke="#3C3C43" stroke-opacity="0.3" stroke-width="4"/></g><defs><clipPath id="clip0_876_40308"><rect width="200" height="200" fill="white"/></clipPath></defs></svg>')
|
||||
}
|
||||
|
||||
// Download
|
||||
|
||||
|
|
|
@ -141,6 +141,11 @@
|
|||
height: 24px;
|
||||
.encoded-svg-mask('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 13" fill="@{brandColor}"><path fill-rule="evenodd" clip-rule="evenodd" d="M17 0H0V1H17V0ZM11.9 4H0V5H11.9V4ZM0 8H17V9H0V8ZM15 12H0V13H15V12Z"/><path fill-rule="evenodd" clip-rule="evenodd" d="M20 0H19V1H20V0ZM20 4H19V5H20V4ZM19 8H20V9H19V8ZM20 12H19V13H20V12Z"/></svg>');
|
||||
}
|
||||
&.icon-navigation {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
.encoded-svg-mask('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M16 4H2V5H16V4Z" fill="@{brandColor}"/><path d="M19 9H5V10H19V9Z" fill="@{brandColor}"/><path d="M23 14V15H9V14H23Z" fill="@{brandColor}" /><path d="M16 20V19H2V20H16Z" fill="@{brandColor}"/></svg>')
|
||||
}
|
||||
|
||||
// Download
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const EditTableContents = props => {
|
|||
const _t = t('Edit', {returnObjects: true});
|
||||
const api = Common.EditorApi.get();
|
||||
const propsTableContents = api.asc_GetTableOfContentsPr();
|
||||
const count = propsTableContents.get_StylesCount();
|
||||
const stylesCount = propsTableContents.get_StylesCount();
|
||||
console.log(propsTableContents);
|
||||
const [type, setType] = useState(0);
|
||||
const [styleValue, setStyleValue] = useState(propsTableContents.get_StylesType());
|
||||
|
@ -103,7 +103,7 @@ const EditTableContents = props => {
|
|||
setLeaderValue
|
||||
}}></ListItem>
|
||||
}
|
||||
<ListItem title={t('Edit.textStructure')} link="/edit-structure-table-contents/" after={count ? t('Edit.textStyles') : t('Edit.textLevels')} routeProps={{
|
||||
<ListItem title={t('Edit.textStructure')} link="/edit-structure-table-contents/" after={stylesCount ? t('Edit.textStyles') : t('Edit.textLevels')} routeProps={{
|
||||
onLevelsChange: props.onLevelsChange,
|
||||
fillTOCProps: props.fillTOCProps,
|
||||
addStyles: props.addStyles
|
||||
|
|
140
apps/documenteditor/mobile/src/view/settings/Navigation.jsx
Normal file
140
apps/documenteditor/mobile/src/view/settings/Navigation.jsx
Normal file
|
@ -0,0 +1,140 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Device } from '../../../../../common/mobile/utils/device';
|
||||
import {f7, View, List, ListItem, Icon, Row, Button, Page, Navbar, NavRight, Segmented, BlockTitle, Link, ListButton, Toggle, Actions, ActionsButton, ActionsGroup, Sheet} from 'framework7-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const Navigation = props => {
|
||||
const { t } = useTranslation();
|
||||
const _t = t('Settings', {returnObjects: true});
|
||||
const android = Device.android;
|
||||
const api = Common.EditorApi.get();
|
||||
const navigationObject = api.asc_ShowDocumentOutline();
|
||||
const count = navigationObject.get_ElementsCount();
|
||||
const [currentPosition, setCurrentPosition] = useState(navigationObject.get_CurrentPosition());
|
||||
const arrHeaders = [];
|
||||
|
||||
const updateNavigation = () => {
|
||||
if (!navigationObject) return;
|
||||
|
||||
let prevLevel = -1,
|
||||
headerLevel = -1,
|
||||
firstHeader = !navigationObject.isFirstItemNotHeader();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
let level = navigationObject.get_Level(i),
|
||||
hasParent = true;
|
||||
if (level > prevLevel && i > 0)
|
||||
arrHeaders[i - 1]['hasSubItems'] = true;
|
||||
if (headerLevel < 0 || level <= headerLevel) {
|
||||
if (i > 0 || firstHeader)
|
||||
headerLevel = level;
|
||||
hasParent = false;
|
||||
}
|
||||
|
||||
arrHeaders.push({
|
||||
name: navigationObject.get_Text(i),
|
||||
level: level,
|
||||
index: i,
|
||||
hasParent: hasParent,
|
||||
isEmptyItem: navigationObject.isEmptyItem(i)
|
||||
});
|
||||
|
||||
prevLevel = level;
|
||||
}
|
||||
|
||||
if (count > 0 && !firstHeader) {
|
||||
arrHeaders[0]['hasSubItems'] = false;
|
||||
arrHeaders[0]['isNotHeader'] = true;
|
||||
arrHeaders[0]['name'] = t('Settings.textBeginningDocument');
|
||||
}
|
||||
}
|
||||
|
||||
updateNavigation();
|
||||
// console.log(navigationObject);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Navbar title={t('Settings.textNavigation')} backLink={_t.textBack} />
|
||||
{!arrHeaders.length
|
||||
?
|
||||
<div className="empty-screens">
|
||||
{!android &&
|
||||
<div className="empty-screens__icon">
|
||||
<Icon slot="media" icon="icon-empty-screens"></Icon>
|
||||
</div>
|
||||
}
|
||||
<p className="empty-screens__text">{t('Settings.textEmptyScreens')}</p>
|
||||
</div>
|
||||
:
|
||||
<List>
|
||||
{arrHeaders.map((header, index) => {
|
||||
return (
|
||||
<ListItem radio key={index} title={header.name} checked={header.index === currentPosition} style={{paddingLeft: header.level * 16}} onClick={() => {
|
||||
setCurrentPosition(header.index);
|
||||
props.onSelectItem(header.index);
|
||||
}}></ListItem>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
}
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
const NavigationSheet = () => {
|
||||
useEffect(() => {
|
||||
f7.sheet.open('#view-navigation-sheet');
|
||||
});
|
||||
|
||||
const [stateHeight, setHeight] = useState('45%');
|
||||
const [stateOpacity, setOpacity] = useState(1);
|
||||
|
||||
const [stateStartY, setStartY] = useState();
|
||||
const [isNeedClose, setNeedClose] = useState(false);
|
||||
|
||||
const handleTouchStart = (event) => {
|
||||
const touchObj = event.changedTouches[0];
|
||||
setStartY(parseInt(touchObj.clientY));
|
||||
};
|
||||
|
||||
const handleTouchMove = (event) => {
|
||||
const touchObj = event.changedTouches[0];
|
||||
const dist = parseInt(touchObj.clientY) - stateStartY;
|
||||
|
||||
if (dist < 0) { // to top
|
||||
setHeight('90%');
|
||||
setOpacity(1);
|
||||
setNeedClose(false);
|
||||
} else if (dist < 80) {
|
||||
setHeight('45%');
|
||||
setOpacity(1);
|
||||
setNeedClose(false);
|
||||
} else {
|
||||
setNeedClose(true);
|
||||
setOpacity(0.6);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTouchEnd = (event) => {
|
||||
const touchObj = event.changedTouches[0];
|
||||
const swipeEnd = parseInt(touchObj.clientY);
|
||||
const dist = swipeEnd - stateStartY;
|
||||
|
||||
if (isNeedClose) {
|
||||
closeCurComments();
|
||||
} else if (stateHeight === '90%' && dist > 20) {
|
||||
setHeight('45%');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Sheet id='view-navigation-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}>
|
||||
<div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
|
||||
<Icon icon='icon-swipe' />
|
||||
</div>
|
||||
<Navigation />
|
||||
</Sheet>
|
||||
)
|
||||
};
|
||||
|
||||
export default Navigation;
|
|
@ -12,6 +12,7 @@ import ApplicationSettingsController from "../../controller/settings/Application
|
|||
import { DocumentFormats, DocumentMargins, DocumentColorSchemes } from "./DocumentSettings";
|
||||
import { MacrosSettings } from "./ApplicationSettings";
|
||||
import About from '../../../../../common/mobile/lib/view/About';
|
||||
import NavigationController from '../../controller/settings/Navigation';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
|
@ -53,6 +54,13 @@ const routes = [
|
|||
{
|
||||
path: '/about/',
|
||||
component: About
|
||||
},
|
||||
|
||||
// Navigation
|
||||
|
||||
{
|
||||
path: '/navigation/',
|
||||
component: NavigationController
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -121,6 +129,9 @@ const SettingsList = inject("storeAppOptions", "storeReview")(observer(props =>
|
|||
<Icon slot="media" icon="icon-search"></Icon>
|
||||
</ListItem>
|
||||
}
|
||||
<ListItem title={t('Settings.textNavigation')} link="#" onClick={onoptionclick.bind(this, "/navigation/")}>
|
||||
<Icon slot="media" icon="icon-navigation"></Icon>
|
||||
</ListItem>
|
||||
{window.matchMedia("(max-width: 359px)").matches ?
|
||||
<ListItem title={_t.textCollaboration} link="#" onClick={onOpenCollaboration} className='no-indicator'>
|
||||
<Icon slot="media" icon="icon-collaboration"></Icon>
|
||||
|
|
Loading…
Reference in a new issue