Skip to content

Commit

Permalink
Add Select Menu when click a tag about _target in webview
Browse files Browse the repository at this point in the history
  • Loading branch information
HyunmoAhn committed Aug 4, 2018
1 parent 936441b commit b951b4c
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 19 deletions.
8 changes: 8 additions & 0 deletions app/constants/i18n/contextMenu.js
Expand Up @@ -9,6 +9,10 @@ export default {
selectAll: 'Select All',
copyUrl: 'Copy Current URL',
openBrowser: 'Open Browser',
openWidget: 'Open Widget',
moveBrowser: 'Move',
openNewBrowser: 'Open with a new browser',
openNewWidget: 'Open with a new widget',
},
ko: {
back: '뒤로',
Expand All @@ -20,5 +24,9 @@ export default {
selectAll: '모두선택',
copyUrl: '현재 주소 복사',
openBrowser: '현재 주소로 브라우저 열기',
openWidget: '현재 주소로 위젯 만들기',
moveBrowser: '이동',
openNewBrowser: '새 브라우저로 열기',
openNewWidget: '새 위젯으로 열기',
},
};
26 changes: 23 additions & 3 deletions app/page/Components/Modal/index.jsx
@@ -1,6 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import ReactModal from 'react-modal';
import OutsideClickHandler from 'page/Components/OutsideClickHandler';
import './Modal.scss';

const propTypes = {
Expand All @@ -23,20 +25,38 @@ class Modal extends React.Component {
onModalClose,
} = this.props;
const isOpen = !!Component;
const {
modalClass,
overlayClass,
activeOutsideClose,
} = modalProps;

const modalClassName = cx(modalClass, {
Modal__container: !modalClass,
});
const overlayClassName = cx(overlayClass, {
Modal__overlay: !overlayClass,
});

if (!isOpen) {
return null;
}

return (
<ReactModal
className="Modal__container"
overlayClassName="Modal__overlay"
className={modalClassName}
overlayClassName={overlayClassName}
contentLabel="Modal"
isOpen={isOpen}
ariaHideApp={false}
>
<Component {...modalProps} onModalClose={onModalClose} />
{activeOutsideClose ? (
<OutsideClickHandler onOutSideClick={onModalClose}>
<Component {...modalProps} onModalClose={onModalClose} />
</OutsideClickHandler>
) :
<Component {...modalProps} onModalClose={onModalClose} />
}
</ReactModal>
);
}
Expand Down
53 changes: 53 additions & 0 deletions app/page/Components/OutsideClickHandler/index.jsx
@@ -0,0 +1,53 @@
import React from 'react';
import PropTypes from 'prop-types';
import './OutsideClickHandler.scss';

const propTypes = {
children: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element),
]).isRequired,
onOutSideClick: PropTypes.func,
};
const defaultProps = {
onOutSideClick() {},
};

class OutsideClickHandler extends React.Component {
constructor(props) {
super(props);
this.handleOutSideClick = this.handleOutSideClick.bind(this);
}

componentDidMount() {
document.addEventListener('click', this.handleOutSideClick);
}

componentWillUnmount() {
document.removeEventListener('click', this.handleOutSideClick);
}

handleOutSideClick(e) {
const { onOutSideClick } = this.props;
if (!this.outsideRef.contains(e.target)) {
onOutSideClick();
}
}

render() {
const { children } = this.props;
return (
<div
className="OutsideClickHandler"
ref={(ref) => { this.outsideRef = ref; }}
>
{children}
</div>
);
}
}

OutsideClickHandler.propTypes = propTypes;
OutsideClickHandler.defaultProps = defaultProps;

export default OutsideClickHandler;
17 changes: 17 additions & 0 deletions app/page/webview/components/MenuNewWindow/MenuNewWindow.scss
@@ -0,0 +1,17 @@
.MenuNewWindow {
background-color: gainsboro;
position: absolute;
}

.MenuNewWindow__btn {
width: 100%;
height: 100%;
}

.MenuNewWindow__list {
width: 100px;
height: 30px;
background-color: antiquewhite;
border: 1px solid black;
margin-bottom: -1px;
}
107 changes: 107 additions & 0 deletions app/page/webview/components/MenuNewWindow/index.jsx
@@ -0,0 +1,107 @@
import React from 'react';
import PropTypes from 'prop-types';
import { shell } from 'electron';
import i18n from 'constants/i18n';
import './MenuNewWindow.scss';

const propTypes = {
url: PropTypes.string,
webview: PropTypes.object, // eslint-disable-line react/forbid-prop-types
x: PropTypes.number,
y: PropTypes.number,
onClose: PropTypes.func,
};

const defaultProps = {
url: '',
webview: null,
x: 0,
y: 0,
onClose() {},
};

class MenuNewWindow extends React.Component {
constructor(props) {
super(props);
this.handleClose = this.handleClose.bind(this);
this.handleOpenBrowser = this.handleOpenBrowser.bind(this);
this.handleOpenWidget = this.handleOpenWidget.bind(this);
this.handleMovementPage = this.handleMovementPage.bind(this);
}

componentDidMount() {
window.addEventListener('mouseup', this.handleClose);
}

componentWillUnmount() {
window.removeEventListener('mouseup', this.handleClose);
}

handleClose() {
const { onClose } = this.props;
onClose();
}

handleOpenBrowser() {
const { url } = this.props;
shell.openExternal(url);
}

handleMovementPage() {
const { webview, url } = this.props;
webview.loadURL(url);
}

handleOpenWidget() {
const { url } = this.props;
console.log('url: ', url);
}

render() {
const {
x,
y,
} = this.props;
const text = i18n().contextMenu;

return (
<ul
className="MenuNewWindow"
style={{ left: x, top: y }}
>
<li className="MenuNewWindow__list">
<button
className="MenuNewWindow__btn"
type="button"
onMouseUp={this.handleOpenBrowser}
>
{text.openNewBrowser}
</button>
</li>
<li className="MenuNewWindow__list">
<button
className="MenuNewWindow__btn"
type="button"
onMouseUp={this.handleMovementPage}
>
{text.moveBrowser}
</button>
</li>
<li className="MenuNewWindow__list">
<button
className="MenuNewWindow__btn"
type="button"
onMouseUp={this.handleOpenWidget}
>
{text.openNewWidget}
</button>
</li>
</ul>
);
}
}

MenuNewWindow.propTypes = propTypes;
MenuNewWindow.defaultProps = defaultProps;

export default MenuNewWindow;
36 changes: 24 additions & 12 deletions app/page/webview/components/WebWidget/index.jsx
@@ -1,6 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
// import { shell } from 'electron';
import url from 'url';
import * as PATH from 'constants/path';
import * as USER_AGENT from 'constants/userAgent';
Expand All @@ -17,14 +16,12 @@ const propTypes = {
name: PropTypes.string,
url: PropTypes.string,
}),
onOpenModal: PropTypes.func,
onOpenPreference: PropTypes.func,
onUpdateInfo: PropTypes.func,
};
const defaultProps = {
defaultMode: 'DESKTOP',
widget: {},
onOpenModal() {},
onOpenPreference() {},
onUpdateInfo() {},
};
Expand All @@ -36,6 +33,7 @@ class WebWidget extends React.Component {
isLoading: false,
isSettingOpen: false,
isMobileHeaderOpen: true,
newWindowURL: null,
};
this.webViewRef = React.createRef();
this.prevScrollY = 0;
Expand All @@ -50,6 +48,7 @@ class WebWidget extends React.Component {
this.handleWidgetRefresh = this.handleWidgetRefresh.bind(this);
this.handleWidgetStopRefresh = this.handleWidgetStopRefresh.bind(this);
this.handleToggleSettingMenu = this.handleToggleSettingMenu.bind(this);
this.handleToggleNewWindowMenu = this.handleToggleNewWindowMenu.bind(this);
}

componentDidMount() {
Expand All @@ -69,16 +68,15 @@ class WebWidget extends React.Component {
y: e.pageY,
};
});
this.webViewRef.current.addEventListener('new-window', () => {
const { onOpenModal } = this.props;
onOpenModal(MenuNewWindow, {});
this.webViewRef.current.addEventListener('new-window', (e) => {
this.handleToggleNewWindowMenu(e.url);
});

this.webViewRef.current.addEventListener('dom-ready', () => {
window.addEventListener('contextmenu', () => {
widgetContextMenu(this.webViewRef.current);
});
this.webViewRef.current.openDevTools();
// this.webViewRef.current.openDevTools();
});

// Communicate webview tag and BrowserWindow
Expand Down Expand Up @@ -120,10 +118,6 @@ class WebWidget extends React.Component {
}
}

// componentWillUnmount() {
//
// }

toggleIsOnTop() {
const { widget, onUpdateInfo } = this.props;

Expand All @@ -150,7 +144,15 @@ class WebWidget extends React.Component {
if (typeof bool === 'boolean') {
this.setState({ isSettingOpen: bool });
} else {
this.setState(nextState => ({ isSettingOpen: !nextState.isSettingOpen }));
this.setState(prevState => ({ isSettingOpen: !prevState.isSettingOpen }));
}
}

handleToggleNewWindowMenu(targetURL) {
if (targetURL) {
this.setState({ newWindowURL: targetURL });
} else {
this.setState({ newWindowURL: '' });
}
}

Expand All @@ -159,6 +161,7 @@ class WebWidget extends React.Component {
isLoading,
isSettingOpen,
isMobileHeaderOpen,
newWindowURL,
} = this.state;
const {
widget,
Expand Down Expand Up @@ -200,6 +203,15 @@ class WebWidget extends React.Component {
onOpenPreference={onOpenPreference}
/>
)}
{newWindowURL && (
<MenuNewWindow
url={newWindowURL}
webview={this.webViewRef.current}
x={this.mousePosition.x}
y={this.mousePosition.y}
onClose={this.handleToggleNewWindowMenu}
/>
)}
<webview
ref={this.webViewRef}
src="https://www.github.com"
Expand Down
2 changes: 0 additions & 2 deletions app/page/webview/containers/WebWidgetContainer.jsx
Expand Up @@ -4,7 +4,6 @@ import { getIndividualInfo } from 'store/share/widgets/selectors';
import { widgetModeSelector } from 'store/share/status/selectors';
import { updateTargetWidgetInfo } from 'actions/widget';
import { openPreference } from 'actions/status';
import { modalOpen } from 'actions/modal';
import WebWidget from '../components/WebWidget';

const mapStateToProps = state => ({
Expand All @@ -15,7 +14,6 @@ const mapStateToProps = state => ({
const mapDispatchToProps = {
onUpdateInfo: updateTargetWidgetInfo,
onOpenPreference: openPreference,
onOpenModal: modalOpen,
};

export default connect(mapStateToProps, mapDispatchToProps)(toJS(WebWidget));
4 changes: 2 additions & 2 deletions app/page/webview/index.jsx
@@ -1,17 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import WebWidget from 'webview/components/WebWidget';
import getStore from 'store/createStore';
import subscribeActionRenderer from 'store/utils/subscribeActionRenderer';
import 'scss/index.scss';
import WebWidgetContainer from './containers/WebWidgetContainer';

const store = getStore();
subscribeActionRenderer(store);

ReactDOM.render(
<Provider store={store}>
<WebWidget />
<WebWidgetContainer />
</Provider>,
document.getElementById('root'),
);

0 comments on commit b951b4c

Please sign in to comment.