Merge branch 'feature/mobile-apps-on-reactjs' of https://github.com/ONLYOFFICE/web-apps into feature/mobile-apps-on-reactjs

This commit is contained in:
SergeyEzhin 2021-03-16 20:47:57 +03:00
commit a069d8c43b
63 changed files with 1714 additions and 798 deletions

View file

@ -1,8 +1,8 @@
import React, { Component } from 'react'; import React, { Component, Fragment } from 'react';
import { f7 } from 'framework7-react'; import { f7 } from 'framework7-react';
import { Device } from '../../../../common/mobile/utils/device' import { Device } from '../../../../common/mobile/utils/device'
import ContextMenuView, { idContextMenuElement } from '../view/ContextMenu'; import ContextMenuView, { idContextMenuElement, ActionsWithExtraItems } from '../view/ContextMenu';
const idCntextMenuTargetElement = '#idx-context-menu-target'; const idCntextMenuTargetElement = '#idx-context-menu-target';
@ -11,12 +11,15 @@ class ContextMenuController extends Component {
super(props); super(props);
this.state = { this.state = {
opened: false opened: false,
, items: [] items: [],
openedMore: false,
extraItems: []
}; };
this.onMenuItemClick = this.onMenuItemClick.bind(this); this.onMenuItemClick = this.onMenuItemClick.bind(this);
this.onMenuClosed = this.onMenuClosed.bind(this); this.onMenuClosed = this.onMenuClosed.bind(this);
this.onActionClosed = this.onActionClosed.bind(this);
this.onDocumentReady = this.onDocumentReady.bind(this); this.onDocumentReady = this.onDocumentReady.bind(this);
this.onApiOpenContextMenu = this.onApiOpenContextMenu.bind(this); this.onApiOpenContextMenu = this.onApiOpenContextMenu.bind(this);
this.onApiHideContextMenu = this.onApiHideContextMenu.bind(this); this.onApiHideContextMenu = this.onApiHideContextMenu.bind(this);
@ -96,7 +99,10 @@ class ContextMenuController extends Component {
onApiOpenContextMenu(x, y) { onApiOpenContextMenu(x, y) {
if ( !this.state.opened ) { if ( !this.state.opened ) {
this.setState({items: this.initMenuItems()}); this.setState({
items: this.initMenuItems(),
extraItems: this.initExtraItems()
});
this.$targetEl.css({left: `${x}px`, top: `${y}px`}); this.$targetEl.css({left: `${x}px`, top: `${y}px`});
const popover = f7.popover.open(idContextMenuElement, idCntextMenuTargetElement); const popover = f7.popover.open(idContextMenuElement, idCntextMenuTargetElement);
@ -132,8 +138,16 @@ class ContextMenuController extends Component {
// })(); // })();
} }
onActionClosed() {
this.setState({openedMore: false});
}
onMenuItemClick(action) { onMenuItemClick(action) {
this.onApiHideContextMenu(); this.onApiHideContextMenu();
if (action === 'showActionSheet') {
this.setState({openedMore: true});
}
} }
componentWillUnmount() { componentWillUnmount() {
@ -158,9 +172,16 @@ class ContextMenuController extends Component {
return []; return [];
} }
initExtraItems () {
return [];
}
render() { render() {
return ( return (
<Fragment>
<ContextMenuView items={this.state.items} onMenuClosed={this.onMenuClosed} onMenuItemClick={this.onMenuItemClick} /> <ContextMenuView items={this.state.items} onMenuClosed={this.onMenuClosed} onMenuItemClick={this.onMenuItemClick} />
<ActionsWithExtraItems items={this.state.extraItems} onMenuItemClick={this.onMenuItemClick} opened={this.state.openedMore} onActionClosed={this.onActionClosed}/>
</Fragment>
) )
} }
} }

View file

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import SearchView, {SearchSettingsView} from '../view/Search' import {SearchView, SearchSettingsView} from '../view/Search';
const SearchController = props => { const SearchController = props => {
const onSearchQuery = params => { const onSearchQuery = params => {

View file

@ -58,6 +58,8 @@ class CommentsController extends Component {
api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this)); api.asc_registerCallback('asc_onRemoveComment', this.removeComment.bind(this));
api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this)); api.asc_registerCallback('asc_onRemoveComments', this.removeComments.bind(this));
api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this)); api.asc_registerCallback('asc_onChangeCommentData', this.changeCommentData.bind(this));
api.asc_registerCallback('asc_onShowComment', this.changeShowComments.bind(this));
api.asc_registerCallback('asc_onHideComment', this.hideComments.bind(this));
}); });
Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse Common.Notifications.on('comments:filterchange', this.onFilterChange.bind(this)); // for sse
@ -97,35 +99,35 @@ class CommentsController extends Component {
this.removeComment(data[i]); this.removeComment(data[i]);
} }
} }
changeShowComments (id) {
this.storeComments.changeShowComment(id);
}
hideComments () {
//Common.Notifications.trigger('closeviewcomment');
}
changeCommentData (id, data) { changeCommentData (id, data) {
let date = null; const changeComment = {};
let replies = null;
let repliesCount = 0;
let dateReply = null;
const comment = this.storeComments.findComment(id); const date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
if (comment) {
date = (data.asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getOnlyOfficeTime())) :
((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime()))); ((data.asc_getTime() === '') ? new Date() : new Date(stringUtcToLocalDate(data.asc_getTime())));
let user = this.usersStore.searchUserById(data.asc_getUserId()); let user = this.usersStore.searchUserById(data.asc_getUserId());
comment.comment = data.asc_getText(); changeComment.comment = data.asc_getText();
comment.userId = data.asc_getUserId(); changeComment.userId = data.asc_getUserId();
comment.userName = data.asc_getUserName(); changeComment.userName = data.asc_getUserName();
comment.userColor = (user) ? user.asc_getColor() : null; changeComment.userColor = (user) ? user.asc_getColor() : null;
comment.resolved = data.asc_getSolved(); changeComment.resolved = data.asc_getSolved();
comment.quote = data.asc_getQuoteText(); changeComment.quote = data.asc_getQuoteText();
comment.time = date.getTime(); changeComment.time = date.getTime();
comment.date = dateToLocaleTimeString(date); changeComment.date = dateToLocaleTimeString(date);
comment.editable = this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId); changeComment.editable = this.appOptions.canEditComments || (data.asc_getUserId() === this.curUserId);
comment.removable = this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId); changeComment.removable = this.appOptions.canDeleteComments || (data.asc_getUserId() === this.curUserId);
replies = []; let dateReply = null;
const replies = [];
repliesCount = data.asc_getRepliesCount(); const repliesCount = data.asc_getRepliesCount();
for (let i = 0; i < repliesCount; ++i) { for (let i = 0; i < repliesCount; ++i) {
dateReply = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) : dateReply = (data.asc_getReply(i).asc_getOnlyOfficeTime()) ? new Date(stringOOToLocalDate(data.asc_getReply(i).asc_getOnlyOfficeTime())) :
@ -146,8 +148,9 @@ class CommentsController extends Component {
removable: this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId) removable: this.appOptions.canDeleteComments || (data.asc_getReply(i).asc_getUserId() === this.curUserId)
}); });
} }
comment.replies = replies; changeComment.replies = replies;
}
this.props.storeComments.changeComment(id, changeComment);
} }
onFilterChange (filter) { onFilterChange (filter) {
this.storeComments.changeFilter(filter); this.storeComments.changeFilter(filter);
@ -308,7 +311,7 @@ class EditCommentController extends Component {
var reply = comment.replies; var reply = comment.replies;
if (reply && reply.length > 0) { if (reply && reply.length > 0) {
reply.forEach((reply) => { reply.forEach((reply) => {
var addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); var addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) { if (addReply) {
addReply.asc_putText(reply.reply); addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time))); addReply.asc_putTime(utcDateToString(new Date(reply.time)));
@ -325,11 +328,12 @@ class EditCommentController extends Component {
} }
} }
onEditComment (comment, text) { onEditComment (comment, text) {
comment.comment = text.trim(); const changeComment = {...comment};
changeComment.comment = text.trim();
const user = this.props.users.currentUser; const user = this.props.users.currentUser;
comment.userid = user.asc_getIdOriginal(); changeComment.userid = user.asc_getIdOriginal();
comment.username = user.asc_getUserName(); changeComment.username = user.asc_getUserName();
this.onChangeComment(comment); this.onChangeComment(changeComment);
} }
onAddReply (comment, replyVal) { onAddReply (comment, replyVal) {
let reply = null; let reply = null;
@ -386,10 +390,13 @@ class EditCommentController extends Component {
onEditReply (comment, reply, textReply) { onEditReply (comment, reply, textReply) {
const currentUser = this.props.users.currentUser; const currentUser = this.props.users.currentUser;
const indReply = reply.ind; const indReply = reply.ind;
comment.replies[indReply].reply = textReply; const changeComment = {...comment};
comment.replies[indReply].userid = currentUser.asc_getIdOriginal(); changeComment.replies = [...comment.replies];
comment.replies[indReply].username = currentUser.asc_getUserName(); changeComment.replies[indReply] = {...reply};
this.onChangeComment(comment); changeComment.replies[indReply].reply = textReply;
changeComment.replies[indReply].userid = currentUser.asc_getIdOriginal();
changeComment.replies[indReply].username = currentUser.asc_getUserName();
this.onChangeComment(changeComment);
} }
render() { render() {
const storeComments = this.props.storeComments; const storeComments = this.props.storeComments;
@ -418,14 +425,18 @@ class ViewCommentsController extends Component {
Common.Notifications.on('viewcomment', () => { Common.Notifications.on('viewcomment', () => {
this.setState({isOpenViewCurComments: true}); this.setState({isOpenViewCurComments: true});
}); });
Common.Notifications.on('closeviewcomment', () => {
this.closeViewCurComments();
});
} }
closeViewCurComments () { closeViewCurComments () {
f7.sheet.close('#view-comment-sheet');
this.setState({isOpenViewCurComments: false}); this.setState({isOpenViewCurComments: false});
} }
onResolveComment (comment) { onResolveComment (comment) {
let reply = null, let reply = null,
addReply = null, addReply = null,
ascComment = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); ascComment = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (ascComment && comment) { if (ascComment && comment) {
ascComment.asc_putText(comment.comment); ascComment.asc_putText(comment.comment);
@ -444,7 +455,7 @@ class ViewCommentsController extends Component {
reply = comment.replies; reply = comment.replies;
if (reply && reply.length > 0) { if (reply && reply.length > 0) {
reply.forEach((reply) => { reply.forEach((reply) => {
addReply = (!!Asc.asc_CCommentDataWord ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null)); addReply = (typeof Asc.asc_CCommentDataWord !== 'undefined' ? new Asc.asc_CCommentDataWord(null) : new Asc.asc_CCommentData(null));
if (addReply) { if (addReply) {
addReply.asc_putText(reply.reply); addReply.asc_putText(reply.reply);
addReply.asc_putTime(utcDateToString(new Date(reply.time))); addReply.asc_putTime(utcDateToString(new Date(reply.time)));
@ -546,7 +557,11 @@ class ViewCommentsController extends Component {
return( return(
<Fragment> <Fragment>
{this.props.allComments && <ViewComments onCommentMenuClick={this.onCommentMenuClick} onResolveComment={this.onResolveComment} />} {this.props.allComments && <ViewComments onCommentMenuClick={this.onCommentMenuClick} onResolveComment={this.onResolveComment} />}
{this.state.isOpenViewCurComments && <ViewCurrentComments opened={this.state.isOpenViewCurComments} closeCurComments={this.closeViewCurComments} />} {this.state.isOpenViewCurComments && <ViewCurrentComments opened={this.state.isOpenViewCurComments}
closeCurComments={this.closeViewCurComments}
onCommentMenuClick={this.onCommentMenuClick}
onResolveComment={this.onResolveComment}
/>}
</Fragment> </Fragment>
) )
} }

View file

@ -9,8 +9,12 @@ export class storeComments {
filter: observable, filter: observable,
groupCollectionFilter: observable, groupCollectionFilter: observable,
showComments: observable,
changeShowComment: action,
addComment: action, addComment: action,
removeComment: action, removeComment: action,
changeComment: action,
changeFilter: action, changeFilter: action,
sortComments: computed, sortComments: computed,
@ -29,6 +33,14 @@ export class storeComments {
filter = undefined; filter = undefined;
groupCollectionFilter = []; // for sse groupCollectionFilter = []; // for sse
showComments = [];
changeShowComment (uid) {
this.showComments.length = 0;
uid.forEach((item) => {
this.showComments.push(this.findComment(item));
});
}
addComment (comment) { addComment (comment) {
comment.groupName ? this.addCommentToGroupCollection(comment) : this.addCommentToCollection(comment); comment.groupName ? this.addCommentToGroupCollection(comment) : this.addCommentToCollection(comment);
} }
@ -81,6 +93,23 @@ export class storeComments {
} }
} }
changeComment (id, changeComment) {
const comment = this.findComment(id);
if (comment) {
comment.comment = changeComment.comment;
comment.userId = changeComment.userId;
comment.userName = changeComment.userName;
comment.userColor = changeComment.userColor;
comment.resolved = changeComment.resolved;
comment.quote = changeComment.quote;
comment.time = changeComment.time;
comment.date = changeComment.date;
comment.editable = changeComment.editable;
comment.removable = changeComment.removable;
comment.replies = changeComment.replies;
}
}
changeFilter (filter) { changeFilter (filter) {
let comments = []; let comments = [];
this.filter = filter; this.filter = filter;

View file

@ -1,6 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Popover, List, ListItem, ListButton, Link, Icon } from 'framework7-react'; import { Popover, List, ListItem, ListButton, Link, Icon, Actions, ActionsGroup, ActionsButton } from 'framework7-react';
import { f7 } from 'framework7-react'; import { f7 } from 'framework7-react';
import { useTranslation } from 'react-i18next';
const idContextMenuElement = "idx-context-menu-popover"; const idContextMenuElement = "idx-context-menu-popover";
@ -38,5 +39,24 @@ class ContextMenuView extends Component {
} }
} }
const ActionsWithExtraItems = ({items, onMenuItemClick, opened, onActionClosed}) => {
const { t } = useTranslation();
const _t = t('ContextMenu', {returnObjects: true});
return (
<Actions opened={opened} onActionsClosed={() => onActionClosed()}>
<ActionsGroup>
{items.length > 0 && items.map((item, index)=>{
return(
<ActionsButton key={`act-${item.caption}`} onClick={() => {onMenuItemClick(item.event)}}>{item.caption}</ActionsButton>
)
})}
</ActionsGroup>
<ActionsGroup>
<ActionsButton>{_t.menuCancel}</ActionsButton>
</ActionsGroup>
</Actions>
)
};
const exportedIdMenuElemen = `#${idContextMenuElement}`; const exportedIdMenuElemen = `#${idContextMenuElement}`;
export {ContextMenuView as default, exportedIdMenuElemen as idContextMenuElement}; export {ContextMenuView as default, exportedIdMenuElemen as idContextMenuElement, ActionsWithExtraItems};

View file

@ -4,7 +4,7 @@ import { Toggle } from 'framework7-react';
import { f7 } from 'framework7-react'; import { f7 } from 'framework7-react';
import { Dom7 } from 'framework7'; import { Dom7 } from 'framework7';
import { Device } from '../../../../common/mobile/utils/device'; import { Device } from '../../../../common/mobile/utils/device';
import { observable } from "mobx"; import { observable, runInAction } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
const searchOptions = observable({ const searchOptions = observable({
@ -24,18 +24,23 @@ class SearchSettingsView extends Component {
this.state = { this.state = {
useReplace: false, useReplace: false,
caseSensitive: false, // caseSensitive: false,
markResults: false // markResults: false
searchIn: 0,
searchBy: 1,
lookIn: 1,
isMatchCase: false,
isMatchCell: false
}; };
} }
onFindReplaceClick(action) { onFindReplaceClick(action) {
searchOptions.usereplace = action == 'replace'; runInAction(() => searchOptions.usereplace = action == 'replace');
this.setState({ this.setState({
useReplace: searchOptions.usereplace useReplace: searchOptions.usereplace
}); });
if (this.onReplaceChecked) {} if (this.onReplaceChecked) {}
} }
@ -43,39 +48,43 @@ class SearchSettingsView extends Component {
} }
render() { render() {
const show_popover = true; const show_popover = !Device.phone;
const navbar = // const navbar =
<Navbar title="Find and replace"> // <Navbar title="Find and replace">
{!show_popover && // {!show_popover &&
<NavRight> // <NavRight>
<Link popupClose=".search-settings-popup">Done</Link> // <Link popupClose=".search-settings-popup">Done</Link>
</NavRight>} // </NavRight>
</Navbar>; // }
// </Navbar>;
const extra = this.extraSearchOptions(); const extra = this.extraSearchOptions();
const content = const content =
<View style={popoverStyle}> <View style={show_popover ? popoverStyle : null}>
<Page> {/* <Page> */}
{navbar} {/* {navbar} */}
<List> {extra}
<ListItem radio title="Find" name="find-replace-checkbox" checked={!this.state.useReplace} onClick={e => this.onFindReplaceClick('find')} /> {/* </Page> */}
<ListItem radio title="Find and replace" name="find-replace-checkbox" checked={this.state.useReplace} onClick={e => this.onFindReplaceClick('replace')} />
</List>
{ extra }
</Page>
</View>; </View>;
return ( return (
show_popover ? show_popover ?
<Popover id="idx-search-settings" className="popover__titled">{content}</Popover> : <Popover id="idx-search-settings" className="popover__titled">{content}</Popover> :
<Popup id="idx-search-settings">{content}</Popup> <Popup id="idx-search-settings" className="search-settings-popup">{content}</Popup>
) )
} }
} }
@observer // @observer
class SearchView extends Component { class SearchView extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {
searchQuery: '',
replaceQuery: ''
};
const $$ = Dom7;
$$(document).on('page:init', (e, page) => { $$(document).on('page:init', (e, page) => {
if ( page.name == 'home' ) { if ( page.name == 'home' ) {
this.searchbar = f7.searchbar.create({ this.searchbar = f7.searchbar.create({
@ -97,8 +106,9 @@ class SearchView extends Component {
// return (m = /(iPad|iPhone|iphone).*?(OS |os |OS\_)(\d+((_|\.)\d)?((_|\.)\d)?)/.exec(ua)) ? parseFloat(m[3]) : 0; // return (m = /(iPad|iPhone|iphone).*?(OS |os |OS\_)(\d+((_|\.)\d)?((_|\.)\d)?)/.exec(ua)) ? parseFloat(m[3]) : 0;
// } // }
const $$ = Dom7;
const $editor = $$('#editor_sdk'); const $editor = $$('#editor_sdk');
// const $replaceLink = $$('#replace-link');
if (false /*iOSVersion() < 13*/) { if (false /*iOSVersion() < 13*/) {
// $editor.single('mousedown touchstart', _.bind(me.onEditorTouchStart, me)); // $editor.single('mousedown touchstart', _.bind(me.onEditorTouchStart, me));
// $editor.single('mouseup touchend', _.bind(me.onEditorTouchEnd, me)); // $editor.single('mouseup touchend', _.bind(me.onEditorTouchEnd, me));
@ -109,21 +119,23 @@ class SearchView extends Component {
$editor.on('pointerdown', this.onEditorTouchStart.bind(this)); $editor.on('pointerdown', this.onEditorTouchStart.bind(this));
$editor.on('pointerup', this.onEditorTouchEnd.bind(this)); $editor.on('pointerup', this.onEditorTouchEnd.bind(this));
// $replaceLink.on('click', this.onReplaceHold.bind(this));
} }
}); });
this.onSettingsClick = this.onSettingsClick.bind(this); this.onSettingsClick = this.onSettingsClick.bind(this);
this.onSearchClick = this.onSearchClick.bind(this); this.onSearchClick = this.onSearchClick.bind(this);
this.onReplaceClick = this.onReplaceClick.bind(this);
} }
componentDidMount(){ componentDidMount(){
const $$ = Dom7; const $$ = Dom7;
this.$repalce = $$('#idx-replace-val'); this.$replace = $$('#idx-replace-val');
} }
onSettingsClick(e) { onSettingsClick(e) {
if ( Device.phone ) { if ( Device.phone ) {
// f7.popup.open('.settings-popup'); f7.popup.open('.search-settings-popup');
} else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings'); } else f7.popover.open('#idx-search-settings', '#idx-btn-search-settings');
} }
@ -132,41 +144,79 @@ class SearchView extends Component {
find: this.searchbar.query find: this.searchbar.query
}; };
if ( searchOptions.usereplace ) if (searchOptions.usereplace) {
params.replace = this.$replace.val(); params.replace = this.$replace.val();
}
return params; return params;
} }
onSearchClick(action) { onSearchClick(action) {
if ( this.searchbar && this.searchbar.query) { if (this.searchbar && this.state.searchQuery) {
if ( this.props.onSearchQuery ) { if (this.props.onSearchQuery) {
let params = this.searchParams(); let params = this.searchParams();
params.find = this.state.searchQuery;
params.forward = action != SEARCH_BACKWARD; params.forward = action != SEARCH_BACKWARD;
// console.log(params);
this.props.onSearchQuery(params); this.props.onSearchQuery(params);
} }
} }
} }
onReplaceClick() {
if (this.searchbar && this.state.searchQuery) {
if (this.props.onReplaceQuery) {
let params = this.searchParams();
params.find = this.state.searchQuery;
// console.log(params);
this.props.onReplaceQuery(params);
}
}
}
onReplaceAllClick() {
if (this.searchbar && this.state.searchQuery) {
if (this.props.onReplaceAllQuery) {
let params = this.searchParams();
params.find = this.state.searchQuery;
// console.log(params);
this.props.onReplaceAllQuery(params);
}
}
}
onSearchbarShow(isshowed, bar) { onSearchbarShow(isshowed, bar) {
if ( !isshowed ) { if ( !isshowed ) {
this.$repalce.val(''); this.$replace.val('');
} }
} }
onEditorTouchStart(e) { onEditorTouchStart(e) {
this.startPoint = this.pointerPosition(e); this.startPoint = this.pointerPosition(e);
// console.log(this.startPoint);
} }
onEditorTouchEnd(e) { onEditorTouchEnd(e) {
const endPoint = this.pointerPosition(e); const endPoint = this.pointerPosition(e);
// console.log(endPoint);
if ( this.searchbar.enabled ) { if (this.searchbar.enabled) {
const distance = (this.startPoint.x === undefined || this.startPoint.y === undefined) ? 0 : let distance;
if(this.startPoint) {
distance = (!!this.startPoint.x || !!this.startPoint.y) ? 0 :
Math.sqrt((endPoint.x -= this.startPoint.x) * endPoint.x + (endPoint.y -= this.startPoint.y) * endPoint.y); Math.sqrt((endPoint.x -= this.startPoint.x) * endPoint.x + (endPoint.y -= this.startPoint.y) * endPoint.y);
} else {
distance = 0;
}
if ( distance < 1 ) { // 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(); this.searchbar.disable();
} }
} }
@ -178,8 +228,7 @@ class SearchView extends Component {
const touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; const touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
out.x = touch.pageX; out.x = touch.pageX;
out.y = touch.pageY; out.y = touch.pageY;
} else } else if ( e.type == 'mousedown' || e.type == 'mouseup' ) {
if ( e.type == 'mousedown' || e.type == 'mouseup' ) {
out.x = e.pageX; out.x = e.pageX;
out.y = e.pageY; out.y = e.pageY;
} }
@ -187,40 +236,73 @@ class SearchView extends Component {
return out; return out;
} }
changeSearchQuery(value) {
this.setState({
searchQuery: value
});
}
changeReplaceQuery(value) {
this.setState({
replaceQuery: value
});
}
render() { render() {
const usereplace = searchOptions.usereplace; const usereplace = searchOptions.usereplace;
const hidden = {display: "none"}; const hidden = {display: "none"};
const searchQuery = this.state.searchQuery;
const replaceQuery = this.state.replaceQuery;
const isIos = Device.ios;
const { _t } = this.props;
if(this.searchbar && this.searchbar.enabled) {
usereplace ? this.searchbar.el.classList.add('replace') : this.searchbar.el.classList.remove('replace');
}
return ( return (
<form className="searchbar"> <form className="searchbar">
<div className="searchbar-bg"></div> {isIos ? <div className="searchbar-bg"></div> : null}
<div className="searchbar-inner"> <div className="searchbar-inner">
<div className="buttons-row"> <div className="buttons-row searchbar-inner__left">
<a id="idx-btn-search-settings" className="link icon-only" onClick={this.onSettingsClick}> <a id="idx-btn-search-settings" className="link icon-only" onClick={this.onSettingsClick}>
<i className="icon icon-settings" /> <i className="icon icon-settings" />
</a> </a>
</div> </div>
<div className="searchbar-inner__center">
<div className="searchbar-input-wrap"> <div className="searchbar-input-wrap">
<input placeholder="Search" type="search" /> <input placeholder={_t.textSearch} type="search" value={searchQuery}
<i className="searchbar-icon" /> onChange={e => {this.changeSearchQuery(e.target.value)}} />
{isIos ? <i className="searchbar-icon" /> : null}
<span className="input-clear-button" /> <span className="input-clear-button" />
</div> </div>
<div className="searchbar-input-wrap" style={!usereplace ? hidden: null}> <div className="searchbar-input-wrap" style={!usereplace ? hidden: null}>
<input placeholder="Replace" type="search" id="idx-replace-val" /> <input placeholder={_t.textReplace} type="search" id="idx-replace-val" value={replaceQuery}
<i className="searchbar-icon" /> onChange={e => {this.changeReplaceQuery(e.target.value)}} />
{isIos ? <i className="searchbar-icon" /> : null}
<span className="input-clear-button" /> <span className="input-clear-button" />
</div> </div>
</div>
<div className="buttons-row searchbar-inner__right">
<div className="buttons-row buttons-row-replace">
<a id="replace-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} style={!usereplace ? hidden: null} onClick={() => this.onReplaceClick()}>{_t.textReplace}</a>
<a id="replace-all-link" className={"link " + (searchQuery.trim().length ? "" : "disabled")} style={!usereplace ? hidden: null} onClick={() => this.onReplaceAllClick()}>{_t.textReplaceAll}</a>
</div>
<div className="buttons-row"> <div className="buttons-row">
<a className="link icon-only prev" onClick={e => this.onSearchClick(SEARCH_BACKWARD)}> <a className={"link icon-only prev " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onSearchClick(SEARCH_BACKWARD)}>
<i className="icon icon-prev" /> <i className="icon icon-prev" />
</a> </a>
<a className="link icon-only next" onClick={e => this.onSearchClick(SEARCH_FORWARD)}> <a className={"link icon-only next " + (searchQuery.trim().length ? "" : "disabled")} onClick={() => this.onSearchClick(SEARCH_FORWARD)}>
<i className="icon icon-next" /> <i className="icon icon-next" />
</a> </a>
</div> </div>
</div> </div>
</div>
</form> </form>
) )
} }
} }
export {SearchView as default, SearchView, SearchSettingsView}; const SearchViewWithObserver = observer(SearchView);
export {SearchViewWithObserver as SearchView, SearchSettingsView};

View file

@ -4,6 +4,18 @@ import { f7, Popup, Sheet, Popover, Page, Toolbar, Navbar, NavLeft, NavRight, Na
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import {Device} from '../../../utils/device'; import {Device} from '../../../utils/device';
// Utils
const sliceQuote = (text) => {
if (text) {
let sliced = text.slice(0, 100);
if (sliced.length < text.length) {
sliced += '...';
return sliced;
}
return text;
}
};
// Add comment // Add comment
const AddCommentPopup = inject("storeComments")(observer(props => { const AddCommentPopup = inject("storeComments")(observer(props => {
@ -533,16 +545,6 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
const viewMode = !storeAppOptions.canComments; const viewMode = !storeAppOptions.canComments;
const comments = storeComments.sortComments; const comments = storeComments.sortComments;
const sliceQuote = (text) => {
if (text) {
let sliced = text.slice(0, 100);
if (sliced.length < text.length) {
sliced += '...';
return sliced;
}
return text;
}
};
const [clickComment, setComment] = useState(); const [clickComment, setComment] = useState();
const [commentActionsOpened, openActionComment] = useState(false); const [commentActionsOpened, openActionComment] = useState(false);
@ -633,18 +635,123 @@ const ViewComments = ({storeComments, storeAppOptions, onCommentMenuClick, onRes
const _ViewComments = inject('storeComments', 'storeAppOptions')(observer(ViewComments)); const _ViewComments = inject('storeComments', 'storeAppOptions')(observer(ViewComments));
const CommentList = () => { const CommentList = inject("storeComments", "storeAppOptions")(observer(({storeComments, storeAppOptions, onCommentMenuClick, onResolveComment}) => {
return (
<List>
</List>
)
};
const ViewCommentSheet = ({closeCurComments}) => {
const { t } = useTranslation(); const { t } = useTranslation();
const _t = t('Common.Collaboration', {returnObjects: true}); const _t = t('Common.Collaboration', {returnObjects: true});
const isAndroid = Device.android;
const viewMode = !storeAppOptions.canComments;
const comments = storeComments.showComments;
const [currentIndex, setCurrentIndex] = useState(0);
const comment = comments[currentIndex];
const [commentActionsOpened, openActionComment] = useState(false);
const [reply, setReply] = useState();
const [replyActionsOpened, openActionReply] = useState(false);
const onViewPrevComment = () => {
if (currentIndex - 1 < 0) {
setCurrentIndex(comments.length - 1);
} else {
setCurrentIndex(currentIndex - 1);
}
};
const onViewNextComment = () => {
if (currentIndex + 1 === comments.length) {
setCurrentIndex(0);
} else {
setCurrentIndex(currentIndex + 1);
}
};
return (
<Fragment>
<Toolbar position='bottom'>
{!viewMode &&
<Link className='btn-add-reply' href='#' onClick={() => {onCommentMenuClick('addReply', comment);}}>{_t.textAddReply}</Link>
}
<div className='comment-navigation row'>
<Link href='#' onClick={onViewPrevComment}><Icon slot='media' icon='icon-prev'/></Link>
<Link href='#' onClick={onViewNextComment}><Icon slot='media' icon='icon-next'/></Link>
</div>
</Toolbar>
<Page className='page-current-comment'>
<List className='comment-list'>
<ListItem>
<div slot='header' className='comment-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${comment.userColor ? comment.userColor : '#cfcfcf'}`}}>{comment.userInitials}</div>}
<div>
<div className='user-name'>{comment.userName}</div>
<div className='comment-date'>{comment.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='comment-resolve' onClick={() => {onResolveComment(comment);}}><Icon icon={comment.resolved ? 'icon-resolve-comment check' : 'icon-resolve-comment'} /></div>
<div className='comment-menu'
onClick={() => {openActionComment(true);}}
><Icon icon='icon-menu-comment'/></div>
</div>
}
</div>
<div slot='footer'>
{comment.quote && <div className='comment-quote'>{sliceQuote(comment.quote)}</div>}
<div className='comment-text'><pre>{comment.comment}</pre></div>
{comment.replies.length > 0 &&
<ul className='reply-list'>
{comment.replies.map((reply, indexReply) => {
return (
<li key={`reply-${indexReply}`}
className='reply-item'
>
<div className='item-content'>
<div className='item-inner'>
<div className='item-title'>
<div slot='header' className='reply-header'>
<div className='left'>
{isAndroid && <div className='initials' style={{backgroundColor: `${reply.userColor ? reply.userColor : '#cfcfcf'}`}}>{reply.userInitials}</div>}
<div>
<div className='user-name'>{reply.userName}</div>
<div className='reply-date'>{reply.date}</div>
</div>
</div>
{!viewMode &&
<div className='right'>
<div className='reply-menu'
onClick={() => {setReply(reply); openActionReply(true);}}
>
<Icon icon='icon-menu-comment'/>
</div>
</div>
}
</div>
<div slot='footer'>
<div className='reply-text'><pre>{reply.reply}</pre></div>
</div>
</div>
</div>
</div>
</li>
)
})}
</ul>
}
</div>
</ListItem>
</List>
<CommentActions comment={comment} onCommentMenuClick={onCommentMenuClick} opened={commentActionsOpened} openActionComment={openActionComment}/>
<ReplyActions comment={comment} reply={reply} onCommentMenuClick={onCommentMenuClick} opened={replyActionsOpened} openActionReply={openActionReply}/>
</Page>
</Fragment>
)
}));
const ViewCommentSheet = ({closeCurComments, onCommentMenuClick, onResolveComment}) => {
useEffect(() => { useEffect(() => {
f7.sheet.open('#view-comment-sheet'); f7.sheet.open('#view-comment-sheet');
}); });
@ -681,7 +788,6 @@ const ViewCommentSheet = ({closeCurComments}) => {
const swipeEnd = parseInt(touchObj.clientY); const swipeEnd = parseInt(touchObj.clientY);
const dist = swipeEnd - stateStartY; const dist = swipeEnd - stateStartY;
if (isNeedClose) { if (isNeedClose) {
f7.sheet.close('#view-comment-sheet');
closeCurComments(); closeCurComments();
} else if (stateHeight === '90%' && dist > 20) { } else if (stateHeight === '90%' && dist > 20) {
setHeight('45%'); setHeight('45%');
@ -689,28 +795,21 @@ const ViewCommentSheet = ({closeCurComments}) => {
}; };
return ( return (
<Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}> <Sheet id='view-comment-sheet' style={{height: `${stateHeight}`, opacity: `${stateOpacity}`}}>
<Toolbar position='bottom'>
<Link className='btn-add-reply' href='#'>{_t.textAddReply}</Link>
<div className='comment-navigation row'>
<Link href='#'><Icon slot='media' icon='icon-prev'/></Link>
<Link href='#'><Icon slot='media' icon='icon-next'/></Link>
</div>
</Toolbar>
<div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}> <div id='swipe-handler' className='swipe-container' onTouchStart={handleTouchStart} onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd}>
<Icon icon='icon-swipe'/> <Icon icon='icon-swipe'/>
</div> </div>
<CommentList /> <CommentList onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment}/>
</Sheet> </Sheet>
) )
}; };
const ViewCommentPopover = () => { const ViewCommentPopover = ({onCommentMenuClick, onResolveComment}) => {
useEffect(() => { useEffect(() => {
f7.popover.open('#view-comment-popover', '#btn-coauth'); f7.popover.open('#view-comment-popover', '#btn-coauth');
}); });
return ( return (
<Popover id='view-comment-popover'> <Popover id='view-comment-popover' style={{height: '410px'}}>
<CommentList /> <CommentList onCommentMenuClick={onCommentMenuClick} onResolveComment={onResolveComment} />
</Popover> </Popover>
) )
}; };

View file

@ -130,6 +130,9 @@
border-radius: 2px; border-radius: 2px;
} }
} }
}
#view-comment-popover, #view-comment-sheet {
.toolbar { .toolbar {
position: fixed; position: fixed;
background-color: @white; background-color: @white;
@ -155,3 +158,40 @@
} }
} }
} }
#view-comment-popover {
background-color: @white;
.page .page-content {
padding: 16px;
padding-left: 0;
}
.comment-list {
.item-content {
.item-inner {
.comment-header, .reply-header {
padding-right: 0;
}
}
}
}
}
.page-current-comment {
position: relative;
.page-content {
background-color: @white;
}
.comment-list {
ul {
&:before, &:after {
content: none;
}
.item-content .item-inner {
padding-top: 0;
.reply-list .item-content .item-inner {
padding-top: 13px;
}
}
}
}
}

View file

@ -390,4 +390,70 @@
background-color: @white; background-color: @white;
} }
} }
// Find and Replace
.navbar {
.searchbar-input-wrap {
margin-right: 10px;
height: 28px;
}
.buttons-row-replace a {
color: @themeColor;
}
}
.searchbar input[type=search] {
box-sizing: border-box;
width: 100%;
height: 100%;
display: block;
border: none;
appearance: none;
border-radius: 5px;
font-family: inherit;
color: @black;
font-size: 14px;
font-weight: 400;
padding: 0 8px;
background-color: @white;
padding: 0 28px;
}
.searchbar-inner {
&__right {
.buttons-row a.next {
margin-left: 15px;
}
}
}
@media(max-width: 550px)
{
.searchbar-expandable.searchbar-enabled {
top: 0;
.searchbar-inner {
&__left {
margin-right: 15px;
}
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
margin-left: 10px;
}
}
&.replace {
height: 88px;
.searchbar-inner {
&__center {
.searchbar-input-wrap {
margin: 8px 0;
}
}
}
}
}
}
} }

View file

@ -286,4 +286,116 @@
} }
} }
} }
// Find and Replace
.searchbar-inner {
&__center {
flex-wrap: wrap;
}
&__left {
padding-top: 4px;
}
}
.buttons-row-replace a {
color: @white;
}
.navbar {
.searchbar-input-wrap {
height: 32px;
margin-right: 10px;
margin: 4px 0;
}
&-inner {
overflow: initial;
}
}
.searchbar .input-clear-button {
width: 18px;
height: 18px;
&:after {
color: @white;
font-size: 19px;
}
}
.searchbar-icon {
&:after {
color: @white;
font-size: 19px;
}
}
.searchbar input[type=search] {
box-sizing: border-box;
width: 100%;
display: block;
border: none;
appearance: none;
border-radius: 0;
font-family: inherit;
color: @white;
font-size: 16px;
font-weight: 400;
padding: 0;
border-bottom: 1px solid @white;
height: 100%;
padding: 0 36px 0 24px;
background-color: transparent;
background-repeat: no-repeat;
background-position: 0 center;
opacity: 1;
background-size: 24px 24px;
transition-duration: .3s;
.encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" fill="@{white}" height="24" viewBox="0 0 24 24" width="24"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg>');
}
.searchbar input[type=search]::placeholder {
color: @white;
}
.navbar {
.searchbar-expandable.searchbar-enabled {
top: 0;
// height: 100%;
.searchbar-inner {
height: 100%;
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
}
}
&.replace {
height: 96px;
}
}
a.link {
padding: 0 16px;
}
a.icon-only {
width: auto;
height: 48px;
}
.buttons-row-replace a {
color: @white;
}
.searchbar .buttons-row {
align-self: flex-start;
}
}
@media(max-width: 550px) {
.searchbar-expandable.searchbar-enabled {
.searchbar-inner {
&__left {
margin-right: 33px;
}
}
}
}
} }

View file

@ -5,3 +5,7 @@
.document-menu { .document-menu {
width: auto; width: auto;
} }
html.phone .document-menu .list-block .list-button {
padding: 0 10px;
}

View file

@ -7,4 +7,7 @@ i.icon {
height: 24px; height: 24px;
.encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" /><path d="M5 0H14V5H5V0Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" /></svg>'); .encoded-svg-uncolored-mask('<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5 2H0V20H9V24H24V7H19V2H14V3H18V7H9V19H1V3H5V2ZM10 8H23V23H10V8Z" /><path d="M5 0H14V5H5V0Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 12H12V11H21V12Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 16H12V15H21V16Z" /><path fill-rule="evenodd" clip-rule="evenodd" d="M21 20H12V19H21V20Z" /></svg>');
} }
&.icon-prev:after, &.icon-next:after {
content: none;
}
} }

View file

@ -4,16 +4,21 @@
&.icon_mask { &.icon_mask {
background-color: white; background-color: white;
} }
&.icon-prev { &.icon-prev {
width: 22px; width: 22px;
height: 22px; height: 22px;
.encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M16,20.5L15,21.5L4.5,11l0,0l0,0L15,0.5L16,1.5L6.6,11L16,20.5z"/></g></svg>'); .encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M16,20.5L15,21.5L4.5,11l0,0l0,0L15,0.5L16,1.5L6.6,11L16,20.5z"/></g></svg>');
&:after {
display: none;
}
} }
&.icon-next { &.icon-next {
width: 22px; width: 22px;
height: 22px; height: 22px;
.encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M15.5,11L6,1.5l1.1-1.1L17.5,11l0,0l0,0L7.1,21.5L6,20.5L15.5,11z"/></g></svg>'); .encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M15.5,11L6,1.5l1.1-1.1L17.5,11l0,0l0,0L7.1,21.5L6,20.5L15.5,11z"/></g></svg>');
&:after {
display: none;
}
} }
} }
} }

View file

@ -39,7 +39,7 @@
} }
.comment-list { .comment-list {
.item-inner:after { .item-inner:after, li:last-child li .item-inner:after {
content: none; content: none;
} }
.comment-header { .comment-header {
@ -79,4 +79,10 @@
} }
} }
#view-comment-popover {
.toolbar-bottom:after {
content: none;
}
}
} }

View file

@ -4,16 +4,21 @@
&.icon_mask { &.icon_mask {
background-color: black; background-color: black;
} }
&.icon-prev { &.icon-prev {
width: 24px; width: 20px;
height: 24px; height: 20px;
.encoded-svg-background('<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.4219 7.40625L10.8281 12L15.4219 16.5938L14.0156 18L8.01562 12L14.0156 6L15.4219 7.40625Z" fill="@{themeColor}"/></svg>'); .encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{white}"><g><polygon points="5.1,10.9 13.9,2 16,4.1 9.2,11.1 16,17.9 13.9,20 5.1,11.2 5,11.1 "/></g></svg>');
&:after {
display: none;
}
} }
&.icon-next { &.icon-next {
width: 24px; width: 20px;
height: 24px; height: 20px;
.encoded-svg-background('<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.98438 6L15.9844 12L9.98438 18L8.57812 16.5938L13.1719 12L8.57812 7.40625L9.98438 6Z" fill="@{themeColor}"/></svg>'); .encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{white}"><g><polygon points="16.9,10.9 8.1,2 6,4.1 12.8,11.1 6,17.9 8.1,20 16.9,11.2 17,11.1 "/></g></svg>');
&:after {
display: none;
}
} }
} }
} }

View file

@ -14,7 +14,59 @@
} }
} }
.searchbar-input-wrap { .searchbar-inner {
margin-right: 10px; &__center {
display: flex;
align-items: center;
width: 100%;
}
&__right {
display: flex;
align-items: center;
}
}
.searchbar-expandable {
transition-duration: 0s;
}
.buttons-row-replace {
display: flex;
flex-direction: column;
align-items: center;
width: max-content;
a {
font-size: 15px;
height: auto;
display: block;
line-height: normal;
}
}
@media(max-width: 550px)
{
.searchbar-expandable.searchbar-enabled {
.searchbar-inner {
&__left {
min-width: 22px;
max-width: 22px;
}
&__center {
flex-direction: column;
}
&__right {
flex-direction: column-reverse;
}
}
&.replace {
top: 0;
.searchbar-inner {
height: 100%;
&__left {
align-self: flex-start;
}
}
}
}
} }
} }

View file

@ -129,6 +129,21 @@
"textEditReply": "Edit Reply" "textEditReply": "Edit Reply"
} }
}, },
"ContextMenu": {
"menuViewComment": "View Comment",
"menuAddComment": "Add Comment",
"menuMerge": "Merge",
"menuSplit": "Split",
"menuDelete": "Delete",
"menuDeleteTable": "Delete Table",
"menuEdit": "Edit",
"menuAddLink": "Add Link",
"menuReviewChange": "Review Change",
"menuReview": "Review",
"menuOpenLink": "Open Link",
"menuMore": "More",
"menuCancel": "Cancel"
},
"Settings": { "Settings": {
"textCancel": "Cancel", "textCancel": "Cancel",
"textSettings": "Settings", "textSettings": "Settings",
@ -195,7 +210,13 @@
"advDRMPassword": "Password", "advDRMPassword": "Password",
"closeButtonText": "Close File", "closeButtonText": "Close File",
"advDRMOptions": "Protected File", "advDRMOptions": "Protected File",
"txtProtected": "Once you enter the password and open the file, the current password to the file will be reset" "txtProtected": "Once you enter the password and open the file, the current password to the file will be reset",
"textNoTextFound": "Text not found",
"textReplace": "Replace",
"textReplaceAll": "Replace All",
"textCaseSensitive": "Case Sensitive",
"textHighlightResults": "Highlight Results",
"textSearch": "Search"
}, },
"Edit": { "Edit": {
"textClose": "Close", "textClose": "Close",
@ -296,7 +317,6 @@
"textAutomatic": "Automatic", "textAutomatic": "Automatic",
"textAddCustomColor": "Add Custom Color", "textAddCustomColor": "Add Custom Color",
"textCustomColor": "Custom Color", "textCustomColor": "Custom Color",
"textBackground": "Background",
"textFill": "Fill", "textFill": "Fill",
"textBorder": "Border", "textBorder": "Border",
"textEffects": "Effects", "textEffects": "Effects",

View file

@ -4,6 +4,7 @@ import { inject, observer } from "mobx-react";
import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu'; import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu';
import { idContextMenuElement } from '../../../../common/mobile/lib/view/ContextMenu'; import { idContextMenuElement } from '../../../../common/mobile/lib/view/ContextMenu';
import { Device } from '../../../../common/mobile/utils/device'; import { Device } from '../../../../common/mobile/utils/device';
import { withTranslation} from 'react-i18next';
@inject ( stores => ({ @inject ( stores => ({
isEdit: stores.storeAppOptions.isEdit, isEdit: stores.storeAppOptions.isEdit,
@ -70,6 +71,9 @@ class ContextMenu extends ContextMenuController {
initMenuItems() { initMenuItems() {
if ( !Common.EditorApi ) return []; if ( !Common.EditorApi ) return [];
const { t } = this.props;
const _t = t("ContextMenu", { returnObjects: true });
const { isEdit, canViewComments, canReview } = this.props; const { isEdit, canViewComments, canReview } = this.props;
const api = Common.EditorApi.get(); const api = Common.EditorApi.get();
@ -81,7 +85,6 @@ class ContextMenu extends ContextMenuController {
if ( canCopy ) { if ( canCopy ) {
itemsIcon.push({ itemsIcon.push({
caption: /*me.menuCopy*/ 'Copy',
event: 'copy', event: 'copy',
icon: 'icon-copy' icon: 'icon-copy'
}); });
@ -89,7 +92,7 @@ class ContextMenu extends ContextMenuController {
if ( canViewComments && this.isComments && !isEdit ) { if ( canViewComments && this.isComments && !isEdit ) {
itemsText.push({ itemsText.push({
caption: /*me.menuViewComment*/'View Comment', caption: _t.menuViewComment,
event: 'viewcomment' event: 'viewcomment'
}); });
} }
@ -144,7 +147,6 @@ class ContextMenu extends ContextMenuController {
if ( isEdit && !this.isDisconnected ) { if ( isEdit && !this.isDisconnected ) {
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader && canCopy ) { if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader && canCopy ) {
itemsIcon.push({ itemsIcon.push({
// caption: me.menuCut,
event: 'cut', event: 'cut',
icon: 'icon-cut' icon: 'icon-cut'
}); });
@ -155,16 +157,70 @@ class ContextMenu extends ContextMenuController {
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) { if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) {
itemsIcon.push({ itemsIcon.push({
// caption: me.menuPaste,
event: 'paste', event: 'paste',
icon: 'icon-paste' icon: 'icon-paste'
}); });
} }
// For test if ( isTable && api.CheckBeforeMergeCells() && !lockedTable && !lockedHeader) {
itemsText.push({
caption: _t.menuMerge,
event: 'merge'
});
}
if ( isTable && api.CheckBeforeSplitCells() && !lockedTable && !lockedHeader ) {
itemsText.push({
caption: _t.menuSplit,
event: 'split'
});
}
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) {
itemsText.push({
caption: _t.menuDelete,
event: 'delete'
});
}
if ( isTable && !lockedTable && !lockedText && !lockedHeader ) {
itemsText.push({
caption: _t.menuDeleteTable,
event: 'deletetable'
});
}
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ){
itemsText.push({
caption: _t.menuEdit,
event: 'edit'
});
}
// if ( !_.isEmpty(api.can_AddHyperlink()) && !lockedHeader) {
// arrItems.push({
// caption: _t.menuAddLink,
// event: 'addlink'
// });
// }
if ( canReview ) {
if (false /*_inRevisionChange*/) {
itemsText.push({
caption: _t.menuReviewChange,
event: 'reviewchange'
});
} else {
itemsText.push({
caption: _t.menuReview,
event: 'review'
});
}
}
if ( this.isComments && canViewComments ) { if ( this.isComments && canViewComments ) {
itemsText.push({ itemsText.push({
caption: /*me.menuViewComment*/'View Comment', caption: _t.menuViewComment,
event: 'viewcomment' event: 'viewcomment'
}); });
} }
@ -173,102 +229,23 @@ class ContextMenu extends ContextMenuController {
const hideAddComment = !canViewComments || api.can_AddQuotedComment() === false || lockedText || lockedTable || lockedImage || lockedHeader || (!isText && isObject); const hideAddComment = !canViewComments || api.can_AddQuotedComment() === false || lockedText || lockedTable || lockedImage || lockedHeader || (!isText && isObject);
if ( !hideAddComment ) { if ( !hideAddComment ) {
itemsText.push({ itemsText.push({
caption: /*me.menuAddComment*/'Add Comment', caption: _t.menuAddComment,
event: 'addcomment' event: 'addcomment'
}); });
} }
// end test
if ( isTable && api.CheckBeforeMergeCells() && !lockedTable && !lockedHeader) {
itemsText.push({
caption: /*me.menuMerge*/'Merge',
event: 'merge'
});
}
if ( isTable && api.CheckBeforeSplitCells() && !lockedTable && !lockedHeader ) {
itemsText.push({
caption: /*me.menuSplit*/'Split',
event: 'split'
});
}
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ) {
itemsText.push({
caption: /*me.menuDelete*/'Delete',
event: 'delete'
});
}
if ( isTable && !lockedTable && !lockedText && !lockedHeader ) {
itemsText.push({
caption: /*me.menuDeleteTable*/'Delete Table',
event: 'deletetable'
});
}
if ( !lockedText && !lockedTable && !lockedImage && !lockedHeader ){
itemsText.push({
caption: /*me.menuEdit*/'Edit',
event: 'edit'
});
}
// if ( !_.isEmpty(api.can_AddHyperlink()) && !lockedHeader) {
// arrItems.push({
// caption: me.menuAddLink,
// event: 'addlink'
// });
// }
if ( canReview ) {
if (false /*_inRevisionChange*/) {
itemsText.push({
caption: /*me.menuReviewChange*/'Review Change',
event: 'reviewchange'
});
} else {
itemsText.push({
caption: /*me.menuReview*/'Review',
event: 'review'
});
}
}
if ( this.isComments && canViewComments ) {
itemsText.push({
caption: /*me.menuViewComment*/'View Comment',
event: 'viewcomment'
});
}
/*const isObject = isShape || isChart || isImage || isTable;
const hideAddComment = !canViewComments || api.can_AddQuotedComment() === false || lockedText || lockedTable || lockedImage || lockedHeader || (!isText && isObject);
if ( !hideAddComment ) {
itemsText.push({
caption: 'Add Comment',
event: 'addcomment'
});
}*/
} }
} }
if ( isLink ) { if ( isLink ) {
itemsText.push({ itemsText.push({
caption: /*me.menuOpenLink*/'Open Link', caption: _t.menuOpenLink,
event: 'openlink' event: 'openlink'
}); });
} }
if ( Device.phone && itemsText.length > 2 ) { if ( Device.phone && itemsText.length > 2 ) {
// _actionSheets = arrItems.slice(2);
// arrItems = arrItems.slice(0, 2);
// arrItems.push({
// caption: me.menuMore,
// event: 'showActionSheet'
// });
this.extraItems = itemsText.splice(2,itemsText.length, { this.extraItems = itemsText.splice(2,itemsText.length, {
caption: /*me.menuMore*/'More', caption: _t.menuMore,
event: 'showActionSheet' event: 'showActionSheet'
}); });
} }
@ -285,6 +262,11 @@ class ContextMenu extends ContextMenuController {
// event: 'review' // event: 'review'
// }]; // }];
} }
initExtraItems () {
return (this.extraItems && this.extraItems.length > 0 ? this.extraItems : []);
}
} }
export { ContextMenu as default }; const _ContextMenu = withTranslation()(ContextMenu);
export { _ContextMenu as default };

View file

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { List, ListItem, Toggle } from 'framework7-react'; import { List, ListItem, Toggle, Page, Navbar, NavRight, Link } from 'framework7-react';
import { SearchController, SearchView, SearchSettingsView } from '../../../../common/mobile/lib/controller/Search'; import { SearchController, SearchView, SearchSettingsView } from '../../../../common/mobile/lib/controller/Search';
import { f7 } from 'framework7-react'; import { f7 } from 'framework7-react';
import { withTranslation } from 'react-i18next';
import { Device } from '../../../../common/mobile/utils/device';
class SearchSettings extends SearchSettingsView { class SearchSettings extends SearchSettingsView {
constructor(props) { constructor(props) {
@ -18,21 +19,43 @@ class SearchSettings extends SearchSettingsView {
extraSearchOptions() { extraSearchOptions() {
const anc_markup = super.extraSearchOptions(); const anc_markup = super.extraSearchOptions();
const show_popover = !Device.phone;
const { t } = this.props;
const _t = t("Settings", {returnObjects: true});
const markup = <List> const markup = (
<ListItem title="Case sensitive"> <Page>
<Navbar title={_t.textFindAndReplace}>
{!show_popover &&
<NavRight>
<Link popupClose=".search-settings-popup">{_t.textDone}</Link>
</NavRight>
}
</Navbar>
<List>
<ListItem radio title={_t.textFind} name="find-replace-checkbox" checked={!this.state.useReplace} onClick={e => this.onFindReplaceClick('find')} />
<ListItem radio title={_t.textFindAndReplace} name="find-replace-checkbox" checked={this.state.useReplace} onClick={e => this.onFindReplaceClick('replace')} />
</List>
<List>
<ListItem title={_t.textCaseSensitive}>
<Toggle slot="after" className="toggle-case-sensitive" /> <Toggle slot="after" className="toggle-case-sensitive" />
</ListItem> </ListItem>
<ListItem title="Highlight results"> <ListItem title={_t.textHighlightResults}>
<Toggle slot="after" className="toggle-mark-results" defaultChecked onToggleChange={this.onToggleMarkResults} /> <Toggle slot="after" className="toggle-mark-results" defaultChecked onToggleChange={this.onToggleMarkResults} />
</ListItem> </ListItem>
</List>; </List>
</Page>
);
return {...anc_markup, ...markup}; return {...anc_markup, ...markup};
} }
} }
class DESearchView extends SearchView { class DESearchView extends SearchView {
constructor(props) {
super(props);
}
searchParams() { searchParams() {
let params = super.searchParams(); let params = super.searchParams();
@ -57,19 +80,39 @@ class DESearchView extends SearchView {
} }
} }
const Search = props => { const Search = withTranslation()(props => {
const { t } = props;
const _t = t('Settings', {returnObjects: true});
const onSearchQuery = params => { const onSearchQuery = params => {
const api = Common.EditorApi.get(); const api = Common.EditorApi.get();
if ( !params.replace ) { if (params.find && params.find.length) {
if ( !api.asc_findText(params.find, params.forward, params.caseSensitive, params.highlight) ) { if (!api.asc_findText(params.find, params.forward, params.caseSensitive, params.highlight) ) {
f7.dialog.alert('there are no more results', e => { f7.dialog.alert(null, _t.textNoTextFound);
});
} }
} }
}; };
return <DESearchView onSearchQuery={onSearchQuery} /> const onReplaceQuery = params => {
}; const api = Common.EditorApi.get();
export {Search, SearchSettings} if (params.find && params.find.length) {
api.asc_replaceText(params.find, params.replace, false, params.caseSensitive, params.highlight);
}
}
const onReplaceAllQuery = params => {
const api = Common.EditorApi.get();
if (params.find && params.find.length) {
api.asc_replaceText(params.find, params.replace, true, params.caseSensitive, params.highlight);
}
}
return <DESearchView _t={_t} onSearchQuery={onSearchQuery} onReplaceQuery={onReplaceQuery} onReplaceAllQuery={onReplaceAllQuery} />
});
const SearchSettingsWithTranslation = withTranslation()(SearchSettings);
export {Search, SearchSettingsWithTranslation as SearchSettings}

View file

@ -79,7 +79,7 @@
&.icon-search { &.icon-search {
width: 22px; width: 22px;
height: 22px; height: 22px;
.encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 22 22" fill="@{navBarIconColor}"><g><path d="M19.5,16.8L16,13.3c0.7-1.1,1.1-2.4,1.1-3.8C17,5.4,13.6,2,9.5,2S2,5.4,2,9.5S5.4,17,9.5,17c1.4,0,2.7-0.4,3.8-1.1l3.5,3.5c0.7,0.7,1.9,0.7,2.6,0C20.2,18.7,20.2,17.6,19.5,16.8z M9.5,15.3c-3.2,0-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8s5.8,2.6,5.8,5.8S12.7,15.3,9.5,15.3z"/></g></svg>'); .encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M19.5,16.8L16,13.3c0.7-1.1,1.1-2.4,1.1-3.8C17,5.4,13.6,2,9.5,2S2,5.4,2,9.5S5.4,17,9.5,17c1.4,0,2.7-0.4,3.8-1.1l3.5,3.5c0.7,0.7,1.9,0.7,2.6,0C20.2,18.7,20.2,17.6,19.5,16.8z M9.5,15.3c-3.2,0-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8s5.8,2.6,5.8,5.8S12.7,15.3,9.5,15.3z"/></g></svg>');
} }
&.icon-reader { &.icon-reader {
width: 22px; width: 22px;

View file

@ -70,15 +70,17 @@ export default class MainPage extends Component {
<Link id='btn-coauth' href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link> <Link id='btn-coauth' href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link>
<Link id='btn-settings' icon='icon-settings' href={false} onClick={e => this.handleClickToOpenOptions('settings')}></Link> <Link id='btn-settings' icon='icon-settings' href={false} onClick={e => this.handleClickToOpenOptions('settings')}></Link>
</NavRight> </NavRight>
{ Device.phone ? null : <Search /> } {/* { Device.phone ? null : <Search /> } */}
<Search useSuspense={false} />
</Navbar> </Navbar>
{/* Page content */} {/* Page content */}
<View id="editor_sdk"> <View id="editor_sdk">
</View> </View>
{ {/* {
Device.phone ? null : <SearchSettings /> Device.phone ? null : <SearchSettings />
} } */}
<SearchSettings useSuspense={false} />
{ {
!this.state.editOptionsVisible ? null : !this.state.editOptionsVisible ? null :
<EditOptions onclosed={this.handleOptionsViewClosed.bind(this, 'edit')} /> <EditOptions onclosed={this.handleOptionsViewClosed.bind(this, 'edit')} />

View file

@ -3,20 +3,20 @@ import {makeObservable, action, observable} from 'mobx';
export class storeApplicationSettings { export class storeApplicationSettings {
constructor() { constructor() {
makeObservable(this, { makeObservable(this, {
unitMeasurement: observable unitMeasurement: observable,
, isSpellChecking: observable isSpellChecking: observable,
, isNonprintingCharacters: observable isNonprintingCharacters: observable,
, isHiddenTableBorders: observable isHiddenTableBorders: observable,
, isComments: observable isComments: observable,
, isResolvedComments: observable isResolvedComments: observable,
, macrosMode: observable macrosMode: observable,
, changeSpellCheck: action changeSpellCheck: action,
, changeUnitMeasurement: action changeUnitMeasurement: action,
, changeNoCharacters: action changeNoCharacters: action,
, changeShowTableEmptyLine: action changeShowTableEmptyLine: action,
, changeDisplayComments: action changeDisplayComments: action,
, changeDisplayResolved: action changeDisplayResolved: action,
, changeMacrosSettings: action changeMacrosSettings: action
}) })
} }

View file

@ -1,6 +1,22 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeChartSettings { export class storeChartSettings {
constructor() {
makeObservable(this, {
chartStyles: observable,
fillColor: observable,
borderColor: observable,
clearChartStyles: action,
updateChartStyles: action,
styles: computed,
types: computed,
setFillColor: action,
getFillColor: action,
setBorderColor: action,
initBorderColor: action
});
}
wrapTypesTransform () { wrapTypesTransform () {
const map = [ const map = [
{ ui:'inline', sdk: Asc.c_oAscWrapStyle2.Inline }, { ui:'inline', sdk: Asc.c_oAscWrapStyle2.Inline },
@ -56,14 +72,18 @@ export class storeChartSettings {
} }
// style // style
@observable chartStyles = null;
@action clearChartStyles () { chartStyles = null;
clearChartStyles () {
this.chartStyles = null; this.chartStyles = null;
} }
@action updateChartStyles (styles) {
updateChartStyles (styles) {
this.chartStyles = styles; this.chartStyles = styles;
} }
@computed get styles () {
get styles () {
if (!this.chartStyles) return null; if (!this.chartStyles) return null;
const widthContainer = document.querySelector(".page-content").clientWidth; const widthContainer = document.querySelector(".page-content").clientWidth;
const columns = parseInt(widthContainer / 70); // magic const columns = parseInt(widthContainer / 70); // magic
@ -78,7 +98,8 @@ export class storeChartSettings {
}); });
return styles; return styles;
} }
@computed get types () {
get types () {
const types = [ const types = [
{ type: Asc.c_oAscChartTypeSettings.barNormal, thumb: 'chart-03.png'}, { type: Asc.c_oAscChartTypeSettings.barNormal, thumb: 'chart-03.png'},
{ type: Asc.c_oAscChartTypeSettings.barStacked, thumb: 'chart-02.png'}, { type: Asc.c_oAscChartTypeSettings.barStacked, thumb: 'chart-02.png'},
@ -120,10 +141,13 @@ export class storeChartSettings {
} }
// Fill Color // Fill Color
@observable fillColor = undefined;
fillColor = undefined;
setFillColor (color) { setFillColor (color) {
this.fillColor = color; this.fillColor = color;
} }
getFillColor (shapeProperties) { getFillColor (shapeProperties) {
let fill = shapeProperties.get_fill(); let fill = shapeProperties.get_fill();
const fillType = fill.get_type(); const fillType = fill.get_type();
@ -144,10 +168,13 @@ export class storeChartSettings {
} }
// Border size and border color // Border size and border color
@observable borderColor;
borderColor;
setBorderColor (color) { setBorderColor (color) {
this.borderColor = color; this.borderColor = color;
} }
initBorderColor (stroke) { initBorderColor (stroke) {
let color = 'transparent'; let color = 'transparent';
if (stroke && stroke.get_type() == Asc.c_oAscStrokeType.STROKE_COLOR) { if (stroke && stroke.get_type() == Asc.c_oAscStrokeType.STROKE_COLOR) {
@ -164,6 +191,7 @@ export class storeChartSettings {
this.borderColor = color; this.borderColor = color;
return color; return color;
} }
borderSizeTransform () { borderSizeTransform () {
const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6]; const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6];

View file

@ -1,21 +1,33 @@
import { action, observable } from "mobx"; import {action, observable, makeObservable} from "mobx";
export class storeDocumentInfo { export class storeDocumentInfo {
@observable infoObj = { constructor() {
makeObservable(this, {
infoObj: observable,
isLoaded: observable,
dataDoc: observable,
switchIsLoaded: action,
changeCount: action,
setDataDoc: action
});
}
infoObj = {
pageCount: 0, pageCount: 0,
wordsCount: 0, wordsCount: 0,
paragraphCount: 0, paragraphCount: 0,
symbolsCount: 0, symbolsCount: 0,
symbolsWSCount: 0, symbolsWSCount: 0,
}; };
@observable isLoaded = false;
@observable dataDoc;
@action switchIsLoaded(value) { isLoaded = false;
dataDoc;
switchIsLoaded(value) {
this.isLoaded = value; this.isLoaded = value;
} }
@action changeCount(obj) { changeCount(obj) {
if (obj) { if (obj) {
if (obj.get_PageCount() > -1) if (obj.get_PageCount() > -1)
this.infoObj.pageCount = obj.get_PageCount(); this.infoObj.pageCount = obj.get_PageCount();
@ -30,7 +42,7 @@ export class storeDocumentInfo {
} }
} }
@action setDataDoc(obj) { setDataDoc(obj) {
this.dataDoc = obj; this.dataDoc = obj;
} }
} }

View file

@ -1,15 +1,31 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeDocumentSettings { export class storeDocumentSettings {
@observable isPortrait = true; constructor() {
@action resetPortrait (isPortrait) { makeObservable(this, {
isPortrait: observable,
widthDocument: observable,
heightDocument: observable,
allSchemes: observable,
resetPortrait: action,
changeDocSize: action,
pageSizesIndex: computed,
addSchemes: action
});
}
isPortrait = true;
resetPortrait (isPortrait) {
this.isPortrait = isPortrait === true; this.isPortrait = isPortrait === true;
} }
//Document Formats //Document Formats
@observable widthDocument;
@observable heightDocument; widthDocument;
@action changeDocSize (width, height) { heightDocument;
changeDocSize (width, height) {
let w = width; let w = width;
let h = height; let h = height;
if (!this.isPortrait) { if (!this.isPortrait) {
@ -20,6 +36,7 @@ export class storeDocumentSettings {
this.widthDocument = w; this.widthDocument = w;
this.heightDocument = h; this.heightDocument = h;
} }
getPageSizesList () { getPageSizesList () {
const txtCm = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.cm); const txtCm = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.cm);
const pageSizes = [ const pageSizes = [
@ -43,7 +60,8 @@ export class storeDocumentSettings {
]; ];
return pageSizes; return pageSizes;
} }
@computed get pageSizesIndex () {
get pageSizesIndex () {
let w = this.widthDocument; let w = this.widthDocument;
let h = this.heightDocument; let h = this.heightDocument;
let ind = -1; let ind = -1;
@ -61,9 +79,9 @@ export class storeDocumentSettings {
// Color Schemes // Color Schemes
@observable allSchemes; allSchemes;
@action addSchemes(arr) { addSchemes(arr) {
this.allSchemes = arr; this.allSchemes = arr;
} }

View file

@ -1,14 +1,32 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeFocusObjects { export class storeFocusObjects {
@observable _focusObjects = []; constructor() {
@observable _headerType = 1; makeObservable(this, {
_focusObjects: observable,
_headerType: observable,
resetFocusObjects: action,
settings: computed,
headerType: computed,
headerObject: computed,
paragraphObject: computed,
shapeObject: computed,
imageObject: computed,
tableObject: computed,
isTableInStack: computed,
chartObject: computed,
linkObject: computed
});
}
@action resetFocusObjects (objects) { _focusObjects = [];
_headerType = 1;
resetFocusObjects (objects) {
this._focusObjects = objects; this._focusObjects = objects;
} }
@computed get settings() { get settings() {
const _settings = []; const _settings = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
let type = object.get_ObjectType(); let type = object.get_ObjectType();
@ -34,7 +52,8 @@ export class storeFocusObjects {
} }
return _settings.filter((value, index, self) => self.indexOf(value) === index); return _settings.filter((value, index, self) => self.indexOf(value) === index);
} }
@computed get headerType() {
get headerType() {
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
const type = object.get_ObjectType(); const type = object.get_ObjectType();
if (Asc.c_oAscTypeSelectElement.Header === type) { if (Asc.c_oAscTypeSelectElement.Header === type) {
@ -43,7 +62,8 @@ export class storeFocusObjects {
} }
return this._headerType; return this._headerType;
} }
@computed get headerObject() {
get headerObject() {
const headers = []; const headers = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Header) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Header) {
@ -57,7 +77,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get paragraphObject() {
get paragraphObject() {
const paragraphs = []; const paragraphs = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) { if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) {
@ -71,7 +92,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get shapeObject() {
get shapeObject() {
const shapes = []; const shapes = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Image) { if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Image) {
@ -87,7 +109,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get imageObject() {
get imageObject() {
const images = []; const images = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image) {
@ -104,7 +127,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get tableObject() {
get tableObject() {
const tables = []; const tables = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
@ -118,7 +142,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get isTableInStack() {
get isTableInStack() {
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
return true; return true;
@ -126,7 +151,8 @@ export class storeFocusObjects {
} }
return false; return false;
} }
@computed get chartObject() {
get chartObject() {
const charts = []; const charts = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectValue() && object.get_ObjectValue().get_ChartProperties()) { if (object.get_ObjectValue() && object.get_ObjectValue().get_ChartProperties()) {
@ -140,7 +166,8 @@ export class storeFocusObjects {
return undefined; return undefined;
} }
} }
@computed get linkObject() {
get linkObject() {
const links = []; const links = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {

View file

@ -1,9 +1,16 @@
import {action, observable} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storePalette { export class storePalette {
@observable customColors = []; constructor() {
makeObservable(this, {
customColors: observable,
changeCustomColors: action
});
}
@action changeCustomColors (colors) { customColors = [];
changeCustomColors (colors) {
this.customColors = colors; this.customColors = colors;
} }
} }

View file

@ -1,18 +1,33 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeParagraphSettings { export class storeParagraphSettings {
@observable styles = []; constructor() {
@observable styleThumbSize = null; makeObservable(this, {
@observable styleName = undefined; styles: observable,
styleThumbSize: observable,
styleName: observable,
backColor: observable,
initEditorStyles: action,
paragraphStyles: computed,
changeParaStyleName: action,
setBackColor: action,
getBackgroundColor: action
});
}
@action initEditorStyles (styles) { styles = [];
styleThumbSize = null;
styleName = undefined;
initEditorStyles (styles) {
this.styles = styles.get_MergedStyles(); this.styles = styles.get_MergedStyles();
this.styleThumbSize = { this.styleThumbSize = {
width : styles.STYLE_THUMBNAIL_WIDTH, width : styles.STYLE_THUMBNAIL_WIDTH,
height : styles.STYLE_THUMBNAIL_HEIGHT height : styles.STYLE_THUMBNAIL_HEIGHT
}; };
} }
@computed get paragraphStyles () {
get paragraphStyles () {
let _styles = []; let _styles = [];
for (let style of this.styles) { for (let style of this.styles) {
_styles.push({ _styles.push({
@ -22,14 +37,17 @@ export class storeParagraphSettings {
} }
return _styles; return _styles;
} }
@action changeParaStyleName (name) {
changeParaStyleName (name) {
this.styleName = name; this.styleName = name;
} }
@observable backColor = undefined; backColor = undefined;
setBackColor (color) { setBackColor (color) {
this.backColor = color; this.backColor = color;
} }
getBackgroundColor (paragraphObject) { getBackgroundColor (paragraphObject) {
const shade = paragraphObject.get_Shade(); const shade = paragraphObject.get_Shade();
let backColor = 'transparent'; let backColor = 'transparent';

View file

@ -1,15 +1,24 @@
import {action, observable, computed} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storeReview { export class storeReview {
@observable displayMode = 'markup'; constructor() {
makeObservable(this, {
displayMode: observable,
dataChanges: observable,
changeDisplayMode: action,
changeArrReview: action
});
}
@action changeDisplayMode (mode) { displayMode = 'markup';
changeDisplayMode (mode) {
this.displayMode = mode; this.displayMode = mode;
} }
@observable dataChanges = []; dataChanges = [];
@action changeArrReview (data) { changeArrReview (data) {
this.dataChanges = data && data.length > 0 ? data : []; this.dataChanges = data && data.length > 0 ? data : [];
} }
} }

View file

@ -1,6 +1,17 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeShapeSettings { export class storeShapeSettings {
constructor() {
makeObservable(this, {
fillColor: observable,
borderColorView: observable,
setFillColor: action,
getFillColor: action,
setBorderColor: action,
initBorderColorView: action
});
}
getStyleGroups () { getStyleGroups () {
const styles = [ const styles = [
{ {
@ -136,6 +147,7 @@ export class storeShapeSettings {
} }
return groups; return groups;
} }
wrapTypesTransform () { wrapTypesTransform () {
const map = [ const map = [
{ ui:'inline', sdk: Asc.c_oAscWrapStyle2.Inline }, { ui:'inline', sdk: Asc.c_oAscWrapStyle2.Inline },
@ -191,10 +203,13 @@ export class storeShapeSettings {
} }
// Fill Color // Fill Color
@observable fillColor = undefined;
fillColor = undefined;
setFillColor (color) { setFillColor (color) {
this.fillColor = color; this.fillColor = color;
} }
getFillColor (shapeObject) { getFillColor (shapeObject) {
let fill = shapeObject.get_ShapeProperties().get_fill(); let fill = shapeObject.get_ShapeProperties().get_fill();
const fillType = fill.get_type(); const fillType = fill.get_type();
@ -215,10 +230,13 @@ export class storeShapeSettings {
} }
// Border size and color // Border size and color
@observable borderColorView;
borderColorView;
setBorderColor (color) { setBorderColor (color) {
this.borderColorView = color; this.borderColorView = color;
} }
initBorderColorView (shapeObject) { initBorderColorView (shapeObject) {
const stroke = shapeObject.get_ShapeProperties().get_stroke(); const stroke = shapeObject.get_ShapeProperties().get_stroke();
let color = 'transparent'; let color = 'transparent';
@ -236,6 +254,7 @@ export class storeShapeSettings {
this.borderColorView = color; this.borderColorView = color;
return color; return color;
} }
borderSizeTransform () { borderSizeTransform () {
const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6]; const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6];

View file

@ -3,14 +3,25 @@ import {f7} from 'framework7-react';
export class storeTableSettings { export class storeTableSettings {
constructor() { constructor() {
makeObservable(this) makeObservable(this, {
_templates: observable,
cellBorders: observable,
cellBorderWidth: observable,
cellBorderColor: observable,
initTableTemplates: action,
styles: computed,
updateCellBorderWidth: action,
updateCellBorderColor: action,
});
} }
@observable _templates = []; _templates = [];
@action initTableTemplates (templates) {
initTableTemplates (templates) {
this._templates = templates; this._templates = templates;
} }
@computed get styles () {
get styles () {
let styles = []; let styles = [];
for (let template of this._templates) { for (let template of this._templates) {
styles.push({ styles.push({
@ -69,9 +80,10 @@ export class storeTableSettings {
} }
// Border style // Border style
@observable cellBorders;
@observable cellBorderWidth = 0.5; cellBorders;
@observable cellBorderColor = '000000'; cellBorderWidth = 0.5;
cellBorderColor = '000000';
borderSizeTransform () { borderSizeTransform () {
const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6]; const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6];

View file

@ -1,25 +1,64 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeTextSettings { export class storeTextSettings {
@observable fontsArray = []; constructor() {
@observable fontName = ''; makeObservable(this, {
@observable fontSize = undefined; fontsArray: observable,
@observable isBold = false; fontName: observable,
@observable isItalic = false; fontSize: observable,
@observable isUnderline = false; isBold: observable,
@observable isStrikethrough = false; isItalic: observable,
@observable typeBaseline = undefined; isUnderline: observable,
@observable listType = undefined; isStrikethrough: observable,
@observable typeBullets = undefined; typeBaseline: observable,
@observable typeNumbers = undefined; listType: observable,
@observable paragraphAlign = undefined; typeBullets: observable,
@observable textColor = undefined; typeNumbers: observable,
@observable customTextColors = []; paragraphAlign: observable,
@observable lineSpacing = undefined; textColor: observable,
@observable backgroundColor = undefined; customTextColors: observable,
lineSpacing: observable,
backgroundColor: observable,
initEditorFonts: action,
resetFontName: action,
resetFontSize: action,
resetIsBold: action,
resetIsItalic: action,
resetIsUnderline: action,
resetIsStrikeout: action,
resetTypeBaseline: action,
isSuperscript: computed,
isSubscript: computed,
resetListType: action,
resetBullets: action,
resetNumbers: action,
resetParagraphAlign: action,
resetTextColor: action,
changeCustomTextColors: action,
resetLineSpacing: action,
resetBackgroundColor: action
});
}
fontsArray = [];
fontName = '';
fontSize = undefined;
isBold = false;
isItalic = false;
isUnderline = false;
isStrikethrough = false;
typeBaseline = undefined;
listType = undefined;
typeBullets = undefined;
typeNumbers = undefined;
paragraphAlign = undefined;
textColor = undefined;
customTextColors = [];
lineSpacing = undefined;
backgroundColor = undefined;
@action initEditorFonts (fonts, select) { initEditorFonts (fonts, select) {
let array = []; let array = [];
for (let font of fonts) { for (let font of fonts) {
let fontId = font.asc_getFontId(); let fontId = font.asc_getFontId();
@ -33,49 +72,49 @@ export class storeTextSettings {
} }
this.fontsArray = array; this.fontsArray = array;
} }
@action resetFontName (font) { resetFontName (font) {
let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName(); let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName();
this.fontName = name; this.fontName = name;
} }
@action resetFontSize (size) { resetFontSize (size) {
this.fontSize = size; this.fontSize = size;
} }
@action resetIsBold (isBold) { resetIsBold (isBold) {
this.isBold = isBold; this.isBold = isBold;
} }
@action resetIsItalic (isItalic) { resetIsItalic (isItalic) {
this.isItalic = isItalic; this.isItalic = isItalic;
} }
@action resetIsUnderline (isUnderline) { resetIsUnderline (isUnderline) {
this.isUnderline = isUnderline; this.isUnderline = isUnderline;
} }
@action resetIsStrikeout (isStrikethrough) { resetIsStrikeout (isStrikethrough) {
this.isStrikethrough = isStrikethrough; this.isStrikethrough = isStrikethrough;
} }
// vertical align // vertical align
@action resetTypeBaseline (typeBaseline) { resetTypeBaseline (typeBaseline) {
this.typeBaseline = typeBaseline; this.typeBaseline = typeBaseline;
} }
@computed get isSuperscript() { get isSuperscript() {
return (this.typeBaseline === 1); return (this.typeBaseline === 1);
} }
@computed get isSubscript() { get isSubscript() {
return (this.typeBaseline === 2); return (this.typeBaseline === 2);
} }
// bullets // bullets
@action resetListType (type) { resetListType (type) {
this.listType = type; this.listType = type;
} }
@action resetBullets (type) { resetBullets (type) {
this.typeBullets = type; this.typeBullets = type;
} }
@action resetNumbers (type) { resetNumbers (type) {
this.typeNumbers = type; this.typeNumbers = type;
} }
@action resetParagraphAlign (align) { resetParagraphAlign (align) {
let value; let value;
switch (align) { switch (align) {
case 0: case 0:
@ -94,7 +133,7 @@ export class storeTextSettings {
this.paragraphAlign = value; this.paragraphAlign = value;
} }
@action resetTextColor (color) { resetTextColor (color) {
let value; let value;
if (color) { if (color) {
if (color.get_auto()) { if (color.get_auto()) {
@ -113,16 +152,16 @@ export class storeTextSettings {
this.textColor = value; this.textColor = value;
} }
@action changeCustomTextColors (colors) { changeCustomTextColors (colors) {
this.customTextColors = colors; this.customTextColors = colors;
} }
@action resetLineSpacing (vc) { resetLineSpacing (vc) {
let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line(); let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line();
this.lineSpacing = line; this.lineSpacing = line;
} }
@action resetBackgroundColor (color) { resetBackgroundColor (color) {
let value; let value;
if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) { if (color.get_type() == Asc.c_oAscColor.COLOR_TYPE_SCHEME) {
value = { value = {

View file

@ -79,21 +79,21 @@ const PageAdvancedSettings = props => {
</List> </List>
<List> <List>
<ListItem title={t('Edit.textSpaceBetweenParagraphs')}> <ListItem title={t('Edit.textSpaceBetweenParagraphs')}>
<Toggle checked={spaceBetween} onToggleChange={() => {props.onSpaceBetween(!spaceBetween)}}/> <Toggle checked={spaceBetween} onChange={() => {props.onSpaceBetween(!spaceBetween)}}/>
</ListItem> </ListItem>
</List> </List>
<List> <List>
<ListItem title={t('Edit.textPageBreakBefore')}> <ListItem title={t('Edit.textPageBreakBefore')}>
<Toggle checked={breakBefore} onToggleChange={() => {props.onBreakBefore(!breakBefore)}}/> <Toggle checked={breakBefore} onChange={() => {props.onBreakBefore(!breakBefore)}}/>
</ListItem> </ListItem>
<ListItem title={t('Edit.textOrphanControl')}> <ListItem title={t('Edit.textOrphanControl')}>
<Toggle checked={orphanControl} onToggleChange={() => {props.onOrphan(!orphanControl)}}/> <Toggle checked={orphanControl} onChange={() => {props.onOrphan(!orphanControl)}}/>
</ListItem> </ListItem>
<ListItem title={t('Edit.textKeepLinesTogether')}> <ListItem title={t('Edit.textKeepLinesTogether')}>
<Toggle checked={keepTogether} onToggleChange={() => {props.onKeepTogether(!keepTogether)}}/> <Toggle checked={keepTogether} onChange={() => {props.onKeepTogether(!keepTogether)}}/>
</ListItem> </ListItem>
<ListItem title={t('Edit.textKeepWithNext')}> <ListItem title={t('Edit.textKeepWithNext')}>
<Toggle checked={keepWithNext} onToggleChange={() => {props.onKeepNext(!keepWithNext)}}/> <Toggle checked={keepWithNext} onChange={() => {props.onKeepNext(!keepWithNext)}}/>
</ListItem> </ListItem>
</List> </List>
</Page> </Page>

View file

@ -317,10 +317,10 @@ const PageWrap = props => {
} }
<List> <List>
<ListItem title={_t.textMoveWithText} className={'inline' === wrapType ? 'disabled' : ''}> <ListItem title={_t.textMoveWithText} className={'inline' === wrapType ? 'disabled' : ''}>
<Toggle checked={moveText} onToggleChange={() => {props.onMoveText(!moveText)}}/> <Toggle checked={moveText} onChange={() => {props.onMoveText(!moveText)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textAllowOverlap}> <ListItem title={_t.textAllowOverlap}>
<Toggle checked={overlap} onToggleChange={() => {props.onOverlap(!overlap)}}/> <Toggle checked={overlap} onChange={() => {props.onOverlap(!overlap)}}/>
</ListItem> </ListItem>
</List> </List>
{ {

View file

@ -21,10 +21,10 @@ const PageTableOptions = props => {
<Navbar title={_t.textOptions} backLink={_t.textBack} /> <Navbar title={_t.textOptions} backLink={_t.textBack} />
<List> <List>
<ListItem title={_t.textRepeatAsHeaderRow} className={isRepeat === null ? 'disabled' : ''}> <ListItem title={_t.textRepeatAsHeaderRow} className={isRepeat === null ? 'disabled' : ''}>
<Toggle checked={isRepeat} onToggleChange={() => {props.onOptionRepeat(!isRepeat)}}/> <Toggle checked={isRepeat} onChange={() => {props.onOptionRepeat(!isRepeat)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textResizeToFitContent}> <ListItem title={_t.textResizeToFitContent}>
<Toggle checked={isResize} onToggleChange={() => {props.onOptionResize(!isResize)}}/> <Toggle checked={isResize} onChange={() => {props.onOptionResize(!isResize)}}/>
</ListItem> </ListItem>
</List> </List>
<BlockTitle>{_t.textCellMargins}</BlockTitle> <BlockTitle>{_t.textCellMargins}</BlockTitle>
@ -79,7 +79,7 @@ const PageWrap = props => {
</List> </List>
<List> <List>
<ListItem title={_t.textMoveWithText} className={'inline' === wrapType ? 'disabled' : ''}> <ListItem title={_t.textMoveWithText} className={'inline' === wrapType ? 'disabled' : ''}>
<Toggle checked={moveText} onToggleChange={() => {props.onWrapMoveText(!moveText)}}/> <Toggle checked={moveText} onChange={() => {props.onWrapMoveText(!moveText)}}/>
</ListItem> </ListItem>
</List> </List>
{ {
@ -189,24 +189,24 @@ const PageStyleOptions = props => {
<Navbar title={_t.textOptions} backLink={_t.textBack}/> <Navbar title={_t.textOptions} backLink={_t.textBack}/>
<List> <List>
<ListItem title={_t.textHeaderRow}> <ListItem title={_t.textHeaderRow}>
<Toggle checked={isFirstRow} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 0, !isFirstRow)}}/> <Toggle checked={isFirstRow} onChange={() => {props.onCheckTemplateChange(tableLook, 0, !isFirstRow)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textTotalRow}> <ListItem title={_t.textTotalRow}>
<Toggle checked={isLastRow} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 1, !isLastRow)}}/> <Toggle checked={isLastRow} onChange={() => {props.onCheckTemplateChange(tableLook, 1, !isLastRow)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textBandedRow}> <ListItem title={_t.textBandedRow}>
<Toggle checked={isBandHor} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 2, !isBandHor)}}/> <Toggle checked={isBandHor} onChange={() => {props.onCheckTemplateChange(tableLook, 2, !isBandHor)}}/>
</ListItem> </ListItem>
</List> </List>
<List> <List>
<ListItem title={_t.textFirstColumn}> <ListItem title={_t.textFirstColumn}>
<Toggle checked={isFirstCol} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 3, !isFirstCol)}}/> <Toggle checked={isFirstCol} onChange={() => {props.onCheckTemplateChange(tableLook, 3, !isFirstCol)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textLastColumn}> <ListItem title={_t.textLastColumn}>
<Toggle checked={isLastCol} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 4, !isLastCol)}}/> <Toggle checked={isLastCol} onChange={() => {props.onCheckTemplateChange(tableLook, 4, !isLastCol)}}/>
</ListItem> </ListItem>
<ListItem title={_t.textBandedColumn}> <ListItem title={_t.textBandedColumn}>
<Toggle checked={isBandVer} onToggleChange={() => {props.onCheckTemplateChange(tableLook, 5, !isBandVer)}}/> <Toggle checked={isBandVer} onChange={() => {props.onCheckTemplateChange(tableLook, 5, !isBandVer)}}/>
</ListItem> </ListItem>
</List> </List>
</Page> </Page>

View file

@ -64,6 +64,14 @@ const SettingsList = inject("storeAppOptions")( observer( withTranslation()( pro
props.onOptionClick(page) props.onOptionClick(page)
}; };
const closeModal = () => {
if (Device.phone) {
f7.sheet.close('.settings-popup', true);
} else {
f7.popover.close('#settings-popover');
}
};
useEffect(() => { useEffect(() => {
}); });
@ -100,7 +108,7 @@ const SettingsList = inject("storeAppOptions")( observer( withTranslation()( pro
{navbar} {navbar}
<List> <List>
{!props.inPopover && {!props.inPopover &&
<ListItem title={!_isEdit ? _t.textFind : _t.textFindAndReplace}> <ListItem title={!_isEdit ? _t.textFind : _t.textFindAndReplace} link="#" searchbarEnable='.searchbar' onClick={closeModal}>
<Icon slot="media" icon="icon-search"></Icon> <Icon slot="media" icon="icon-search"></Icon>
</ListItem> </ListItem>
} }

View file

@ -71,7 +71,14 @@
"textAddress": "address:", "textAddress": "address:",
"textEmail": "email:", "textEmail": "email:",
"textTel": "tel:", "textTel": "tel:",
"textPoweredBy": "Powered By" "textPoweredBy": "Powered By",
"textReplaceAll": "Replace All",
"textFind": "Find",
"textSearch": "Search",
"textCaseSensitive": "Case Sensitive",
"textHighlight": "Highlight Results",
"textReplace": "Replace",
"textNoTextFound": "Text not Found"
}, },
"Add": { "Add": {
"textSlide": "Slide", "textSlide": "Slide",
@ -244,7 +251,15 @@
"textRemoveLink": "Remove Link", "textRemoveLink": "Remove Link",
"textDisplay": "Display", "textDisplay": "Display",
"textScreenTip": "Screen Tip", "textScreenTip": "Screen Tip",
"textDefault": "Selected text" "textDefault": "Selected text",
"textReplaceAll": "Replace All",
"textFind": "Find",
"textFindAndReplace": "Find and Replace",
"textDone": "Done",
"textSearch": "Search",
"textCaseSensitive": "Case Sensitive",
"textHighlight": "Highlight Results",
"textNoTextFound": "Text not Found"
} }
}, },
"Common": { "Common": {

View file

@ -0,0 +1,100 @@
import React from 'react';
import { List, ListItem, Toggle, Page, Navbar, NavRight, Link } from 'framework7-react';
import { SearchController, SearchView, SearchSettingsView } from '../../../../common/mobile/lib/controller/Search';
import { f7 } from 'framework7-react';
import { withTranslation } from 'react-i18next';
import { Device } from '../../../../common/mobile/utils/device';
class SearchSettings extends SearchSettingsView {
constructor(props) {
super(props);
}
extraSearchOptions() {
const anc_markup = super.extraSearchOptions();
const show_popover = !Device.phone;
const { t } = this.props;
const _t = t("View.Settings", {returnObjects: true});
const markup = (
<Page>
<Navbar title={_t.textFindAndReplace}>
{!show_popover &&
<NavRight>
<Link popupClose=".search-settings-popup">{_t.textDone}</Link>
</NavRight>
}
</Navbar>
<List>
<ListItem radio title={_t.textFind} name="find-replace-checkbox" checked={!this.state.useReplace} onClick={e => this.onFindReplaceClick('find')} />
<ListItem radio title={_t.textFindAndReplace} name="find-replace-checkbox" checked={this.state.useReplace} onClick={e => this.onFindReplaceClick('replace')} />
</List>
<List>
<ListItem title={_t.textCaseSensitive}>
<Toggle slot="after" className="toggle-case-sensitive" />
</ListItem>
</List>
</Page>
);
return {...anc_markup, ...markup};
}
}
class PESearchView extends SearchView {
constructor(props) {
super(props);
}
searchParams() {
let params = super.searchParams();
const checkboxCaseSensitive = f7.toggle.get('.toggle-case-sensitive');
const searchOptions = {
caseSensitive: checkboxCaseSensitive.checked,
};
return {...params, ...searchOptions};
}
onSearchbarShow(isshowed, bar) {
super.onSearchbarShow(isshowed, bar);
}
}
const Search = withTranslation()(props => {
const { t } = props;
const _t = t('View.Settings', {returnObjects: true});
const onSearchQuery = params => {
const api = Common.EditorApi.get();
if (params.find && params.find.length) {
if (!api.findText(params.find, params.forward, params.caseSensitive) ) {
f7.dialog.alert(null, _t.textNoTextFound);
}
}
};
const onReplaceQuery = params => {
const api = Common.EditorApi.get();
if (params.find && params.find.length) {
api.asc_replaceText(params.find, params.replace, false, params.caseSensitive);
}
}
const onReplaceAllQuery = params => {
const api = Common.EditorApi.get();
if (params.find && params.find.length) {
api.asc_replaceText(params.find, params.replace, true, params.caseSensitive);
}
}
return <PESearchView _t={_t} onSearchQuery={onSearchQuery} onReplaceQuery={onReplaceQuery} onReplaceAllQuery={onReplaceAllQuery} />
});
const SearchSettingsWithTranslation = withTranslation()(SearchSettings);
export {Search, SearchSettingsWithTranslation as SearchSettings}

View file

@ -67,7 +67,7 @@ class EditLinkController extends Component {
let mask = "ppaction://hlinksldjumpslide", let mask = "ppaction://hlinksldjumpslide",
indSlide = url.indexOf(mask); indSlide = url.indexOf(mask);
if (0 == indSlide) { if (0 == indSlide) {
slideNum = parseInt(url.substring(mask.length)); this.slideNum = parseInt(url.substring(mask.length));
if (slideNum < 0) this.slideNum = 0; if (slideNum < 0) this.slideNum = 0;
if (slideNum >= slidesCount) this.slideNum = slidesCount - 1; if (slideNum >= slidesCount) this.slideNum = slidesCount - 1;
} else this.slideNum = 0; } else this.slideNum = 0;
@ -121,7 +121,7 @@ class EditLinkController extends Component {
break; break;
case 1: case 1:
url = url + "showjump?jump=previousslide"; url = url + "showjump?jump=previousslide";
slidetip = _t.textPrevSlide; slidetip = _t.textPreviousSlide;
break; break;
case 2: case 2:
url = url + "showjump?jump=firstslide"; url = url + "showjump?jump=firstslide";
@ -137,12 +137,12 @@ class EditLinkController extends Component {
break; break;
} }
props.put_Value(url); props.put_Value(url);
props.put_ToolTip(!tip ? slidetip : tip); props.put_ToolTip(tip === '' ? slidetip : tip);
def_display = slidetip; def_display = slidetip;
} }
if (!linkInfo.displayDisabled) { if (!linkInfo.displayDisabled) {
props.put_Text(!display ? def_display : display); props.put_Text(display === '' ? def_display : display);
} else } else
props.put_Text(null); props.put_Text(null);

View file

@ -7,12 +7,19 @@ class PresentationSettingsController extends Component {
super(props); super(props);
this.initSlideSize = this.initSlideSize.bind(this); this.initSlideSize = this.initSlideSize.bind(this);
this.onSlideSize = this.onSlideSize.bind(this); this.onSlideSize = this.onSlideSize.bind(this);
this.initSlideSize();
} }
initSlideSize() { initSlideSize() {
if (!this.init) { if (!this.init) {
const api = Common.EditorApi.get(); const api = Common.EditorApi.get();
const slideSizes = [
[9144000, 6858000, Asc.c_oAscSlideSZType.SzScreen4x3],
[12192000, 6858000, Asc.c_oAscSlideSZType.SzCustom]
];
this.props.storePresentationSettings.changeSizeIndex(api.get_PresentationWidth(), api.get_PresentationHeight()); this.props.storePresentationSettings.changeSizeIndex(api.get_PresentationWidth(), api.get_PresentationHeight());
this.props.storePresentationSettings.initSlideSizes(slideSizes);
this.init = true; this.init = true;
} }
} }

View file

@ -1,12 +1,16 @@
@themeColor: #aa5252; @themeColor: #aa5252;
@import '../../../../../vendor/framework7-react/node_modules/framework7/less/mixins.less';
@import '../../../../common/mobile/resources/less/_mixins.less'; @import '../../../../common/mobile/resources/less/_mixins.less';
@import '../../../../common/mobile/resources/less/collaboration.less'; @import '../../../../common/mobile/resources/less/collaboration.less';
@import '../../../../common/mobile/resources/less/common.less'; @import '../../../../common/mobile/resources/less/common.less';
@import '../../../../common/mobile/resources/less/common-ios.less'; @import '../../../../common/mobile/resources/less/common-ios.less';
@import '../../../../common/mobile/resources/less/common-material.less'; @import '../../../../common/mobile/resources/less/common-material.less';
@import '../../../../common/mobile/resources/less/icons.less';
@import '../../../../common/mobile/resources/less/dataview.less'; @import '../../../../common/mobile/resources/less/dataview.less';
@import '../../../../common/mobile/resources/less/about.less'; @import '../../../../common/mobile/resources/less/about.less';
@import '../../../../common/mobile/resources/less/search.less';
@import './app-material.less'; @import './app-material.less';
@import './app-ios.less'; @import './app-ios.less';
@import './icons-ios.less'; @import './icons-ios.less';

View file

@ -4,7 +4,9 @@ import { Page, View, Navbar, NavLeft, NavRight, Link, Icon } from 'framework7-re
import EditOptions from '../view/edit/Edit'; import EditOptions from '../view/edit/Edit';
import AddOptions from '../view/add/Add'; import AddOptions from '../view/add/Add';
import Settings from '../view/settings/Settings'; import Settings from '../view/settings/Settings';
import CollaborationView from '../../../../common/mobile/lib/view/collaboration/Collaboration.jsx' import CollaborationView from '../../../../common/mobile/lib/view/collaboration/Collaboration.jsx';
import { Device } from '../../../../common/mobile/utils/device';
import { Search, SearchSettings } from '../controller/Search';
export default class MainPage extends Component { export default class MainPage extends Component {
constructor(props) { constructor(props) {
@ -58,12 +60,17 @@ export default class MainPage extends Component {
<NavRight> <NavRight>
<Link id='btn-edit' icon='icon-edit-settings' href={false} onClick={e => this.handleClickToOpenOptions('edit')}></Link> <Link id='btn-edit' icon='icon-edit-settings' href={false} onClick={e => this.handleClickToOpenOptions('edit')}></Link>
<Link id='btn-add' icon='icon-plus' href={false} onClick={e => this.handleClickToOpenOptions('add')}></Link> <Link id='btn-add' icon='icon-plus' href={false} onClick={e => this.handleClickToOpenOptions('add')}></Link>
{ Device.phone ? null : <Link icon='icon-search' searchbarEnable='.searchbar' href={false}></Link> }
<Link id='btn-coauth' href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link> <Link id='btn-coauth' href={false} icon='icon-collaboration' onClick={e => this.handleClickToOpenOptions('coauth')}></Link>
<Link id='btn-settings' icon='icon-settings' href={false} onClick={e => this.handleClickToOpenOptions('settings')}></Link> <Link id='btn-settings' icon='icon-settings' href={false} onClick={e => this.handleClickToOpenOptions('settings')}></Link>
</NavRight> </NavRight>
<Search useSuspense={false} />
</Navbar> </Navbar>
{/* Page content */} {/* Page content */}
<View id="editor_sdk" /> <View id="editor_sdk" />
<SearchSettings useSuspense={false} />
{ {
!this.state.editOptionsVisible ? null : !this.state.editOptionsVisible ? null :
<EditOptions onclosed={this.handleOptionsViewClosed.bind(this, 'edit')} /> <EditOptions onclosed={this.handleOptionsViewClosed.bind(this, 'edit')} />

View file

@ -1,4 +1,4 @@
import {makeObservable, action, observable} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storeAppOptions { export class storeAppOptions {
constructor() { constructor() {
@ -11,6 +11,7 @@ export class storeAppOptions {
isEdit = false; isEdit = false;
config = {}; config = {};
setConfigOptions (config) { setConfigOptions (config) {
this.config = config; this.config = config;
this.user = Common.Utils.fillUserInfo(config.user, config.lang, "Local.User"/*me.textAnonymous*/); this.user = Common.Utils.fillUserInfo(config.user, config.lang, "Local.User"/*me.textAnonymous*/);
@ -33,6 +34,7 @@ export class storeAppOptions {
this.canBack = this.canBackToFolder === true; this.canBack = this.canBackToFolder === true;
this.canPlugins = false; this.canPlugins = false;
} }
setPermissionOptions (document, licType, params, permissions) { setPermissionOptions (document, licType, params, permissions) {
this.review = (permissions.review === undefined) ? (permissions.edit !== false) : permissions.review; this.review = (permissions.review === undefined) ? (permissions.edit !== false) : permissions.review;
this.canAnalytics = params.asc_getIsAnalyticsEnable(); this.canAnalytics = params.asc_getIsAnalyticsEnable();

View file

@ -1,20 +1,30 @@
import {action, observable} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storeApplicationSettings { export class storeApplicationSettings {
constructor() {
makeObservable(this, {
unitMeasurement: observable,
isSpellChecking: observable,
macrosMode: observable,
changeUnitMeasurement: action,
changeSpellCheck: action,
changeMacrosSettings: action
});
}
@observable unitMeasurement = 1; unitMeasurement = 1;
@observable isSpellChecking = true; isSpellChecking = true;
@observable macrosMode = 0; macrosMode = 0;
@action changeUnitMeasurement(value) { changeUnitMeasurement(value) {
this.unitMeasurement = +value; this.unitMeasurement = +value;
} }
@action changeSpellCheck(value) { changeSpellCheck(value) {
this.isSpellChecking = value; this.isSpellChecking = value;
} }
@action changeMacrosSettings(value) { changeMacrosSettings(value) {
this.macrosMode = +value; this.macrosMode = +value;
} }
} }

View file

@ -1,20 +1,35 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeChartSettings { export class storeChartSettings {
constructor() {
makeObservable(this, {
chartStyles: observable,
fillColor: observable,
borderColor: observable,
clearChartStyles: action,
updateChartStyles: action,
styles: computed,
types: computed,
setFillColor: action,
getFillColor: action,
setBorderColor: action,
initBorderColor: action
});
}
// Style // Style
@observable chartStyles = null; chartStyles = null;
@action clearChartStyles () { clearChartStyles () {
this.chartStyles = null; this.chartStyles = null;
} }
@action updateChartStyles (styles) { updateChartStyles (styles) {
this.chartStyles = styles; this.chartStyles = styles;
} }
@computed get styles () { get styles () {
if (!this.chartStyles) return null; if (!this.chartStyles) return null;
const widthContainer = document.querySelector(".page-content").clientWidth; const widthContainer = document.querySelector(".page-content").clientWidth;
const columns = parseInt(widthContainer / 70); // magic const columns = parseInt(widthContainer / 70); // magic
@ -32,7 +47,7 @@ export class storeChartSettings {
return styles; return styles;
} }
@computed get types () { get types () {
const types = [ const types = [
{ type: Asc.c_oAscChartTypeSettings.barNormal, thumb: 'chart-03.png'}, { type: Asc.c_oAscChartTypeSettings.barNormal, thumb: 'chart-03.png'},
{ type: Asc.c_oAscChartTypeSettings.barStacked, thumb: 'chart-02.png'}, { type: Asc.c_oAscChartTypeSettings.barStacked, thumb: 'chart-02.png'},
@ -75,7 +90,7 @@ export class storeChartSettings {
// Fill Color // Fill Color
@observable fillColor = undefined; fillColor = undefined;
setFillColor (color) { setFillColor (color) {
this.fillColor = color; this.fillColor = color;
@ -104,7 +119,7 @@ export class storeChartSettings {
// Border size and border color // Border size and border color
@observable borderColor; borderColor;
setBorderColor (color) { setBorderColor (color) {
this.borderColor = color; this.borderColor = color;

View file

@ -1,13 +1,30 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeFocusObjects { export class storeFocusObjects {
@observable _focusObjects = []; constructor() {
makeObservable(this, {
_focusObjects: observable,
resetFocusObjects: action,
settings: computed,
slideObject: computed,
paragraphObject: computed,
paragraphLocked: computed,
shapeObject: computed,
imageObject: computed,
tableObject: computed,
isTableInStack: computed,
chartObject: computed,
linkObject: computed
});
}
@action resetFocusObjects(objects) { _focusObjects = [];
resetFocusObjects(objects) {
this._focusObjects = objects; this._focusObjects = objects;
} }
@computed get settings() { get settings() {
const _settings = []; const _settings = [];
let no_text = true; let no_text = true;
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
@ -53,7 +70,7 @@ export class storeFocusObjects {
return resultArr; return resultArr;
} }
@computed get slideObject() { get slideObject() {
const slides = []; const slides = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Slide) { if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Slide) {
@ -68,7 +85,7 @@ export class storeFocusObjects {
} }
} }
@computed get paragraphObject() { get paragraphObject() {
const paragraphs = []; const paragraphs = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) { if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Paragraph) {
@ -83,7 +100,7 @@ export class storeFocusObjects {
} }
} }
@computed get paragraphLocked() { get paragraphLocked() {
let _paragraphLocked = false; let _paragraphLocked = false;
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (Asc.c_oAscTypeSelectElement.Paragraph == object.get_ObjectType()) { if (Asc.c_oAscTypeSelectElement.Paragraph == object.get_ObjectType()) {
@ -93,7 +110,7 @@ export class storeFocusObjects {
return _paragraphLocked; return _paragraphLocked;
} }
@computed get shapeObject() { get shapeObject() {
const shapes = []; const shapes = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Shape) { if (object.get_ObjectType() === Asc.c_oAscTypeSelectElement.Shape) {
@ -108,7 +125,7 @@ export class storeFocusObjects {
} }
} }
@computed get imageObject() { get imageObject() {
const images = []; const images = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image && object.get_ObjectValue()) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Image && object.get_ObjectValue()) {
@ -123,7 +140,7 @@ export class storeFocusObjects {
} }
} }
@computed get tableObject() { get tableObject() {
const tables = []; const tables = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
@ -138,7 +155,7 @@ export class storeFocusObjects {
} }
} }
@computed get isTableInStack() { get isTableInStack() {
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Table) {
return true; return true;
@ -147,7 +164,7 @@ export class storeFocusObjects {
return false; return false;
} }
@computed get chartObject() { get chartObject() {
const charts = []; const charts = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
@ -164,7 +181,7 @@ export class storeFocusObjects {
} }
} }
@computed get linkObject() { get linkObject() {
const links = []; const links = [];
for (let object of this._focusObjects) { for (let object of this._focusObjects) {
if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) { if (object.get_ObjectType() == Asc.c_oAscTypeSelectElement.Hyperlink) {

View file

@ -1,8 +1,16 @@
import {action, observable, computed} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storeLinkSettings { export class storeLinkSettings {
@observable canAddLink; constructor() {
@action canAddHyperlink (value) { makeObservable(this, {
canAddLink: observable,
canAddHyperlink: action
});
}
canAddLink;
canAddHyperlink (value) {
this.canAddLink = value; this.canAddLink = value;
} }
} }

View file

@ -1,9 +1,16 @@
import {action, observable} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storePalette { export class storePalette {
@observable customColors = []; constructor() {
makeObservable(this, {
customColors: observable,
changeCustomColors: action
});
}
@action changeCustomColors (colors) { customColors = [];
changeCustomColors (colors) {
this.customColors = colors; this.customColors = colors;
} }
} }

View file

@ -1,10 +1,16 @@
import { action, observable } from "mobx"; import { action, observable, makeObservable } from "mobx";
export class storePresentationInfo { export class storePresentationInfo {
constructor() {
makeObservable(this, {
dataDoc: observable,
setDataDoc: action
});
}
@observable dataDoc; dataDoc;
@action setDataDoc(obj) { setDataDoc(obj) {
this.dataDoc = obj; this.dataDoc = obj;
} }
} }

View file

@ -1,15 +1,23 @@
import {action, observable} from 'mobx'; import {action, observable, makeObservable} from 'mobx';
export class storePresentationSettings { export class storePresentationSettings {
@observable slideSizes = [ constructor() {
[9144000, 6858000, Asc.c_oAscSlideSZType.SzScreen4x3], makeObservable(this, {
[12192000, 6858000, Asc.c_oAscSlideSZType.SzCustom] slideSizes: observable,
]; currentPageSize: observable,
slideSizeIndex: observable,
allSchemes: observable,
changeSizeIndex: action,
addSchemes: action,
initSlideSizes: action
})
}
@observable currentPageSize; slideSizes = [];
@observable slideSizeIndex; currentPageSize;
slideSizeIndex;
@action changeSizeIndex(width, height) { changeSizeIndex(width, height) {
this.currentPageSize = {width, height}; this.currentPageSize = {width, height};
let ratio = height / width; let ratio = height / width;
@ -20,11 +28,15 @@ export class storePresentationSettings {
}); });
} }
initSlideSizes(value) {
this.slideSizes = value;
}
// Color Schemes // Color Schemes
@observable allSchemes; allSchemes;
@action addSchemes(arr) { addSchemes(arr) {
this.allSchemes = arr; this.allSchemes = arr;
} }

View file

@ -1,6 +1,16 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeShapeSettings { export class storeShapeSettings {
constructor() {
makeObservable(this, {
fillColor: observable,
borderColorView: observable,
setFillColor: action,
getFillColor: action,
setBorderColor: action,
initBorderColorView: action
});
}
getStyleGroups () { getStyleGroups () {
const styles = [ const styles = [
@ -140,7 +150,7 @@ export class storeShapeSettings {
// Fill Color // Fill Color
@observable fillColor = undefined; fillColor = undefined;
setFillColor (color) { setFillColor (color) {
this.fillColor = color; this.fillColor = color;
@ -169,7 +179,7 @@ export class storeShapeSettings {
// Border size and color // Border size and color
@observable borderColorView; borderColorView;
setBorderColor (color) { setBorderColor (color) {
this.borderColorView = color; this.borderColorView = color;

View file

@ -1,17 +1,30 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeSlideSettings { export class storeSlideSettings {
constructor() {
makeObservable(this, {
arrayLayouts: observable,
slideLayoutIndex: observable,
fillColor: observable,
arrayThemes: observable,
slideThemeIndex: observable,
getFillColor: action,
changeFillColor: action,
addArrayLayouts: action,
slideLayouts: computed,
changeSlideLayoutIndex: action,
addArrayThemes: action,
changeSlideThemeIndex: action,
});
}
@observable arrayLayouts; arrayLayouts;
@observable slideLayoutIndex = -1; slideLayoutIndex = -1;
@observable fillColor = undefined; fillColor = undefined;
@observable arrayThemes; arrayThemes;
@observable slideThemeIndex; slideThemeIndex;
@observable effect;
@observable type;
@action getFillColor (slideObject) {
getFillColor (slideObject) {
let color = 'transparent'; let color = 'transparent';
let fill = slideObject.get_background(), let fill = slideObject.get_background(),
fillType = fill.get_type(); fillType = fill.get_type();
@ -34,14 +47,15 @@ export class storeSlideSettings {
return color; return color;
} }
@action changeFillColor (color) { changeFillColor (color) {
this.fillColor = color; this.fillColor = color;
} }
@action addArrayLayouts(array) { addArrayLayouts(array) {
this.arrayLayouts = array; this.arrayLayouts = array;
} }
@computed get slideLayouts () {
get slideLayouts () {
const layouts = []; const layouts = [];
const columns = 2; const columns = 2;
let row = -1; let row = -1;
@ -60,23 +74,15 @@ export class storeSlideSettings {
return layouts; return layouts;
} }
@action changeSlideLayoutIndex(index) { changeSlideLayoutIndex(index) {
this.slideLayoutIndex = index; this.slideLayoutIndex = index;
} }
@action addArrayThemes(array) { addArrayThemes(array) {
this.arrayThemes = array; this.arrayThemes = array;
} }
@action changeSlideThemeIndex(index) { changeSlideThemeIndex(index) {
this.slideThemeIndex = index; this.slideThemeIndex = index;
} }
@action changeEffect(value) {
this.effect = value;
}
@action changeType(value) {
this.type = value;
}
} }

View file

@ -1,15 +1,27 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
import {f7} from 'framework7-react'; import {f7} from 'framework7-react';
export class storeTableSettings { export class storeTableSettings {
constructor() {
makeObservable(this, {
_templates: observable,
cellBorders: observable,
cellBorderWidth: observable,
cellBorderColor: observable,
initTableTemplates: action,
styles: computed,
updateCellBorderWidth: action,
updateCellBorderColor: action,
});
}
@observable _templates = []; _templates = [];
@action initTableTemplates (templates) { initTableTemplates (templates) {
this._templates = templates; this._templates = templates;
} }
@computed get styles () { get styles () {
let styles = []; let styles = [];
for (let template of this._templates) { for (let template of this._templates) {
styles.push({ styles.push({
@ -52,9 +64,9 @@ export class storeTableSettings {
// Border style // Border style
@observable cellBorders; cellBorders;
@observable cellBorderWidth = 0.5; cellBorderWidth = 0.5;
@observable cellBorderColor = '000000'; cellBorderColor = '000000';
borderSizeTransform () { borderSizeTransform () {
const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6]; const _sizes = [0, 0.5, 1, 1.5, 2.25, 3, 4.5, 6];

View file

@ -1,27 +1,69 @@
import {action, observable, computed} from 'mobx'; import {action, observable, computed, makeObservable} from 'mobx';
export class storeTextSettings { export class storeTextSettings {
constructor() {
makeObservable(this, {
fontsArray: observable,
fontName: observable,
fontSize: observable,
isBold: observable,
isItalic: observable,
isUnderline: observable,
isStrikethrough: observable,
typeBaseline: observable,
listType: observable,
typeBullets: observable,
typeNumbers: observable,
paragraphAlign: observable,
paragraphValign: observable,
canIncreaseIndent: observable,
canDecreaseIndent: observable,
textColor: observable,
customTextColors: observable,
lineSpacing: observable,
initEditorFonts: action,
resetFontName: action,
resetFontSize: action,
resetIsBold: action,
resetIsItalic: action,
resetIsUnderline: action,
resetIsStrikeout: action,
resetIncreaseIndent: action,
resetDecreaseIndent: action,
resetTypeBaseline: action,
isSuperscript: computed,
isSubscript: computed,
resetListType: action,
resetBullets: action,
resetNumbers: action,
resetParagraphAlign: action,
resetParagraphValign: action,
resetTextColor: action,
changeCustomTextColors: action,
resetLineSpacing: action
});
}
@observable fontsArray = []; fontsArray = [];
@observable fontName = ''; fontName = '';
@observable fontSize = undefined; fontSize = undefined;
@observable isBold = false; isBold = false;
@observable isItalic = false; isItalic = false;
@observable isUnderline = false; isUnderline = false;
@observable isStrikethrough = false; isStrikethrough = false;
@observable typeBaseline = undefined; typeBaseline = undefined;
@observable listType = undefined; listType = undefined;
@observable typeBullets = undefined; typeBullets = undefined;
@observable typeNumbers = undefined; typeNumbers = undefined;
@observable paragraphAlign = undefined; paragraphAlign = undefined;
@observable paragraphValign = undefined; paragraphValign = undefined;
@observable canIncreaseIndent = undefined; canIncreaseIndent = undefined;
@observable canDecreaseIndent = undefined; canDecreaseIndent = undefined;
@observable textColor = undefined; textColor = undefined;
@observable customTextColors = []; customTextColors = [];
@observable lineSpacing = undefined; lineSpacing = undefined;
@action initEditorFonts (fonts, select) { initEditorFonts (fonts, select) {
let array = []; let array = [];
for (let font of fonts) { for (let font of fonts) {
let fontId = font.asc_getFontId(); let fontId = font.asc_getFontId();
@ -35,59 +77,71 @@ export class storeTextSettings {
} }
this.fontsArray = array; this.fontsArray = array;
} }
@action resetFontName (font) {
resetFontName (font) {
let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName(); let name = (typeof font.get_Name) === "function" ? font.get_Name() : font.asc_getName();
this.fontName = name; this.fontName = name;
} }
@action resetFontSize (size) {
resetFontSize (size) {
this.fontSize = size; this.fontSize = size;
} }
@action resetIsBold (isBold) {
resetIsBold (isBold) {
this.isBold = isBold; this.isBold = isBold;
} }
@action resetIsItalic (isItalic) {
resetIsItalic (isItalic) {
this.isItalic = isItalic; this.isItalic = isItalic;
} }
@action resetIsUnderline (isUnderline) {
resetIsUnderline (isUnderline) {
this.isUnderline = isUnderline; this.isUnderline = isUnderline;
} }
@action resetIsStrikeout (isStrikethrough) {
resetIsStrikeout (isStrikethrough) {
this.isStrikethrough = isStrikethrough; this.isStrikethrough = isStrikethrough;
} }
// Indent // Indent
@action resetIncreaseIndent(value) { resetIncreaseIndent(value) {
this.canIncreaseIndent = value; this.canIncreaseIndent = value;
} }
@action resetDecreaseIndent(value) { resetDecreaseIndent(value) {
this.canDecreaseIndent = value; this.canDecreaseIndent = value;
} }
// vertical align // vertical align
@action resetTypeBaseline (typeBaseline) {
resetTypeBaseline (typeBaseline) {
this.typeBaseline = typeBaseline; this.typeBaseline = typeBaseline;
} }
@computed get isSuperscript() {
get isSuperscript() {
return (this.typeBaseline === 1); return (this.typeBaseline === 1);
} }
@computed get isSubscript() {
get isSubscript() {
return (this.typeBaseline === 2); return (this.typeBaseline === 2);
} }
// bullets // bullets
@action resetListType (type) {
resetListType (type) {
this.listType = type; this.listType = type;
} }
@action resetBullets (type) {
resetBullets (type) {
this.typeBullets = type; this.typeBullets = type;
} }
@action resetNumbers (type) {
resetNumbers (type) {
this.typeNumbers = type; this.typeNumbers = type;
} }
@action resetParagraphAlign (align) { resetParagraphAlign (align) {
let value; let value;
switch (align) { switch (align) {
case 0: case 0:
@ -106,7 +160,7 @@ export class storeTextSettings {
this.paragraphAlign = value; this.paragraphAlign = value;
} }
@action resetParagraphValign (align) { resetParagraphValign (align) {
let value; let value;
switch (align) { switch (align) {
case 0: case 0:
@ -122,7 +176,7 @@ export class storeTextSettings {
this.paragraphValign = value; this.paragraphValign = value;
} }
@action resetTextColor (color) { resetTextColor (color) {
let value; let value;
if (color) { if (color) {
if (color.get_auto()) { if (color.get_auto()) {
@ -141,11 +195,11 @@ export class storeTextSettings {
this.textColor = value; this.textColor = value;
} }
@action changeCustomTextColors (colors) { changeCustomTextColors (colors) {
this.customTextColors = colors; this.customTextColors = colors;
} }
@action resetLineSpacing (vc) { resetLineSpacing (vc) {
let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line(); let line = (vc.get_Line() === null || vc.get_LineRule() === null || vc.get_LineRule() != 1) ? -1 : vc.get_Line();
this.lineSpacing = line; this.lineSpacing = line;
} }

View file

@ -13,8 +13,8 @@ const PageTypeLink = props => {
<Page> <Page>
<Navbar title={_t.textLinkType} backLink={_t.textBack}/> <Navbar title={_t.textLinkType} backLink={_t.textBack}/>
<List> <List>
<ListItem title={_t.textExternalLink} radio checked={typeLink === 1} onClick={() => {setTypeLink(1); props.changeType(1); props.initLink();}}></ListItem> <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); props.initLink();}}></ListItem> <ListItem title={_t.textSlideInThisPresentation} radio checked={typeLink === 0} onClick={() => {setTypeLink(0); props.changeType(0);}}></ListItem>
</List> </List>
</Page> </Page>
) )
@ -32,7 +32,7 @@ const PageLinkTo = props => {
props.changeTo(type); props.changeTo(type);
}; };
const [stateNumberTo, setNumberTo] = useState(0); const [stateNumberTo, setNumberTo] = useState(props.numberTo);
const changeNumber = (curNumber, isDecrement) => { const changeNumber = (curNumber, isDecrement) => {
setTypeTo(4); setTypeTo(4);
@ -139,6 +139,7 @@ const PageLink = props => {
<ListItem link={'/edit-link-to/'} title={_t.textLinkTo} after={displayTo} routeProps={{ <ListItem link={'/edit-link-to/'} title={_t.textLinkTo} after={displayTo} routeProps={{
changeTo: changeTo, changeTo: changeTo,
curTo: linkTo, curTo: linkTo,
numberTo: numberTo,
initLink: props.initLink, initLink: props.initLink,
slidesCount: props.slidesCount slidesCount: props.slidesCount
}}/> }}/>

View file

@ -212,19 +212,11 @@ const PageTransition = props => {
}; };
const storeFocusObjects = props.storeFocusObjects; const storeFocusObjects = props.storeFocusObjects;
const storeSlideSettings = props.storeSlideSettings;
const transitionObj = storeFocusObjects.slideObject.get_transition(); const transitionObj = storeFocusObjects.slideObject.get_transition();
if(!storeSlideSettings.effect) { const [_effect, setEffect] = useState(transitionObj.get_TransitionType());
storeSlideSettings.changeEffect(transitionObj.get_TransitionType());
}
const _effect = storeSlideSettings.effect;
const valueEffectTypes = fillEffectTypes(_effect); const valueEffectTypes = fillEffectTypes(_effect);
const [type, setType] = useState(valueEffectTypes);
if(!storeSlideSettings.type) {
storeSlideSettings.changeType(valueEffectTypes);
}
let _effectDelay = transitionObj.get_SlideAdvanceDuration(); let _effectDelay = transitionObj.get_SlideAdvanceDuration();
@ -248,13 +240,19 @@ const PageTransition = props => {
<ListItem link="/effect/" title={_t.textEffect} after={nameEffect} routeProps={{ <ListItem link="/effect/" title={_t.textEffect} after={nameEffect} routeProps={{
_arrEffect, _arrEffect,
onEffectClick: props.onEffectClick, onEffectClick: props.onEffectClick,
fillEffectTypes fillEffectTypes,
_effect,
setEffect,
setType
}}></ListItem> }}></ListItem>
<ListItem link="/type/" title={_t.textType} <ListItem link="/type/" title={_t.textType}
after={_effect != Asc.c_oAscSlideTransitionTypes.None ? nameEffectType : ''} after={_effect != Asc.c_oAscSlideTransitionTypes.None ? nameEffectType : ''}
disabled={_effect == Asc.c_oAscSlideTransitionTypes.None} routeProps={{ disabled={_effect == Asc.c_oAscSlideTransitionTypes.None} routeProps={{
_arrCurrentEffectTypes, _arrCurrentEffectTypes,
onEffectTypeClick: props.onEffectTypeClick onEffectTypeClick: props.onEffectTypeClick,
_effect,
type,
setType
}}> }}>
</ListItem> </ListItem>
<ListItem title={_t.textDuration} disabled={_effect == Asc.c_oAscSlideTransitionTypes.None}> <ListItem title={_t.textDuration} disabled={_effect == Asc.c_oAscSlideTransitionTypes.None}>
@ -285,11 +283,11 @@ const PageTransition = props => {
<List> <List>
<ListItem> <ListItem>
<span>{_t.textStartOnClick}</span> <span>{_t.textStartOnClick}</span>
<Toggle checked={isStartOnClick} onToggleChange={() => {props.onStartClick(!isStartOnClick)}} /> <Toggle checked={isStartOnClick} onChange={() => {props.onStartClick(!isStartOnClick)}} />
</ListItem> </ListItem>
<ListItem> <ListItem>
<span>{_t.textDelay}</span> <span>{_t.textDelay}</span>
<Toggle checked={isDelay} onToggleChange={() => {props.onDelayCheck(!isDelay, _effectDelay)}} /> <Toggle checked={isDelay} onChange={() => {props.onDelayCheck(!isDelay, _effectDelay)}} />
</ListItem> </ListItem>
<ListItem> <ListItem>
<div slot='inner' style={{width: '100%'}}> <div slot='inner' style={{width: '100%'}}>
@ -316,8 +314,8 @@ const PageTransition = props => {
const PageEffect = props => { const PageEffect = props => {
const { t } = useTranslation(); const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true }); const _t = t("View.Edit", { returnObjects: true });
const storeSlideSettings = props.storeSlideSettings; const _effect = props._effect;
const _effect = storeSlideSettings.effect; const [currentEffect, setEffect] = useState(_effect);
const _arrEffect = props._arrEffect; const _arrEffect = props._arrEffect;
return ( return (
@ -328,10 +326,11 @@ const PageEffect = props => {
{_arrEffect.map((elem, index) => { {_arrEffect.map((elem, index) => {
return ( return (
<ListItem key={index} radio name="editslide-effect" title={elem.displayValue} value={elem.value} <ListItem key={index} radio name="editslide-effect" title={elem.displayValue} value={elem.value}
checked={elem.value === _effect} onChange={() => { checked={elem.value === currentEffect} onChange={() => {
storeSlideSettings.changeEffect(elem.value); setEffect(elem.value);
props.setEffect(elem.value);
let valueEffectTypes = props.fillEffectTypes(elem.value); let valueEffectTypes = props.fillEffectTypes(elem.value);
storeSlideSettings.changeType(valueEffectTypes); props.setType(valueEffectTypes);
props.onEffectClick(elem.value, valueEffectTypes); props.onEffectClick(elem.value, valueEffectTypes);
}}></ListItem> }}></ListItem>
) )
@ -346,9 +345,9 @@ const PageType= props => {
const { t } = useTranslation(); const { t } = useTranslation();
const _t = t("View.Edit", { returnObjects: true }); const _t = t("View.Edit", { returnObjects: true });
const _arrCurrentEffectTypes = props._arrCurrentEffectTypes; const _arrCurrentEffectTypes = props._arrCurrentEffectTypes;
const storeSlideSettings = props.storeSlideSettings; const _effect = props._effect;
const _effect = storeSlideSettings.effect; const type = props.type;
const type = storeSlideSettings.type; const [currentType, setType] = useState(type);
return ( return (
<Page className="style-type"> <Page className="style-type">
@ -362,8 +361,9 @@ const PageType= props => {
{_arrCurrentEffectTypes.map((elem, index) => { {_arrCurrentEffectTypes.map((elem, index) => {
return ( return (
<ListItem key={index} radio name="editslide-effect-type" title={elem.displayValue} value={elem.value} <ListItem key={index} radio name="editslide-effect-type" title={elem.displayValue} value={elem.value}
checked={elem.value === type} onChange={() => { checked={elem.value === currentType} onChange={() => {
storeSlideSettings.changeType(elem.value); setType(elem.value);
props.setType(elem.value);
props.onEffectTypeClick(elem.value, _effect); props.onEffectTypeClick(elem.value, _effect);
}}> }}>
</ListItem> </ListItem>

View file

@ -17,9 +17,8 @@ const PagePresentationAbout = props => {
const infoCustomer = customer ? customer.info : null; const infoCustomer = customer ? customer.info : null;
const logoCustomer = customer ? customer.logo : null; const logoCustomer = customer ? customer.logo : null;
console.log(store); const publisherUrl = __PUBLISHER_URL__,
console.log(isCanBranding); publisherPrintUrl = publisherUrl.replace(/https?:\/{2}|\/$/,"");
return ( return (
<Page className="about"> <Page className="about">
<Navbar title={_t.textAbout} backLink={_t.textBack} /> <Navbar title={_t.textAbout} backLink={_t.textBack} />
@ -35,7 +34,25 @@ const PagePresentationAbout = props => {
</div> </div>
<div className="content-block"> <div className="content-block">
<h3>PRESENTATION EDITOR</h3> <h3>PRESENTATION EDITOR</h3>
<h3>{_t.textVersion} 6.1.1</h3> <h3>{_t.textVersion} {__PRODUCT_VERSION__}</h3>
</div>
<div className="content-block">
<p>
<label>{_t.textAddress}</label>
<a id="settings-about-address" className="external">{__PUBLISHER_ADDRESS__}</a>
</p>
<p>
<label>{_t.textEmail}</label>
<a id="settings-about-email" className="external" href={`mailto:${__SUPPORT_EMAIL__}`}>{__SUPPORT_EMAIL__}</a>
</p>
<p>
<label>{_t.textTel}</label>
<a id="settings-about-tel" className="external" href={`tel:${__PUBLISHER_PHONE__}`}>{__PUBLISHER_PHONE__}</a>
</p>
<p>
<a id="settings-about-url" className="external" target="_blank" href={publisherUrl}>{publisherPrintUrl}</a>
</p>
{/*<p><label id="settings-about-info" style="display: none;"></label></p>*/}
</div> </div>
<div className="content-block"> <div className="content-block">
{nameCustomer && nameCustomer.length ? ( {nameCustomer && nameCustomer.length ? (

View file

@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next";
const PagePresentationSettings = props => { const PagePresentationSettings = props => {
const { t } = useTranslation(); const { t } = useTranslation();
const _t = t("View.Settings", { returnObjects: true }); const _t = t("View.Settings", { returnObjects: true });
props.initSlideSize(); // props.initSlideSize();
const storePresentationSettings = props.storePresentationSettings; const storePresentationSettings = props.storePresentationSettings;
const slideSizeArr = storePresentationSettings.slideSizes; const slideSizeArr = storePresentationSettings.slideSizes;
const slideSizeIndex = storePresentationSettings.slideSizeIndex; const slideSizeIndex = storePresentationSettings.slideSizeIndex;

View file

@ -106,7 +106,7 @@ const SettingsList = withTranslation()(props => {
{navbar} {navbar}
<List> <List>
{!props.inPopover && {!props.inPopover &&
<ListItem title={_t.textFindAndReplace}> <ListItem title={_t.textFindAndReplace} link="#" searchbarEnable='.searchbar' onClick={closeModal}>
<Icon slot="media" icon="icon-search"></Icon> <Icon slot="media" icon="icon-search"></Icon>
</ListItem> </ListItem>
} }

View file

@ -15,7 +15,7 @@
&.icon-search { &.icon-search {
width: 22px; width: 22px;
height: 22px; height: 22px;
.encoded-svg-background('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M19.5,16.8L16,13.3c0.7-1.1,1.1-2.4,1.1-3.8C17,5.4,13.6,2,9.5,2S2,5.4,2,9.5S5.4,17,9.5,17c1.4,0,2.7-0.4,3.8-1.1l3.5,3.5c0.7,0.7,1.9,0.7,2.6,0C20.2,18.7,20.2,17.6,19.5,16.8z M9.5,15.3c-3.2,0-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8s5.8,2.6,5.8,5.8S12.7,15.3,9.5,15.3z"/></g></svg>'); .encoded-svg-background('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 22 22" fill="@{themeColor}"><g><path d="M19.5,16.8L16,13.3c0.7-1.1,1.1-2.4,1.1-3.8C17,5.4,13.6,2,9.5,2S2,5.4,2,9.5S5.4,17,9.5,17c1.4,0,2.7-0.4,3.8-1.1l3.5,3.5c0.7,0.7,1.9,0.7,2.6,0C20.2,18.7,20.2,17.6,19.5,16.8z M9.5,15.3c-3.2,0-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8s5.8,2.6,5.8,5.8S12.7,15.3,9.5,15.3z"/></g></svg>');
} }
&.icon-edit { &.icon-edit {
width: 22px; width: 22px;

View file

@ -2,8 +2,7 @@ const webpack = require('webpack');
const ora = require('ora'); const ora = require('ora');
const rm = require('rimraf'); const rm = require('rimraf');
const chalk = require('chalk'); const chalk = require('chalk');
const editor = process.env.TARGET_EDITOR; const config = require('./webpack.config.js');
const config = !process.env.TARGET_EDITOR ? require('./webpack.config.js') : require('./webpack.config.pe.js');
const env = process.env.NODE_ENV || 'development'; const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web'; const target = process.env.TARGET || 'web';

View file

@ -16,14 +16,16 @@ function resolvePath(dir) {
const env = process.env.NODE_ENV || 'development'; const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web'; const target = process.env.TARGET || 'web';
const editor = process.env.TARGET_EDITOR == 'cell' ? 'spreadsheeteditor' :
process.env.TARGET_EDITOR == 'slide' ? 'presentationeditor' : 'documenteditor';
module.exports = { module.exports = {
mode: env, mode: env,
entry: { entry: {
app: '../../apps/documenteditor/mobile/src/app.js', app: `../../apps/${editor}/mobile/src/app.js`,
}, },
output: { output: {
path: resolvePath('../../apps/documenteditor/mobile'), // path above depends on it path: resolvePath(`../../apps/${editor}/mobile`), // path above depends on it
filename: 'dist/js/[name].js', // in such form will be injected in index.html filename: 'dist/js/[name].js', // in such form will be injected in index.html
chunkFilename: 'dist/js/[name].js', chunkFilename: 'dist/js/[name].js',
publicPath: '', publicPath: '',
@ -33,7 +35,7 @@ module.exports = {
resolve: { resolve: {
extensions: ['.js', '.jsx', '.json'], extensions: ['.js', '.jsx', '.json'],
alias: { alias: {
'@': resolvePath('../../apps/documenteditor/mobile/src'), '@': resolvePath(`../../apps/${editor}/mobile/src`),
}, },
modules: [path.resolve(__dirname, '..', 'node_modules'), 'node_modules'], modules: [path.resolve(__dirname, '..', 'node_modules'), 'node_modules'],
}, },
@ -63,7 +65,7 @@ module.exports = {
} }
}, },
include: [ include: [
resolvePath('../../apps/documenteditor/mobile/src'), resolvePath(`../../apps/${editor}/mobile/src`),
resolvePath('../../apps/common/mobile/lib'), resolvePath('../../apps/common/mobile/lib'),
resolvePath('node_modules/framework7'), resolvePath('node_modules/framework7'),
@ -107,14 +109,6 @@ module.exports = {
} }
}), }),
'css-loader', 'css-loader',
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true
}
}
},
{ {
loader: 'postcss-loader', loader: 'postcss-loader',
options: { options: {
@ -123,6 +117,14 @@ module.exports = {
} }
}, },
}, },
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true
}
}
},
], ],
}, },
{ {
@ -131,7 +133,7 @@ module.exports = {
options: { options: {
limit: 10000, limit: 10000,
name: 'images/[name].[ext]', name: 'images/[name].[ext]',
outputPath: '../../../apps/documenteditor/mobile/dist', outputPath: `../../../apps/${editor}/mobile/dist`,
}, },
}, },
@ -141,7 +143,7 @@ module.exports = {
options: { options: {
limit: 10000, limit: 10000,
name: 'fonts/[name].[ext]', name: 'fonts/[name].[ext]',
outputPath: '../../../apps/documenteditor/mobile/dist/assets', outputPath: `../../../apps/${editor}/mobile/dist/assets`,
}, },
}, },
@ -151,6 +153,12 @@ module.exports = {
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env), 'process.env.NODE_ENV': JSON.stringify(env),
'process.env.TARGET': JSON.stringify(target), 'process.env.TARGET': JSON.stringify(target),
__PRODUCT_VERSION__: JSON.stringify(process.env.PRODUCT_VERSION ? process.env.PRODUCT_VERSION : '0.0.1'),
__PUBLISHER_ADDRESS__: JSON.stringify('20A-12 Ernesta Birznieka-Upisha street, Riga, Latvia, EU, LV-1050'),
__SUPPORT_EMAIL__: JSON.stringify('support@onlyoffice.com'),
__PUBLISHER_PHONE__: JSON.stringify('+371 633-99867'),
__PUBLISHER_URL__: JSON.stringify('https://www.onlyoffice.com'),
__PUBLISHER_NAME__: JSON.stringify('Ascensio System SIA'),
}), }),
...(env === 'production' ? [ ...(env === 'production' ? [
@ -168,8 +176,8 @@ module.exports = {
]), ]),
// new CleanWebpackPlugin(), // new CleanWebpackPlugin(),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
filename: '../../../apps/documenteditor/mobile/index.html', filename: `../../../apps/${editor}/mobile/index.html`,
template: '../../apps/documenteditor/mobile/src/index_dev.html', template: `../../apps/${editor}/mobile/src/index_dev.html`,
inject: true, inject: true,
minify: env === 'production' ? { minify: env === 'production' ? {
collapseWhitespace: true, collapseWhitespace: true,

View file

@ -1,203 +0,0 @@
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const WorkboxPlugin = require('workbox-webpack-plugin');
const path = require('path');
function resolvePath(dir) {
return path.join(__dirname, '..', dir);
}
const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web';
const editor = process.env.TARGET_EDITOR == 'cell' ? 'spreadsheeteditor' :
process.env.TARGET_EDITOR == 'slide' ? 'presentationeditor' : 'documenteditor';
module.exports = {
mode: env,
entry: {
app: `../../apps/${editor}/mobile/src/app.js`,
},
output: {
path: resolvePath(`../../apps/${editor}/mobile`), // path above depends on it
filename: 'dist/js/[name].js', // in such form will be injected in index.html
chunkFilename: 'dist/js/[name].js',
publicPath: '',
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json',
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': resolvePath(`../../apps/${editor}/mobile/src`),
},
modules: [path.resolve(__dirname, '..', 'node_modules'), 'node_modules'],
},
watch: true,
watchOptions: {
aggregateTimeout: 600,
poll: 1000,
},
externals: {
jquery: 'jQuery'
},
devtool: env === 'production' ? 'source-map' : 'source-map',
optimization: {
minimizer: [new TerserPlugin({
sourceMap: true,
})],
},
module: {
rules: [
{
test: /\.(mjs|js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
}
},
include: [
resolvePath(`../../apps/${editor}/mobile/src`),
resolvePath('../../apps/common/mobile/lib'),
resolvePath('node_modules/framework7'),
resolvePath('node_modules/framework7-react'),
resolvePath('node_modules/template7'),
resolvePath('node_modules/dom7'),
resolvePath('node_modules/ssr-window'),
],
},
{
test: /\.css$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
{
loader: 'postcss-loader',
options: {
config: {
path: path.resolve(__dirname, '..'),
}
},
},
],
},
{
test: /\.less$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
{
loader: 'postcss-loader',
options: {
config: {
path: path.resolve(__dirname, '..'),
}
},
},
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true
}
}
},
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'images/[name].[ext]',
outputPath: `../../../apps/${editor}/mobile/dist`,
},
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name].[ext]',
outputPath: `../../../apps/${editor}/mobile/dist/assets`,
},
},
],
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env),
'process.env.TARGET': JSON.stringify(target),
}),
...(env === 'production' ? [
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
map: { inline: false },
},
}),
new webpack.optimize.ModuleConcatenationPlugin(),
] : [
// Development only plugins
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
]),
// new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: `../../../apps/${editor}/mobile/index.html`,
template: `../../apps/${editor}/mobile/src/index_dev.html`,
inject: true,
minify: env === 'production' ? {
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
useShortDoctype: true
} : false,
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
new CopyWebpackPlugin({
patterns: [
{
noErrorOnMissing: true,
from: resolvePath('src/static'),
to: resolvePath('www/static'),
},
{
noErrorOnMissing: true,
from: resolvePath('src/manifest.json'),
to: resolvePath('www/manifest.json'),
},
],
}),
],
};