diff --git a/apps/common/mobile/lib/controller/Search.jsx b/apps/common/mobile/lib/controller/Search.jsx
new file mode 100644
index 0000000000..fa60859ecc
--- /dev/null
+++ b/apps/common/mobile/lib/controller/Search.jsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import SearchView, {SearchSettingsView} from '../view/Search'
+
+
+const SearchController = props => {
+ const onSearchQuery = params => {
+ console.log('on search: ' + params);
+ };
+
+ return
+};
+
+export {SearchController, SearchView, SearchSettingsView};
diff --git a/apps/common/mobile/lib/view/Search.jsx b/apps/common/mobile/lib/view/Search.jsx
new file mode 100644
index 0000000000..51bca9ca58
--- /dev/null
+++ b/apps/common/mobile/lib/view/Search.jsx
@@ -0,0 +1,226 @@
+import React, { Component } from 'react';
+import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react';
+import { Toggle } from 'framework7-react';
+import { f7 } from 'framework7-react';
+import { Dom7 } from 'framework7';
+import { Device } from '../../../../common/mobile/utils/device';
+import { observable } from "mobx";
+import { observer } from "mobx-react";
+
+const searchOptions = observable({
+ usereplace: false
+});
+
+const popoverStyle = {
+ height: '300px'
+};
+
+const SEARCH_BACKWARD = 'back';
+const SEARCH_FORWARD = 'next';
+
+class SearchSettingsView extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ useReplace: false,
+ caseSensitive: false,
+ markResults: false
+ };
+ }
+
+ onFindReplaceClick(action) {
+ searchOptions.usereplace = action == 'replace';
+ this.setState({
+ useReplace: searchOptions.usereplace
+ });
+
+
+ if (this.onReplaceChecked) {}
+ }
+
+ extraSearchOptions() {
+ }
+
+ render() {
+ const show_popover = true;
+ const navbar =
+
+ {!show_popover &&
+
+ Done
+ }
+ ;
+ const extra = this.extraSearchOptions();
+ const content =
+
+
+ {navbar}
+
+ this.onFindReplaceClick('find')} />
+ this.onFindReplaceClick('replace')} />
+
+ { extra }
+
+ ;
+ return (
+ show_popover ?
+ {content} :
+ {content}
+ )
+ }
+}
+
+@observer
+class SearchView extends Component {
+ constructor(props) {
+ super(props);
+
+ $$(document).on('page:init', (e, page) => {
+ if ( page.name == 'home' ) {
+ this.searchbar = f7.searchbar.create({
+ el: '.searchbar',
+ customSearch: true,
+ expandable: true,
+ backdrop: false,
+ on: {
+ search: (bar, curval, prevval) => {
+ },
+ enable: this.onSearchbarShow.bind(this, true),
+ disable: this.onSearchbarShow.bind(this, false)
+ }
+ });
+
+ // function iOSVersion() {
+ // var ua = navigator.userAgent;
+ // var m;
+ // return (m = /(iPad|iPhone|iphone).*?(OS |os |OS\_)(\d+((_|\.)\d)?((_|\.)\d)?)/.exec(ua)) ? parseFloat(m[3]) : 0;
+ // }
+
+ const $$ = Dom7;
+ const $editor = $$('#editor_sdk');
+ if (false /*iOSVersion() < 13*/) {
+ // $editor.single('mousedown touchstart', _.bind(me.onEditorTouchStart, me));
+ // $editor.single('mouseup touchend', _.bind(me.onEditorTouchEnd, me));
+ } else {
+ // $editor.single('pointerdown', this.onEditorTouchStart, me));
+ // $editor.single('pointerup', _.bind(me.onEditorTouchEnd, me));
+ }
+
+ $editor.on('pointerdown', this.onEditorTouchStart.bind(this));
+ $editor.on('pointerup', this.onEditorTouchEnd.bind(this));
+ }
+ });
+
+ this.onSettingsClick = this.onSettingsClick.bind(this);
+ this.onSearchClick = this.onSearchClick.bind(this);
+ }
+
+ componentDidMount(){
+ const $$ = Dom7;
+ this.$repalce = $$('#idx-replace-val');
+ }
+
+ onSettingsClick(e) {
+ if ( Device.phone ) {
+ // f7.popup.open('.settings-popup');
+ } else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings');
+ }
+
+ searchParams() {
+ let params = {
+ find: this.searchbar.query
+ };
+
+ if ( searchOptions.usereplace )
+ params.replace = this.$replace.val();
+
+ return params;
+ }
+
+ onSearchClick(action) {
+ if ( this.searchbar && this.searchbar.query) {
+ if ( this.props.onSearchQuery ) {
+ let params = this.searchParams();
+ params.forward = action != SEARCH_BACKWARD;
+
+ this.props.onSearchQuery(params);
+ }
+ }
+ }
+
+ onSearchbarShow(isshowed, bar) {
+ if ( !isshowed ) {
+ this.$repalce.val('');
+ }
+ }
+
+ onEditorTouchStart(e) {
+ this.startPoint = this.pointerPosition(e);
+ }
+
+ onEditorTouchEnd(e) {
+ const endPoint = this.pointerPosition(e);
+
+ if ( this.searchbar.enabled ) {
+ const distance = (this.startPoint.x === undefined || this.startPoint.y === undefined) ? 0 :
+ Math.sqrt((endPoint.x -= this.startPoint.x) * endPoint.x + (endPoint.y -= this.startPoint.y) * endPoint.y);
+
+ if ( distance < 1 ) {
+ this.searchbar.disable();
+ }
+ }
+ }
+
+ pointerPosition(e) {
+ let out = {x:0, y:0};
+ if ( e.type == 'touchstart' || e.type == 'touchend' ) {
+ const touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
+ out.x = touch.pageX;
+ out.y = touch.pageY;
+ } else
+ if ( e.type == 'mousedown' || e.type == 'mouseup' ) {
+ out.x = e.pageX;
+ out.y = e.pageY;
+ }
+
+ return out;
+ }
+
+ render() {
+ const usereplace = searchOptions.usereplace;
+ const hidden = {display: "none"};
+ return (
+
+ )
+ }
+}
+
+export {SearchView as default, SearchView, SearchSettingsView};
diff --git a/apps/common/mobile/resources/less/common-ios.less b/apps/common/mobile/resources/less/common-ios.less
index ee582bc7be..b153c61c51 100644
--- a/apps/common/mobile/resources/less/common-ios.less
+++ b/apps/common/mobile/resources/less/common-ios.less
@@ -153,14 +153,24 @@
}
}
- .popover li:last-child {
- .segmented a {
- &:first-child {
- border-radius: var(--f7-button-border-radius) 0 0 var(--f7-button-border-radius);
- }
+ .popover {
+ li:last-child {
+ .segmented a {
+ &:first-child {
+ border-radius: var(--f7-button-border-radius) 0 0 var(--f7-button-border-radius);
+ }
- &:last-child {
- border-radius: 0 var(--f7-button-border-radius) var(--f7-button-border-radius) 0;
+ &:last-child {
+ border-radius: 0 var(--f7-button-border-radius) var(--f7-button-border-radius) 0;
+ }
+ }
+ }
+
+ .page-content {
+ > .list {
+ &:last-child {
+ margin-bottom: 30px;
+ }
}
}
}
@@ -366,8 +376,8 @@
}
}
- .dataview, #add-table, #add-shape {
- &.page-content {
+ .dataview, #add-table, #add-shape, #add-slide {
+ &.page-content, .page-content {
background-color: @white;
}
}
diff --git a/apps/common/mobile/resources/less/common-material.less b/apps/common/mobile/resources/less/common-material.less
index dab99d7c26..18af81ee12 100644
--- a/apps/common/mobile/resources/less/common-material.less
+++ b/apps/common/mobile/resources/less/common-material.less
@@ -165,10 +165,10 @@
}
}
&.inputs-list {
- .item-input {
+ .item-input, .item-link {
.item-inner {
display: block;
- .item-label {
+ .item-title, .item-label {
width: 100%;
font-size: 12px;
}
diff --git a/apps/common/mobile/resources/less/search.less b/apps/common/mobile/resources/less/search.less
index ab694cea8d..21249b9414 100644
--- a/apps/common/mobile/resources/less/search.less
+++ b/apps/common/mobile/resources/less/search.less
@@ -13,4 +13,8 @@
.hairline(bottom, @statusBarBorderColor);
}
}
+
+ .searchbar-input-wrap {
+ margin-right: 10px;
+ }
}
diff --git a/apps/common/mobile/resources/less/variables.less b/apps/common/mobile/resources/less/variables.less
new file mode 100644
index 0000000000..2ba2c9402e
--- /dev/null
+++ b/apps/common/mobile/resources/less/variables.less
@@ -0,0 +1,3 @@
+
+@border-regular-control: #cbcbcb;
+@text-normal: #000;
diff --git a/apps/documenteditor/mobile/src/controller/Search.jsx b/apps/documenteditor/mobile/src/controller/Search.jsx
index 6c662c5f3c..99ac30ccc7 100644
--- a/apps/documenteditor/mobile/src/controller/Search.jsx
+++ b/apps/documenteditor/mobile/src/controller/Search.jsx
@@ -1,8 +1,75 @@
import React from 'react';
-import SearchView, {SearchSettingsView} from '../view/Search'
+import { List, ListItem, Toggle } from 'framework7-react';
+import { SearchController, SearchView, SearchSettingsView } from '../../../../common/mobile/lib/controller/Search';
+import { f7 } from 'framework7-react';
-const SearchController = props => {
- return
+
+class SearchSettings extends SearchSettingsView {
+ constructor(props) {
+ super(props);
+
+ this.onToggleMarkResults = this.onToggleMarkResults.bind(this);
+ }
+
+ onToggleMarkResults(checked) {
+ const api = Common.EditorApi.get();
+ api.asc_selectSearchingResults(checked);
+ }
+
+ extraSearchOptions() {
+ const anc_markup = super.extraSearchOptions();
+
+ const markup =
+
+
+
+
+
+
+
;
+
+ return {...anc_markup, ...markup};
+ }
+}
+
+class DESearchView extends SearchView {
+ searchParams() {
+ let params = super.searchParams();
+
+ const checkboxCaseSensitive = f7.toggle.get('.toggle-case-sensitive'),
+ checkboxMarkResults = f7.toggle.get('.toggle-mark-results');
+ const searchOptions = {
+ caseSensitive: checkboxCaseSensitive.checked,
+ highlight: checkboxMarkResults.checked
+ };
+
+ return {...params, ...searchOptions};
+ }
+
+ onSearchbarShow(isshowed, bar) {
+ super.onSearchbarShow(isshowed, bar);
+
+ const api = Common.EditorApi.get();
+ if ( isshowed ) {
+ const checkboxMarkResults = f7.toggle.get('.toggle-mark-results');
+ api.asc_selectSearchingResults(checkboxMarkResults.checked);
+ } else api.asc_selectSearchingResults(false);
+ }
+}
+
+const Search = props => {
+ const onSearchQuery = params => {
+ const api = Common.EditorApi.get();
+
+ if ( !params.replace ) {
+ if ( !api.asc_findText(params.find, params.forward, params.caseSensitive, params.highlight) ) {
+ f7.dialog.alert('there are no more results', e => {
+ });
+ }
+ }
+ };
+
+ return
};
-export {SearchController as Search, SearchSettingsView as SearchSettings};
+export {Search, SearchSettings}
diff --git a/apps/documenteditor/mobile/src/view/Search.jsx b/apps/documenteditor/mobile/src/view/Search.jsx
deleted file mode 100644
index c5c01ac652..0000000000
--- a/apps/documenteditor/mobile/src/view/Search.jsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import React, { Component } from 'react';
-import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react';
-import { f7ready, f7 } from 'framework7-react';
-import { Device } from '../../../../common/mobile/utils/device';
-
-const popoverStyle = {
- height: '300px'
-};
-
-class SearchSettingsView extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- useReplace: false,
- caseSensitive: false,
- markResults: false
- };
- }
-
- onFindReplaceClick(action) {
- this.setState({
- useReplace: action == 'replace'
- });
- }
-
- render() {
- const show_popover = true;
- const navbar =
-
- {!show_popover &&
-
- Done
- }
- ;
- const content =
-
-
- {navbar}
-
- this.onFindReplaceClick('find')}>
- this.onFindReplaceClick('replace')}>
-
-
- ;
- return (
- show_popover ?
- {content} :
- {content}
- )
- }
-}
-
-class SearchView extends Component {
- constructor(props) {
- super(props);
-
- $$(document).on('page:init', (e, page) => {
- if ( page.name == 'home' ) {
- f7.searchbar.create({
- el: '.searchbar',
- customSearch: true,
- expandable: true,
- backdrop: false,
- on: {
- search: (bar, curval, prevval) => {
- console.log('on search results ' + curval);
- }
- }
- });
- }
- });
-
- this.onSettingsClick = this.onSettingsClick.bind(this);
- }
-
- componentDidMount(){
- }
-
- onSettingsClick(e) {
- if ( Device.phone ) {
- // f7.popup.open('.settings-popup');
- } else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings');
- }
-
- render() {
- return (
-
- )
- }
-}
-
-export {SearchView as default, SearchSettingsView};
diff --git a/apps/documenteditor/mobile/src/view/search.jsx b/apps/documenteditor/mobile/src/view/search.jsx
deleted file mode 100644
index c5c01ac652..0000000000
--- a/apps/documenteditor/mobile/src/view/search.jsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import React, { Component } from 'react';
-import { Searchbar, Popover, Popup, View, Page, List, ListItem, Navbar, NavRight, Link } from 'framework7-react';
-import { f7ready, f7 } from 'framework7-react';
-import { Device } from '../../../../common/mobile/utils/device';
-
-const popoverStyle = {
- height: '300px'
-};
-
-class SearchSettingsView extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- useReplace: false,
- caseSensitive: false,
- markResults: false
- };
- }
-
- onFindReplaceClick(action) {
- this.setState({
- useReplace: action == 'replace'
- });
- }
-
- render() {
- const show_popover = true;
- const navbar =
-
- {!show_popover &&
-
- Done
- }
- ;
- const content =
-
-
- {navbar}
-
- this.onFindReplaceClick('find')}>
- this.onFindReplaceClick('replace')}>
-
-
- ;
- return (
- show_popover ?
- {content} :
- {content}
- )
- }
-}
-
-class SearchView extends Component {
- constructor(props) {
- super(props);
-
- $$(document).on('page:init', (e, page) => {
- if ( page.name == 'home' ) {
- f7.searchbar.create({
- el: '.searchbar',
- customSearch: true,
- expandable: true,
- backdrop: false,
- on: {
- search: (bar, curval, prevval) => {
- console.log('on search results ' + curval);
- }
- }
- });
- }
- });
-
- this.onSettingsClick = this.onSettingsClick.bind(this);
- }
-
- componentDidMount(){
- }
-
- onSettingsClick(e) {
- if ( Device.phone ) {
- // f7.popup.open('.settings-popup');
- } else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings');
- }
-
- render() {
- return (
-
- )
- }
-}
-
-export {SearchView as default, SearchSettingsView};
diff --git a/apps/documenteditor/mobile/src/view/settings/ApplicationSettings.jsx b/apps/documenteditor/mobile/src/view/settings/ApplicationSettings.jsx
index 9a3a800600..9561950344 100644
--- a/apps/documenteditor/mobile/src/view/settings/ApplicationSettings.jsx
+++ b/apps/documenteditor/mobile/src/view/settings/ApplicationSettings.jsx
@@ -39,8 +39,7 @@ const PageApplicationSettings = props => {
onChange={() => changeMeasureSettings(2)}>
-
- {_t.textSpellcheck}
+
{
store.changeSpellCheck(!isSpellChecking);
@@ -50,8 +49,7 @@ const PageApplicationSettings = props => {
- {/*ToDo: if (DisplayMode == "final" || DisplayMode == "original") {disabled} */}
- {_t.textNoCharacters}
+ {/*ToDo: if (DisplayMode == "final" || DisplayMode == "original") {disabled} */}
{
store.changeNoCharacters(!isNonprintingCharacters);
@@ -59,8 +57,7 @@ const PageApplicationSettings = props => {
}}
/>
- {/*ToDo: if (DisplayMode == "final" || DisplayMode == "original") {disabled} */}
- {_t.textHiddenTableBorders}
+ {/*ToDo: if (DisplayMode == "final" || DisplayMode == "original") {disabled} */}
{
store.changeShowTableEmptyLine(!isHiddenTableBorders);
@@ -73,17 +70,15 @@ const PageApplicationSettings = props => {
}
{_t.textCommentsDisplay}
-
- {_t.textComments}
-
+ {
store.changeDisplayComments(!isComments);
props.switchDisplayComments(!isComments);
}}
/>
-
- {_t.textResolvedComments}
+
{
store.changeDisplayResolved(!isResolvedComments);
diff --git a/apps/presentationeditor/mobile/locale/en.json b/apps/presentationeditor/mobile/locale/en.json
index ea3358380b..7207ffc45a 100644
--- a/apps/presentationeditor/mobile/locale/en.json
+++ b/apps/presentationeditor/mobile/locale/en.json
@@ -77,7 +77,37 @@
"textSlide": "Slide",
"textShape": "Shape",
"textImage": "Image",
- "textOther": "Other"
+ "textOther": "Other",
+ "textPictureFromLibrary": "Picture from Library",
+ "textPictureFromURL": "Picture from URL",
+ "textLinkSettings": "LinkSettings",
+ "textBack": "Back",
+ "textEmptyImgUrl": "You need to specify image URL.",
+ "txtNotUrl": "This field should be a URL in the format \"http://www.example.com\"",
+ "notcriticalErrorTitle": "Warning",
+ "textAddress": "Address",
+ "textImageURL": "Image URL",
+ "textInsertImage": "Insert Image",
+ "textTable": "Table",
+ "textComment": "Comment",
+ "textTableSize": "Table Size",
+ "textColumns": "Columns",
+ "textRows": "Rows",
+ "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": {
"textText": "Text",
diff --git a/apps/presentationeditor/mobile/src/controller/Main.jsx b/apps/presentationeditor/mobile/src/controller/Main.jsx
index 902dca3d77..ef2b7aa65d 100644
--- a/apps/presentationeditor/mobile/src/controller/Main.jsx
+++ b/apps/presentationeditor/mobile/src/controller/Main.jsx
@@ -5,7 +5,11 @@ import { f7 } from "framework7-react";
import { withTranslation } from 'react-i18next';
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
+<<<<<<< HEAD
@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings", "storeTableSettings", "storeChartSettings")
+=======
+@inject("storeFocusObjects", "storeAppOptions", "storePresentationInfo", "storePresentationSettings", "storeSlideSettings", "storeTextSettings", "storeTableSettings", "storeLinkSettings")
+>>>>>>> feature/mobile-apps-on-reactjs
class MainController extends Component {
constructor(props) {
super(props)
diff --git a/apps/presentationeditor/mobile/src/controller/add/AddImage.jsx b/apps/presentationeditor/mobile/src/controller/add/AddImage.jsx
new file mode 100644
index 0000000000..4aafae09b1
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/controller/add/AddImage.jsx
@@ -0,0 +1,59 @@
+import React, {Component} from 'react';
+import { f7 } from 'framework7-react';
+import {Device} from '../../../../../common/mobile/utils/device';
+import { withTranslation} from 'react-i18next';
+
+import {AddImage} from '../../view/add/AddImage';
+
+class AddImageController extends Component {
+ constructor (props) {
+ super(props);
+ this.onInsertByFile = this.onInsertByFile.bind(this);
+ this.onInsertByUrl = this.onInsertByUrl.bind(this);
+ }
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ onInsertByFile () {
+ const api = Common.EditorApi.get();
+ api.asc_addImage();
+ this.closeModal();
+ }
+
+ onInsertByUrl (value) {
+ const { t } = this.props;
+ const _t = t("View.Add", { returnObjects: true });
+
+ const _value = value.replace(/ /g, '');
+
+ if (_value) {
+ if ((/((^https?)|(^ftp)):\/\/.+/i.test(_value))) {
+ this.closeModal();
+ const api = Common.EditorApi.get();
+ api.AddImageUrl(_value);
+ } else {
+ f7.dialog.alert(_t.txtNotUrl, _t.notcriticalErrorTitle);
+ }
+ } else {
+ f7.dialog.alert(_t.textEmptyImgUrl, _t.notcriticalErrorTitle);
+ }
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+const AddImageWithTranslation = withTranslation()(AddImageController);
+
+export {AddImageWithTranslation as AddImageController};
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/controller/add/AddLink.jsx b/apps/presentationeditor/mobile/src/controller/add/AddLink.jsx
new file mode 100644
index 0000000000..e9e9ba81a6
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/controller/add/AddLink.jsx
@@ -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 (
+
+ )
+ }
+}
+
+const AddLinkWithTranslation = withTranslation()(AddLinkController);
+
+export {AddLinkWithTranslation as AddLinkController};
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/controller/add/AddOther.jsx b/apps/presentationeditor/mobile/src/controller/add/AddOther.jsx
new file mode 100644
index 0000000000..e2838493e9
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/controller/add/AddOther.jsx
@@ -0,0 +1,102 @@
+import React, {Component} from 'react';
+import { f7 } from 'framework7-react';
+import {Device} from '../../../../../common/mobile/utils/device';
+import { withTranslation} from 'react-i18next';
+
+import {AddOther} from '../../view/add/AddOther';
+
+class AddOtherController extends Component {
+ constructor (props) {
+ super(props);
+ this.onStyleClick = this.onStyleClick.bind(this);
+ this.initStyleTable = this.initStyleTable.bind(this);
+
+ this.initTable = false;
+ }
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ initStyleTable () {
+ if (!this.initTable) {
+ const api = Common.EditorApi.get();
+ api.asc_GetDefaultTableStyles();
+ this.initTable = true;
+ }
+ }
+
+ onStyleClick (type) {
+ const api = Common.EditorApi.get();
+
+ this.closeModal();
+
+ const { t } = this.props;
+ const _t = t("View.Add", { returnObjects: true });
+
+ let picker;
+
+ const dialog = f7.dialog.create({
+ title: _t.textTableSize,
+ text: '',
+ content:
+ '' +
+ '
' +
+ '
' + _t.textColumns + '
' +
+ '
' + _t.textRows + '
' +
+ '
' +
+ '
' +
+ '
',
+ buttons: [
+ {
+ text: _t.textCancel
+ },
+ {
+ text: 'OK',
+ bold: true,
+ onClick: function () {
+ const size = picker.value;
+
+ api.put_Table(parseInt(size[0]), parseInt(size[1]), undefined, type.toString());
+ }
+ }
+ ]
+ }).open();
+ dialog.on('opened', () => {
+ picker = f7.picker.create({
+ containerEl: document.getElementById('picker-table-size'),
+ cols: [
+ {
+ textAlign: 'center',
+ width: '100%',
+ values: [1,2,3,4,5,6,7,8,9,10]
+ },
+ {
+ textAlign: 'center',
+ width: '100%',
+ values: [1,2,3,4,5,6,7,8,9,10]
+ }
+ ],
+ toolbar: false,
+ rotateEffect: true,
+ value: [3, 3]
+ });
+ });
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+const AddOtherWithTranslation = withTranslation()(AddOtherController);
+
+export {AddOtherWithTranslation as AddOtherController};
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/controller/add/AddShape.jsx b/apps/presentationeditor/mobile/src/controller/add/AddShape.jsx
index bf649dc1d4..74d3cdd5df 100644
--- a/apps/presentationeditor/mobile/src/controller/add/AddShape.jsx
+++ b/apps/presentationeditor/mobile/src/controller/add/AddShape.jsx
@@ -3,15 +3,31 @@ import { f7 } from 'framework7-react';
import {Device} from '../../../../../common/mobile/utils/device';
import {observer, inject} from "mobx-react";
-import { AddShape } from '../../view/add/AddShape';
+import AddShape from '../../view/add/AddShape';
class AddShapeController extends Component {
constructor (props) {
super(props);
+ this.onShapeClick = this.onShapeClick.bind(this);
}
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ onShapeClick (type) {
+ const api = Common.EditorApi.get();
+ api.AddShapeOnCurrentPage(type);
+ this.closeModal();
+ }
+
render () {
return (
-
)
}
diff --git a/apps/presentationeditor/mobile/src/controller/add/AddSlide.jsx b/apps/presentationeditor/mobile/src/controller/add/AddSlide.jsx
index 5723596ce6..6c2cb706b4 100644
--- a/apps/presentationeditor/mobile/src/controller/add/AddSlide.jsx
+++ b/apps/presentationeditor/mobile/src/controller/add/AddSlide.jsx
@@ -3,15 +3,31 @@ import { f7 } from 'framework7-react';
import {Device} from '../../../../../common/mobile/utils/device';
import {observer, inject} from "mobx-react";
-import { AddSlide } from '../../view/add/AddSlide';
+import AddSlide from '../../view/add/AddSlide';
class AddSlideController extends Component {
constructor (props) {
super(props);
+ this.onSlideLayout = this.onSlideLayout.bind(this);
}
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ onSlideLayout (type) {
+ const api = Common.EditorApi.get();
+ api.AddSlide(type);
+ this.closeModal();
+ }
+
render () {
return (
-
)
}
diff --git a/apps/presentationeditor/mobile/src/store/focusObjects.js b/apps/presentationeditor/mobile/src/store/focusObjects.js
index 64e69df712..9a762cbc99 100644
--- a/apps/presentationeditor/mobile/src/store/focusObjects.js
+++ b/apps/presentationeditor/mobile/src/store/focusObjects.js
@@ -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() {
const shapes = [];
for (let object of this._focusObjects) {
diff --git a/apps/presentationeditor/mobile/src/store/linkSettings.js b/apps/presentationeditor/mobile/src/store/linkSettings.js
new file mode 100644
index 0000000000..9670a64667
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/store/linkSettings.js
@@ -0,0 +1,8 @@
+import {action, observable, computed} from 'mobx';
+
+export class storeLinkSettings {
+ @observable canAddLink;
+ @action canAddHyperlink (value) {
+ this.canAddLink = value;
+ }
+}
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/store/slideSettings.js b/apps/presentationeditor/mobile/src/store/slideSettings.js
index 0899b7bbcc..37ee3ec4c3 100644
--- a/apps/presentationeditor/mobile/src/store/slideSettings.js
+++ b/apps/presentationeditor/mobile/src/store/slideSettings.js
@@ -41,6 +41,24 @@ export class storeSlideSettings {
@action addArrayLayouts(array) {
this.arrayLayouts = array;
}
+ @computed get slideLayouts () {
+ const layouts = [];
+ const columns = 2;
+ let row = -1;
+ this.arrayLayouts.forEach((item, index)=>{
+ if (0 == index % columns) {
+ layouts.push([]);
+ row++
+ }
+ layouts[row].push({
+ type: item.getIndex(),
+ image: item.get_Image(),
+ width: item.get_Width(),
+ height: item.get_Height()
+ });
+ });
+ return layouts;
+ }
@action changeSlideLayoutIndex(index) {
this.slideLayoutIndex = index;
diff --git a/apps/presentationeditor/mobile/src/store/tableSettings.js b/apps/presentationeditor/mobile/src/store/tableSettings.js
index d36a09aea7..7608c5f3c5 100644
--- a/apps/presentationeditor/mobile/src/store/tableSettings.js
+++ b/apps/presentationeditor/mobile/src/store/tableSettings.js
@@ -141,5 +141,4 @@ export class storeTableSettings {
border.put_Value(0);
}
}
-
}
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/view/add/Add.jsx b/apps/presentationeditor/mobile/src/view/add/Add.jsx
index 07d98fa646..00f312662b 100644
--- a/apps/presentationeditor/mobile/src/view/add/Add.jsx
+++ b/apps/presentationeditor/mobile/src/view/add/Add.jsx
@@ -7,11 +7,36 @@ import {Device} from '../../../../../common/mobile/utils/device';
import AddSlideController from "../../controller/add/AddSlide";
import AddShapeController from "../../controller/add/AddShape";
-//import AddImageController from "../../controller/add/AddImage";
-//import AddOtherController from "../../controller/add/AddOther";
+import {AddImageController} from "../../controller/add/AddImage";
+import {PageImageLinkSettings} from "./AddImage";
+import {AddOtherController} from "../../controller/add/AddOther";
+import {PageAddTable} from "./AddOther";
+import {AddLinkController} from "../../controller/add/AddLink";
+import {PageTypeLink, PageLinkTo} from "./AddLink";
const routes = [
-
+ // Image
+ {
+ path: '/add-image-from-url/',
+ component: PageImageLinkSettings
+ },
+ // Other
+ {
+ path: '/add-table/',
+ component: PageAddTable
+ },
+ {
+ path: '/add-link/',
+ component: AddLinkController
+ },
+ {
+ path: '/add-link-type/',
+ component: PageTypeLink
+ },
+ {
+ path: '/add-link-to/',
+ component: PageLinkTo
+ }
];
const AddLayoutNavbar = ({ tabs, inPopover }) => {
@@ -58,7 +83,7 @@ const AddTabs = props => {
icon: 'icon-add-shape',
component:
});
- /*tabs.push({
+ tabs.push({
caption: _t.textImage,
id: 'add-image',
icon: 'icon-add-image',
@@ -69,7 +94,7 @@ const AddTabs = props => {
id: 'add-other',
icon: 'icon-add-other',
component:
- });*/
+ });
return (
diff --git a/apps/presentationeditor/mobile/src/view/add/AddImage.jsx b/apps/presentationeditor/mobile/src/view/add/AddImage.jsx
new file mode 100644
index 0000000000..f25c979df9
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/view/add/AddImage.jsx
@@ -0,0 +1,49 @@
+import React, {useState} from 'react';
+import {observer, inject} from "mobx-react";
+import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle} from 'framework7-react';
+import { useTranslation } from 'react-i18next';
+
+const PageLinkSettings = props => {
+ const { t } = useTranslation();
+ const _t = t('View.Add', {returnObjects: true});
+ const [stateValue, setValue] = useState('');
+ return (
+
+
+ {_t.textAddress}
+
+ {setValue(event.target.value)}}
+ >
+
+
+
+ {props.onInsertByUrl(stateValue)}}>
+
+
+ )
+};
+
+const AddImage = props => {
+ const { t } = useTranslation();
+ const _t = t('View.Add', {returnObjects: true});
+ return (
+
+ {props.onInsertByFile()}}>
+
+
+
+
+
+
+ )
+};
+
+export {AddImage, PageLinkSettings as PageImageLinkSettings};
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/view/add/AddLink.jsx b/apps/presentationeditor/mobile/src/view/add/AddLink.jsx
new file mode 100644
index 0000000000..567a23e843
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/view/add/AddLink.jsx
@@ -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 (
+
+
+
+ {setTypeLink(1); props.changeType(1);}}>
+ {setTypeLink(0); props.changeType(0);}}>
+
+
+ )
+};
+
+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 (
+
+
+
+ {changeTypeTo(0)}}>
+ {changeTypeTo(1)}}>
+ {changeTypeTo(2)}}>
+ {changeTypeTo(3)}}>
+
+ {!isAndroid && {stateNumberTo + 1}
}
+
+
+
+ {isAndroid && }
+
+
+
+
+
+
+ )
+};
+
+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 (
+
+
+
+
+ {typeLink === 1 ?
+ {setLink(event.target.value)}}
+ /> :
+
+ }
+ {setDisplay(event.target.value)}}
+ />
+ {setScreenTip(event.target.value)}}
+ />
+
+
+ {
+ props.onInsertLink(typeLink, (typeLink === 1 ?
+ {url: link, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled } :
+ {linkTo: linkTo, numberTo: numberTo, display: stateDisplay, tip: screenTip, displayDisabled: displayDisabled}));
+ }}
+ />
+
+
+ )
+};
+
+export {PageLink,
+ PageLinkTo,
+ PageTypeLink}
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/view/add/AddOther.jsx b/apps/presentationeditor/mobile/src/view/add/AddOther.jsx
new file mode 100644
index 0000000000..e80478b4a2
--- /dev/null
+++ b/apps/presentationeditor/mobile/src/view/add/AddOther.jsx
@@ -0,0 +1,60 @@
+import React, {useState} from 'react';
+import {observer, inject} from "mobx-react";
+import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle, Segmented, Button} from 'framework7-react';
+import { useTranslation } from 'react-i18next';
+import {Device} from "../../../../../common/mobile/utils/device";
+
+const PageTable = props => {
+ props.initStyleTable();
+ const { t } = useTranslation();
+ const _t = t('View.Add', {returnObjects: true});
+ const storeTableSettings = props.storeTableSettings;
+ const styles = storeTableSettings.styles;
+ return (
+
+
+
+
+ {styles.map((style, index) => {
+ return (
+ - {props.onStyleClick(style.templateId)}}>
+
+
+ )
+ })}
+
+
+
+ )
+};
+
+const AddOther = props => {
+ const { t } = useTranslation();
+ const _t = t('View.Add', {returnObjects: true});
+ const showInsertLink = props.storeLinkSettings.canAddLink && !props.storeFocusObjects.paragraphLocked;
+ return (
+
+
+
+
+
+
+
+ {showInsertLink &&
+
+
+
+ }
+
+ )
+};
+
+const PageAddTable = inject("storeTableSettings")(observer(PageTable));
+const AddOtherContainer = inject("storeFocusObjects", "storeLinkSettings")(observer(AddOther));
+
+export {AddOtherContainer as AddOther,
+ PageAddTable};
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/view/add/AddShape.jsx b/apps/presentationeditor/mobile/src/view/add/AddShape.jsx
index bf408d896b..e5910762b5 100644
--- a/apps/presentationeditor/mobile/src/view/add/AddShape.jsx
+++ b/apps/presentationeditor/mobile/src/view/add/AddShape.jsx
@@ -5,11 +5,26 @@ import { useTranslation } from 'react-i18next';
import {Device} from '../../../../../common/mobile/utils/device';
const AddShape = props => {
+ const shapes = props.storeShapeSettings.getStyleGroups();
return (
-
-
-
+
+ {shapes.map((row, indexRow) => {
+ return (
+
+ {row.map((shape, index) => {
+ return (
+ - {props.onShapeClick(shape.type)}}>
+
+
+
+ )
+ })}
+
+ )
+ })}
+
)
};
-export {AddShape};
\ No newline at end of file
+export default inject("storeShapeSettings")(observer(AddShape));
\ No newline at end of file
diff --git a/apps/presentationeditor/mobile/src/view/add/AddSlide.jsx b/apps/presentationeditor/mobile/src/view/add/AddSlide.jsx
index 3a4daa85c3..96b50c2678 100644
--- a/apps/presentationeditor/mobile/src/view/add/AddSlide.jsx
+++ b/apps/presentationeditor/mobile/src/view/add/AddSlide.jsx
@@ -5,11 +5,24 @@ import { useTranslation } from 'react-i18next';
import {Device} from '../../../../../common/mobile/utils/device';
const AddSlide = props => {
+ const layouts = props.storeSlideSettings.slideLayouts;
return (
-
-
-
+
+ {layouts.map((row, rowIndex) => {
+ return (
+
+ {row.map((layout, index) => {
+ return (
+ - {props.onSlideLayout(layout.type)}}>
+
+
+ )
+ })}
+
+ )
+ })}
+
)
};
-export {AddSlide};
\ No newline at end of file
+export default inject("storeSlideSettings")(observer(AddSlide));
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/locale/en.json b/apps/spreadsheeteditor/mobile/locale/en.json
index 4a18434f1c..f7c5fa5cd7 100644
--- a/apps/spreadsheeteditor/mobile/locale/en.json
+++ b/apps/spreadsheeteditor/mobile/locale/en.json
@@ -5,5 +5,18 @@
},
"textAnonymous": "Anonymous"
}
+ },
+ "View" : {
+ "Add" : {
+ "textChart": "Chart",
+ "textFormula": "Formula",
+ "textShape": "Shape",
+ "textOther": "Other"
+ },
+ "Edit" : {
+ "textSelectObjectToEdit": "Select object to edit",
+ "textSettings": "Settings",
+ "textCell": "Cell"
+ }
}
}
diff --git a/apps/spreadsheeteditor/mobile/src/controller/Main.jsx b/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
index 3aa5693cd9..0a28824c78 100644
--- a/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
+++ b/apps/spreadsheeteditor/mobile/src/controller/Main.jsx
@@ -5,6 +5,7 @@ import { f7 } from 'framework7-react';
import { withTranslation } from 'react-i18next';
import CollaborationController from '../../../../common/mobile/lib/controller/Collaboration.jsx'
+@inject("storeFocusObjects")
class MainController extends Component {
constructor(props) {
super(props)
@@ -202,6 +203,14 @@ class MainController extends Component {
// me.api.asc_registerCallback('asc_onPrintUrl', _.bind(me.onPrintUrl, me));
// me.api.asc_registerCallback('asc_onDocumentName', _.bind(me.onDocumentName, me));
me.api.asc_registerCallback('asc_onEndAction', me._onLongActionEnd.bind(me));
+
+ const storeFocusObjects = this.props.storeFocusObjects;
+ this.api.asc_registerCallback('asc_onFocusObject', objects => {
+ storeFocusObjects.resetFocusObjects(objects);
+ });
+ this.api.asc_registerCallback('asc_onSelectionChanged', cellInfo => {
+ storeFocusObjects.resetCellInfo(cellInfo);
+ });
}
_onLongActionEnd(type, id) {
diff --git a/apps/spreadsheeteditor/mobile/src/controller/add/AddChart.jsx b/apps/spreadsheeteditor/mobile/src/controller/add/AddChart.jsx
new file mode 100644
index 0000000000..5e69d6d853
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/controller/add/AddChart.jsx
@@ -0,0 +1,28 @@
+import React, {Component} from 'react';
+import { f7 } from 'framework7-react';
+import {Device} from '../../../../../common/mobile/utils/device';
+
+import AddChart from '../../view/add/AddChart';
+
+class AddChartController extends Component {
+ constructor (props) {
+ super(props);
+ }
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+export default AddChartController;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/controller/add/AddFormula.jsx b/apps/spreadsheeteditor/mobile/src/controller/add/AddFormula.jsx
new file mode 100644
index 0000000000..46959e5c29
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/controller/add/AddFormula.jsx
@@ -0,0 +1,28 @@
+import React, {Component} from 'react';
+import { f7 } from 'framework7-react';
+import {Device} from '../../../../../common/mobile/utils/device';
+
+import AddFormula from '../../view/add/AddFormula';
+
+class AddFormulaController extends Component {
+ constructor (props) {
+ super(props);
+ }
+
+ closeModal () {
+ if ( Device.phone ) {
+ f7.sheet.close('.add-popup', true);
+ } else {
+ f7.popover.close('#add-popover');
+ }
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+export default AddFormulaController;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/controller/edit/EditCell.jsx b/apps/spreadsheeteditor/mobile/src/controller/edit/EditCell.jsx
new file mode 100644
index 0000000000..d74d69b64c
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/controller/edit/EditCell.jsx
@@ -0,0 +1,20 @@
+import React, {Component} from 'react';
+import { f7 } from 'framework7-react';
+import {Device} from '../../../../../common/mobile/utils/device';
+
+import EditCell from '../../view/edit/EditCell';
+
+class EditCellController extends Component {
+ constructor (props) {
+ super(props);
+ }
+
+ render () {
+ return (
+
+ )
+ }
+}
+
+export default EditCellController;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less
index 36cb30894f..ec61398a84 100644
--- a/apps/spreadsheeteditor/mobile/src/less/icons-ios.less
+++ b/apps/spreadsheeteditor/mobile/src/less/icons-ios.less
@@ -475,7 +475,7 @@
}
}
- .active {
+ .tab-link-active {
i.icon {
&.icon-add-chart {
width: 24px;
diff --git a/apps/spreadsheeteditor/mobile/src/page/main.jsx b/apps/spreadsheeteditor/mobile/src/page/main.jsx
index 0d648d5223..5d51c19929 100644
--- a/apps/spreadsheeteditor/mobile/src/page/main.jsx
+++ b/apps/spreadsheeteditor/mobile/src/page/main.jsx
@@ -6,12 +6,15 @@ import Settings from '../view/settings/Settings';
import CollaborationView from '../../../../common/mobile/lib/view/Collaboration.jsx'
import CellEditor from '../controller/CellEditor';
import Statusbar from '../controller/StatusBar'
+import AddOptions from "../view/add/Add";
+import EditOptions from "../view/edit/Edit";
export default class MainPage extends Component {
constructor(props) {
super(props);
this.state = {
editOptionsVisible: false,
+ addOptionsVisible: false,
settingsVisible: false,
collaborationVisible: false,
};
@@ -21,12 +24,12 @@ export default class MainPage extends Component {
this.setState(state => {
if ( opts == 'edit' )
return {editOptionsVisible: true};
- else
- if ( opts == 'settings' )
+ else if ( opts == 'add' )
+ return {addOptionsVisible: true};
+ else if ( opts == 'settings' )
return {settingsVisible: true};
- else
- if ( opts == 'coauth' )
- return {collaborationVisible: true}
+ else if ( opts == 'coauth' )
+ return {collaborationVisible: true};
});
};
@@ -35,12 +38,12 @@ export default class MainPage extends Component {
await 1 && this.setState(state => {
if ( opts == 'edit' )
return {editOptionsVisible: false};
- else
- if ( opts == 'settings' )
+ else if ( opts == 'add' )
+ return {addOptionsVisible: false};
+ else if ( opts == 'settings' )
return {settingsVisible: false};
- else
- if ( opts == 'coauth' )
- return {collaborationVisible: false}
+ else if ( opts == 'coauth' )
+ return {collaborationVisible: false};
})
})();
};
@@ -57,6 +60,7 @@ export default class MainPage extends Component {
this.handleClickToOpenOptions('edit')}>
+ this.handleClickToOpenOptions('add')}>
this.handleClickToOpenOptions('coauth')}>
this.handleClickToOpenOptions('settings')}>
@@ -64,10 +68,14 @@ export default class MainPage extends Component {
{/* Page content */}
- {/*{*/}
- {/*!this.state.editOptionsVisible ? null :*/}
- {/**/}
- {/*}*/}
+ {
+ !this.state.editOptionsVisible ? null :
+
+ }
+ {
+ !this.state.addOptionsVisible ? null :
+
+ }
{
!this.state.settingsVisible ? null :
diff --git a/apps/spreadsheeteditor/mobile/src/store/focusObjects.js b/apps/spreadsheeteditor/mobile/src/store/focusObjects.js
new file mode 100644
index 0000000000..5d87693d9c
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/store/focusObjects.js
@@ -0,0 +1,138 @@
+import {action, observable, computed} from 'mobx';
+
+export class storeFocusObjects {
+ @observable focusOn = undefined;
+
+ @observable _focusObjects = [];
+
+ @action resetFocusObjects(objects) {
+ this.focusOn = 'obj';
+ this._focusObjects = objects;
+ }
+
+ @computed get objects() {
+ const _objects = [];
+ for (let object of this._focusObjects) {
+ const type = object.get_ObjectType();
+
+ if (Asc.c_oAscTypeSelectElement.Paragraph == type) {
+ _objects.push('text', 'paragraph');
+ } else if (Asc.c_oAscTypeSelectElement.Table == type) {
+ _objects.push('table');
+ } else if (Asc.c_oAscTypeSelectElement.Image == type) {
+ if (object.get_ObjectValue().get_ChartProperties()) {
+ _objects.push('chart');
+ } else if (object.get_ObjectValue().get_ShapeProperties()) {
+ _objects.push('shape');
+ } else {
+ _objects.push('image');
+ }
+ } else if (Asc.c_oAscTypeSelectElement.Hyperlink == type) {
+ _objects.push('hyperlink');
+ }
+ }
+ const resultArr = _objects.filter((value, index, self) => self.indexOf(value) === index); //get uniq array
+ // Exclude shapes if chart exist
+ if (resultArr.indexOf('chart') > -1) {
+ resultArr.splice(resultArr.indexOf('shape'), 1);
+ }
+ return resultArr;
+ }
+
+ @observable _cellInfo;
+
+ @action resetCellInfo (cellInfo) {
+ this.focusOn = 'cell';
+ this._cellInfo = cellInfo;
+ }
+
+ @computed get selections () {
+ const _selections = [];
+
+ let isCell, isRow, isCol, isAll, isChart, isImage, isTextShape, isShape, isTextChart,
+ selType = this._cellInfo.asc_getSelectionType(),
+ isObjLocked = false;
+
+ switch (selType) {
+ case Asc.c_oAscSelectionType.RangeCells: isCell = true; break;
+ case Asc.c_oAscSelectionType.RangeRow: isRow = true; break;
+ case Asc.c_oAscSelectionType.RangeCol: isCol = true; break;
+ case Asc.c_oAscSelectionType.RangeMax: isAll = true; break;
+ case Asc.c_oAscSelectionType.RangeImage: isImage = true; break;
+ case Asc.c_oAscSelectionType.RangeShape: isShape = true; break;
+ case Asc.c_oAscSelectionType.RangeChart: isChart = true; break;
+ case Asc.c_oAscSelectionType.RangeChartText:isTextChart = true; break;
+ case Asc.c_oAscSelectionType.RangeShapeText: isTextShape = true; break;
+ }
+
+ if (isImage || isShape || isChart) {
+ isImage = isShape = isChart = false;
+ let has_chartprops = false;
+ let selectedObjects = Common.EditorApi.get().asc_getGraphicObjectProps();
+
+ for (let i = 0; i < selectedObjects.length; i++) {
+ if (selectedObjects[i].asc_getObjectType() == Asc.c_oAscTypeSelectElement.Image) {
+ const elValue = selectedObjects[i].asc_getObjectValue();
+ isObjLocked = isObjLocked || elValue.asc_getLocked();
+ const shapeProps = elValue.asc_getShapeProperties();
+
+ if (shapeProps) {
+ if (shapeProps.asc_getFromChart()) {
+ isChart = true;
+ } else {
+ isShape = true;
+ }
+ } else if (elValue.asc_getChartProperties()) {
+ isChart = true;
+ has_chartprops = true;
+ } else {
+ isImage = true;
+ }
+ }
+ }
+ } else if (isTextShape || isTextChart) {
+ const selectedObjects = this.api.asc_getGraphicObjectProps();
+ let isEquation = false;
+
+ for (var i = 0; i < selectedObjects.length; i++) {
+ const elType = selectedObjects[i].asc_getObjectType();
+ if (elType == Asc.c_oAscTypeSelectElement.Image) {
+ const value = selectedObjects[i].asc_getObjectValue();
+ isObjLocked = isObjLocked || value.asc_getLocked();
+ } else if (elType == Asc.c_oAscTypeSelectElement.Paragraph) {
+ } else if (elType == Asc.c_oAscTypeSelectElement.Math) {
+ isEquation = true;
+ }
+ }
+ }
+ if (isChart || isTextChart) {
+ _selections.push('chart');
+
+ if (isTextChart) {
+ _selections.push('text');
+ }
+ } else if ((isShape || isTextShape) && !isImage) {
+ _selections.push('shape');
+
+ if (isTextShape) {
+ _selections.push('text');
+ }
+ } else if (isImage) {
+ _selections.push('image');
+
+ if (isShape) {
+ _selections.push('shape');
+ }
+ } else {
+ _selections.push('cell');
+
+ if (this._cellInfo.asc_getHyperlink()) {
+ _selections.push('hyperlink');
+ }
+ }
+ return _selections;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/store/mainStore.js b/apps/spreadsheeteditor/mobile/src/store/mainStore.js
index a54c22e561..850aea6f8e 100644
--- a/apps/spreadsheeteditor/mobile/src/store/mainStore.js
+++ b/apps/spreadsheeteditor/mobile/src/store/mainStore.js
@@ -1,6 +1,6 @@
// import {storeDocumentSettings} from './documentSettings';
-// import {storeFocusObjects} from "./focusObjects";
+import {storeFocusObjects} from "./focusObjects";
import {storeUsers} from '../../../../common/mobile/lib/store/users';
import {storeWorksheets} from './sheets';
// import {storeTextSettings} from "./textSettings";
@@ -11,7 +11,7 @@ import {storeWorksheets} from './sheets';
// import {storeChartSettings} from "./chartSettings";
export const stores = {
- // storeFocusObjects: new storeFocusObjects(),
+ storeFocusObjects: new storeFocusObjects(),
// storeDocumentSettings: new storeDocumentSettings(),
users: new storeUsers(),
sheets: new storeWorksheets()
diff --git a/apps/spreadsheeteditor/mobile/src/view/add/Add.jsx b/apps/spreadsheeteditor/mobile/src/view/add/Add.jsx
new file mode 100644
index 0000000000..619b8983ad
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/view/add/Add.jsx
@@ -0,0 +1,122 @@
+import React, {Component, useEffect} from 'react';
+import {View,Page,Navbar,NavRight,Link,Popup,Popover,Icon,Tabs,Tab} from 'framework7-react';
+import { useTranslation } from 'react-i18next';
+import {f7} from 'framework7-react';
+import { observer, inject } from "mobx-react";
+import {Device} from '../../../../../common/mobile/utils/device';
+
+import AddChartController from "../../controller/add/AddChart";
+import AddFormulaController from "../../controller/add/AddFormula";
+//import AddShapeController from "../../controller/add/AddShape";
+//import {AddOtherController} from "../../controller/add/AddOther";
+
+const routes = [
+];
+
+const AddLayoutNavbar = ({ tabs, inPopover }) => {
+ const isAndroid = Device.android;
+ return (
+
+
+ {tabs.map((item, index) =>
+
+
+ )}
+ {isAndroid && }
+
+ { !inPopover && }
+
+ )
+};
+
+const AddLayoutContent = ({ tabs }) => {
+ return (
+
+ {tabs.map((item, index) =>
+
+ {item.component}
+
+ )}
+
+ )
+};
+
+const AddTabs = props => {
+ const { t } = useTranslation();
+ const _t = t('Add', {returnObjects: true});
+ const tabs = [];
+ tabs.push({
+ caption: _t.textChart,
+ id: 'add-chart',
+ icon: 'icon-add-chart',
+ component:
+ });
+ tabs.push({
+ caption: _t.textFormula,
+ id: 'add-formula',
+ icon: 'icon-add-formula',
+ component:
+ });
+ /*tabs.push({
+ caption: _t.textShape,
+ id: 'add-shape',
+ icon: 'icon-add-shape',
+ component:
+ });
+ tabs.push({
+ caption: _t.textOther,
+ id: 'add-other',
+ icon: 'icon-add-other',
+ component:
+ });*/
+ return (
+
+
+
+
+
+
+ )
+};
+
+class AddView extends Component {
+ constructor(props) {
+ super(props);
+
+ this.onoptionclick = this.onoptionclick.bind(this);
+ }
+ onoptionclick(page){
+ f7.views.current.router.navigate(page);
+ }
+ render() {
+ const show_popover = this.props.usePopover;
+ return (
+ show_popover ?
+ this.props.onclosed()}>
+
+ :
+ this.props.onclosed()}>
+
+
+ )
+ }
+}
+
+const Add = props => {
+ useEffect(() => {
+ if ( Device.phone )
+ f7.popup.open('.add-popup');
+ else f7.popover.open('#add-popover', '#btn-add');
+
+ return () => {
+ // component will unmount
+ }
+ });
+ const onviewclosed = () => {
+ if ( props.onclosed )
+ props.onclosed();
+ };
+ return
+};
+
+export default Add;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/view/add/AddChart.jsx b/apps/spreadsheeteditor/mobile/src/view/add/AddChart.jsx
new file mode 100644
index 0000000000..8eec1a782e
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/view/add/AddChart.jsx
@@ -0,0 +1,12 @@
+import React, {Fragment, useState} from 'react';
+import {observer, inject} from "mobx-react";
+
+const AddChart = props => {
+ return (
+
+
+
+ )
+};
+
+export default AddChart;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/view/add/AddFormula.jsx b/apps/spreadsheeteditor/mobile/src/view/add/AddFormula.jsx
new file mode 100644
index 0000000000..b8272b828e
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/view/add/AddFormula.jsx
@@ -0,0 +1,12 @@
+import React, {Fragment, useState} from 'react';
+import {observer, inject} from "mobx-react";
+
+const AddFormula = props => {
+ return (
+
+
+
+ )
+};
+
+export default AddFormula;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/view/edit/Edit.jsx b/apps/spreadsheeteditor/mobile/src/view/edit/Edit.jsx
new file mode 100644
index 0000000000..3ed9651ef2
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/view/edit/Edit.jsx
@@ -0,0 +1,138 @@
+import React, {useState, useEffect} from 'react';
+import {observer, inject} from "mobx-react";
+import { Popover, Sheet, View, Page, Navbar, NavRight, NavLeft, NavTitle, Tabs, Tab, Link } from 'framework7-react';
+import { f7 } from 'framework7-react';
+import { useTranslation } from 'react-i18next';
+import {Device} from '../../../../../common/mobile/utils/device';
+
+import EditCellController from "../../controller/edit/EditCell";
+
+const routes = [
+];
+
+const EmptyEditLayout = () => {
+ const { t } = useTranslation();
+ const _t = t('View.Edit', {returnObjects: true});
+ return (
+
+
+
+
{_t.textSelectObjectToEdit}
+
+
+
+ )
+};
+
+const EditLayoutNavbar = ({ editors, inPopover }) => {
+ const isAndroid = Device.android;
+ const { t } = useTranslation();
+ const _t = t('View.Edit', {returnObjects: true});
+ return (
+
+ {
+ editors.length > 1 ?
+
+ {editors.map((item, index) => {item.caption})}
+ {isAndroid && }
+
:
+ { editors[0].caption }
+ }
+ { !inPopover && }
+
+ )
+};
+
+const EditLayoutContent = ({ editors }) => {
+ if (editors.length > 1) {
+ return (
+
+ {editors.map((item, index) =>
+
+ {item.component}
+
+ )}
+
+ )
+ } else {
+ return (
+
+ {editors[0].component}
+
+ )
+ }
+};
+
+const EditTabs = props => {
+ const { t } = useTranslation();
+ const _t = t('View.Edit', {returnObjects: true});
+
+ const store = props.storeFocusObjects;
+ const settings = !store.focusOn ? [] : (store.focusOn === 'obj' ? store.settings : store.selections);
+ let editors = [];
+ if (settings.length < 1) {
+ editors.push({
+ caption: _t.textSettings,
+ component:
+ });
+ } else {
+ if (settings.indexOf('cell') > -1) {
+ editors.push({
+ caption: _t.textCell,
+ id: 'edit-text',
+ component:
+ })
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+ )
+};
+
+const EditTabsContainer = inject("storeFocusObjects")(observer(EditTabs));
+
+const EditView = props => {
+ const onOptionClick = (page) => {
+ $f7.views.current.router.navigate(page);
+ };
+ const show_popover = props.usePopover;
+ return (
+ show_popover ?
+ props.onClosed()}>
+
+ :
+ props.onClosed()}>
+
+
+ )
+};
+
+const EditOptions = props => {
+ useEffect(() => {
+ if ( Device.phone )
+ f7.sheet.open('#edit-sheet');
+ else f7.popover.open('#edit-popover', '#btn-edit');
+
+ return () => {
+ // component will unmount
+ }
+ });
+
+ const onviewclosed = () => {
+ if ( props.onclosed )
+ props.onclosed();
+ };
+
+ return (
+
+ )
+};
+
+export default EditOptions;
\ No newline at end of file
diff --git a/apps/spreadsheeteditor/mobile/src/view/edit/EditCell.jsx b/apps/spreadsheeteditor/mobile/src/view/edit/EditCell.jsx
new file mode 100644
index 0000000000..6299857112
--- /dev/null
+++ b/apps/spreadsheeteditor/mobile/src/view/edit/EditCell.jsx
@@ -0,0 +1,12 @@
+import React, {Fragment, useState} from 'react';
+import {observer, inject} from "mobx-react";
+
+const EditCell = props => {
+ return (
+
+
+
+ )
+};
+
+export default EditCell;
\ No newline at end of file