[DE mobile] context menu moved to common
This commit is contained in:
parent
1c3e77c22b
commit
89d297ea9c
157
apps/common/mobile/lib/controller/ContextMenu.jsx
Normal file
157
apps/common/mobile/lib/controller/ContextMenu.jsx
Normal file
|
@ -0,0 +1,157 @@
|
|||
import React, { Component } from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import { Device } from '../../../../common/mobile/utils/device'
|
||||
|
||||
import ContextMenuView from '../view/ContextMenu';
|
||||
|
||||
class ContextMenuController extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
opened: false
|
||||
};
|
||||
|
||||
this.onMenuClosed = this.onMenuClosed.bind(this);
|
||||
this.onDocumentReady = this.onDocumentReady.bind(this);
|
||||
this.onApiOpenContextMenu = this.onApiOpenContextMenu.bind(this);
|
||||
this.onApiHideContextMenu = this.onApiHideContextMenu.bind(this);
|
||||
}
|
||||
|
||||
onDocumentReady() {
|
||||
this.$targetEl = $$('#idx-context-menu-target');
|
||||
if ( !this.$targetEl.length ) {
|
||||
// this.$targetEl = $$('<div id="idx-context-menu-target" style="position:absolute;width:15px;height:15px;background-color:green;z-index:1;"></div>');
|
||||
this.$targetEl = $$('<div id="idx-context-menu-target" style="position:absolute;"></div>');
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
|
||||
$$('#editor_sdk').append(this.$targetEl);
|
||||
}
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_registerCallback('asc_onShowPopMenu', this.onApiOpenContextMenu);
|
||||
api.asc_registerCallback('asc_onHidePopMenu', this.onApiHideContextMenu);
|
||||
}
|
||||
|
||||
offsetPopoverTop(popover) {
|
||||
var app = popover.app,
|
||||
$el = popover.$el,
|
||||
$targetEl = popover.$targetEl;
|
||||
|
||||
const width = $el.width(),
|
||||
height = $el.height();
|
||||
|
||||
$el.removeClass('popover-on-left popover-on-right popover-on-top popover-on-bottom popover-on-middle').css({
|
||||
left: '',
|
||||
top: ''
|
||||
});
|
||||
|
||||
let targetOffsetLeft, targetOffsetTop;
|
||||
// var safeAreaTop = parseInt($('html').css('--f7-safe-area-top'), 10);
|
||||
let safeAreaLeft = parseInt($('html').css('--f7-safe-area-left'), 10),
|
||||
safeAreaRight = parseInt($('html').css('--f7-safe-area-right'), 10);
|
||||
// if (Number.isNaN(safeAreaTop)) safeAreaTop = 0;
|
||||
if (Number.isNaN(safeAreaLeft)) safeAreaLeft = 0;
|
||||
if (Number.isNaN(safeAreaRight)) safeAreaRight = 0;
|
||||
|
||||
if ($targetEl && $targetEl.length > 0) {
|
||||
let targetOffset = $targetEl.offset();
|
||||
targetOffsetLeft = targetOffset.left - app.left;
|
||||
targetOffsetTop = targetOffset.top - app.top;
|
||||
let targetParentPage = $targetEl.parents('.page');
|
||||
|
||||
if (targetParentPage.length > 0) {
|
||||
targetOffsetTop -= targetParentPage[0].scrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
let position = 'top';
|
||||
|
||||
let top = targetOffsetTop - height - 10;
|
||||
top = Math.max(8, Math.min(top, app.height - height - 8)); // Horizontal Position
|
||||
|
||||
let hPosition;
|
||||
|
||||
// if (targetOffsetLeft < app.width / 2) {
|
||||
// hPosition = 'right';
|
||||
// left = position === 'middle' ? targetOffsetLeft + targetWidth : targetOffsetLeft;
|
||||
// } else {
|
||||
// hPosition = 'left';
|
||||
// left = position === 'middle' ? targetOffsetLeft - width : targetOffsetLeft + targetWidth - width;
|
||||
// }
|
||||
|
||||
hPosition = 'middle';
|
||||
let left = targetOffsetLeft - width / 2;
|
||||
|
||||
left = Math.max(8, Math.min(left, app.width - width - 8 - safeAreaRight), safeAreaLeft);
|
||||
$el.addClass(`popover-on-${position} popover-on-${hPosition}`);
|
||||
|
||||
$el.css({top: `${top}px`,
|
||||
left: `${left}px`});
|
||||
}
|
||||
|
||||
onApiOpenContextMenu(x, y) {
|
||||
if ( !this.state.opened ) {
|
||||
this.$targetEl.css({left: `${x}px`, top: `${y}px`});
|
||||
const popover = f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
|
||||
|
||||
if ( Device.android )
|
||||
this.offsetPopoverTop(popover);
|
||||
|
||||
this.setState(state => {
|
||||
return {opened: true}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onApiHideContextMenu() {
|
||||
if ( this.state.opened ) {
|
||||
f7.popover.close('#idx-context-menu-popover');
|
||||
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
this.setState({opened: false});
|
||||
}
|
||||
}
|
||||
|
||||
onMenuClosed() {
|
||||
// (async () => {
|
||||
// await 1 && this.setState(state => {
|
||||
// this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
// return ({opened: false});
|
||||
// });
|
||||
// })();
|
||||
}
|
||||
|
||||
onMenuItemClick(action) {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Common.Notifications.off('document:ready', this.onDocumentReady);
|
||||
|
||||
const api = Common.EditorApi.get();
|
||||
api.asc_unregisterCallback('asc_onShowPopMenu', this.onApiOpenContextMenu);
|
||||
api.asc_unregisterCallback('asc_onHidePopMenu', this.onApiHideContextMenu);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if ( !Common.EditorApi ) {
|
||||
Common.Notifications.on({
|
||||
'document:ready': this.onDocumentReady
|
||||
});
|
||||
} else {
|
||||
this.onDocumentReady();
|
||||
}
|
||||
}
|
||||
|
||||
initMenuItems() {
|
||||
return [];
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ContextMenuView items={this.initMenuItems()} onMenuClosed={this.onMenuClosed} onMenuItemClick={this.onMenuItemClick} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ContextMenuController;
|
39
apps/common/mobile/lib/view/ContextMenu.jsx
Normal file
39
apps/common/mobile/lib/view/ContextMenu.jsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Popover, List, ListItem, ListButton, Link, Icon } from 'framework7-react';
|
||||
import { f7 } from 'framework7-react';
|
||||
|
||||
class ContextMenuView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
|
||||
}
|
||||
|
||||
render() {
|
||||
const buttons = this.props.items || {};
|
||||
|
||||
return (
|
||||
<Popover id="idx-context-menu-popover"
|
||||
className="document-menu"
|
||||
backdrop={false}
|
||||
closeByBackdropClick={false}
|
||||
closeByOutsideClick={false}
|
||||
onPopoverClosed={e => this.props.onMenuClosed()}
|
||||
>
|
||||
<List className="list-block">
|
||||
{buttons.map((b, index) =>
|
||||
!!b.text ?
|
||||
<ListButton className="asd" title={b.text} key={index} onClick={e => this.props.onMenuItemClick(b.action)} /> :
|
||||
<ListButton className="asd" title={b.text} key={index}>
|
||||
<Icon slot="media" icon={`icon_mask ${b.icon}`} />
|
||||
</ListButton>
|
||||
)}
|
||||
</List>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ContextMenuView;
|
7
apps/common/mobile/resources/less/contextmenu.less
Normal file
7
apps/common/mobile/resources/less/contextmenu.less
Normal file
|
@ -0,0 +1,7 @@
|
|||
@import './ios/contextmenu';
|
||||
@import './material/contextmenu';
|
||||
|
||||
|
||||
.document-menu {
|
||||
width: auto;
|
||||
}
|
102
apps/common/mobile/resources/less/ios/contextmenu.less
Normal file
102
apps/common/mobile/resources/less/ios/contextmenu.less
Normal file
|
@ -0,0 +1,102 @@
|
|||
|
||||
.device-ios {
|
||||
.document-menu {
|
||||
@contextMenuBg: rgba(0, 0, 0, 0.9);
|
||||
@modalHairlineColor: rgba(230, 230, 230, 0.9);
|
||||
@modalButtonColor: rgba(200, 200, 200, 0.9);
|
||||
|
||||
background-color: @contextMenuBg;
|
||||
border-radius: 8px;
|
||||
|
||||
.popover-angle {
|
||||
&:after {
|
||||
background: @contextMenuBg;
|
||||
}
|
||||
}
|
||||
|
||||
.list-block {
|
||||
font-size: 14px;
|
||||
white-space: pre;
|
||||
|
||||
&:first-child {
|
||||
ul {
|
||||
.hairline-remove(left);
|
||||
//border-radius: 7px 0 0 7px;
|
||||
}
|
||||
|
||||
li:first-child a {
|
||||
//border-radius: 7px 0 0 7px;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
//&:last-child {
|
||||
// ul {
|
||||
// .hairline-remove(right);
|
||||
// border-radius: 0 7px 7px 0;
|
||||
// }
|
||||
// li:last-child a{
|
||||
// border-radius: 0 7px 7px 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
//&:first-child:last-child {
|
||||
// li:first-child:last-child a, ul:first-child:last-child {
|
||||
// border-radius: 7px;
|
||||
// }
|
||||
//}
|
||||
|
||||
.item-link {
|
||||
display: inline-block;
|
||||
|
||||
html:not(.watch-active-state) &:active, &.active-state {
|
||||
//.transition(0ms);
|
||||
background-color: #d9d9d9;
|
||||
.item-inner {
|
||||
.hairline-color(right, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
html.phone & {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-button {
|
||||
color: @white;
|
||||
line-height: 36px;
|
||||
|
||||
.hairline(right, @modalHairlineColor);
|
||||
}
|
||||
|
||||
// List items
|
||||
li {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
// Last-childs
|
||||
li {
|
||||
&:last-child {
|
||||
.list-button {
|
||||
.hairline-remove(right);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child, &:last-child li:last-child {
|
||||
.item-inner {
|
||||
.hairline-remove(right);
|
||||
}
|
||||
}
|
||||
|
||||
li:last-child, &:last-child li {
|
||||
.item-inner {
|
||||
.hairline(right, @modalHairlineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.no-hairlines();
|
||||
//.no-hairlines-between()
|
||||
}
|
||||
}
|
||||
}
|
32
apps/common/mobile/resources/less/material/contextmenu.less
Normal file
32
apps/common/mobile/resources/less/material/contextmenu.less
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
.md {
|
||||
.document-menu {
|
||||
//line-height: 1 !important;
|
||||
|
||||
.popover-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.list-block {
|
||||
white-space: pre;
|
||||
|
||||
ul {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.list-button {
|
||||
color: #212121;
|
||||
}
|
||||
|
||||
//.item-link {
|
||||
// html.phone & {
|
||||
//padding: 0 10px;
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +1,38 @@
|
|||
import React, { Component } from 'react';
|
||||
import React from 'react';
|
||||
import { f7 } from 'framework7-react';
|
||||
import ContextMenuController from '../../../../common/mobile/lib/controller/ContextMenu';
|
||||
|
||||
import ContextMenuView from '../view/ContextMenu';
|
||||
|
||||
class ContextMenuController extends Component {
|
||||
class ContextMenu extends ContextMenuController {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
pos: [-10000,-10000],
|
||||
show: false
|
||||
};
|
||||
// console.log('context menu controller created');
|
||||
}
|
||||
|
||||
this.onMenuClosed = this.onMenuClosed.bind(this);
|
||||
// onMenuClosed() {
|
||||
// super.onMenuClosed();
|
||||
// }
|
||||
|
||||
Common.Notifications.on({
|
||||
'engineCreated': api => {
|
||||
api.asc_registerCallback('asc_onShowPopMenu', this.onApiShowPopMenu.bind(this));
|
||||
api.asc_registerCallback('asc_onHidePopMenu', this.onApiHidePopMenu.bind(this));
|
||||
},
|
||||
'document:ready': () => {
|
||||
this.$targetEl = $$('<div id="idx-context-menu-target" style="position:absolute;width:15px;height:15px;background-color:green;z-index:1;"></div>');
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
onMenuItemClick(action) {
|
||||
super.onMenuItemClick(action);
|
||||
|
||||
$$('#editor_sdk').append(this.$targetEl);
|
||||
console.log("on click item");
|
||||
}
|
||||
|
||||
initMenuItems() {
|
||||
return [
|
||||
{
|
||||
text: 'Edit',
|
||||
action: 'edit'
|
||||
}, {
|
||||
text: 'View',
|
||||
action: 'view'
|
||||
}, {
|
||||
icon: 'icon-paste',
|
||||
action: 'review'
|
||||
}
|
||||
});
|
||||
|
||||
console.log('context menu controller created');
|
||||
}
|
||||
|
||||
onApiShowPopMenu(x, y) {
|
||||
console.log('show context menu ' + [x,y]);
|
||||
|
||||
this.$targetEl.css({left: `${x}px`, top: `${y}px`});
|
||||
this.setState({
|
||||
pos: [x,y],
|
||||
show: true });
|
||||
}
|
||||
|
||||
onApiHidePopMenu() {
|
||||
// console.log('hide context menu');
|
||||
|
||||
if ( this.state.show ) {
|
||||
f7.popover.close('#idx-context-menu-popover');
|
||||
}
|
||||
}
|
||||
|
||||
onMenuClosed() {
|
||||
(async () => {
|
||||
await 1 && this.setState(state => {
|
||||
this.$targetEl.css({left: '-10000px', top: '-10000px'});
|
||||
return ({pos: [-10000, -10000], show: false});
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log('context menu controller will be unmounted');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log('context menu controller did mount');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
!this.state.show ? null :
|
||||
<ContextMenuView onMenuClosed={this.onMenuClosed} />)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export { ContextMenuController as ContextMenu };
|
||||
export { ContextMenu };
|
|
@ -7,8 +7,10 @@
|
|||
@import '../../../../common/mobile/resources/less/common.less';
|
||||
@import '../../../../common/mobile/resources/less/common-ios.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/search.less';
|
||||
@import '../../../../common/mobile/resources/less/contextmenu.less';
|
||||
@import './app-material.less';
|
||||
@import './app-ios.less';
|
||||
@import './icons-ios.less';
|
||||
|
|
|
@ -90,7 +90,7 @@ export default class MainPage extends Component {
|
|||
!this.state.collaborationVisible ? null :
|
||||
<Collaboration onclosed={this.handleOptionsViewClosed.bind(this, 'coauth')} />
|
||||
}
|
||||
{/*<ContextMenu />*/}
|
||||
<ContextMenu />
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,29 +2,18 @@ import React, { Component } from 'react';
|
|||
import { Popover, List, ListItem, ListButton, Link, Icon } from 'framework7-react';
|
||||
import { f7 } from 'framework7-react';
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
text: 'Edit',
|
||||
action: 'edit'
|
||||
}, {
|
||||
text: 'View',
|
||||
action: 'view'
|
||||
}, {
|
||||
icon: 'icon-paste',
|
||||
action: 'review'
|
||||
}
|
||||
];
|
||||
|
||||
class ContextMenuView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
|
||||
// f7.popover.open('#idx-context-menu-popover', '#idx-context-menu-target');
|
||||
}
|
||||
|
||||
render() {
|
||||
const buttons = this.props.items || {};
|
||||
|
||||
return (
|
||||
<Popover id="idx-context-menu-popover"
|
||||
className="document-menu"
|
||||
|
@ -36,9 +25,9 @@ class ContextMenuView extends Component {
|
|||
<List className="list-block">
|
||||
{buttons.map((b, index) =>
|
||||
!!b.text ?
|
||||
<ListButton className="asd" title={b.text} key={index} /> :
|
||||
<ListButton className="asd" title={b.text} key={index} onClick={e => this.props.onMenuItemClick(b.action)} /> :
|
||||
<ListButton className="asd" title={b.text} key={index}>
|
||||
<Icon slot="media" icon={b.icon} />
|
||||
<Icon slot="media" icon={`icon_mask ${b.icon}`} />
|
||||
</ListButton>
|
||||
)}
|
||||
</List>
|
||||
|
|
Loading…
Reference in a new issue