Fix review comments
This commit is contained in:
108
src/browser/components/Finder.jsx
Normal file
108
src/browser/components/Finder.jsx
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class Finder extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.webview = document.getElementById('mattermostView' + this.props.webviewKey);
|
||||
this.state = {
|
||||
foundInPage: false,
|
||||
searchTxt: '',
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.webview.addEventListener('found-in-page', this.foundInPage);
|
||||
this.searchInput.focus();
|
||||
|
||||
// synthetic events are not working all that reliably for touch bar with esc keys
|
||||
this.searchInput.addEventListener('keyup', this.handleKeyEvent);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.webview.stopFindInPage('clearSelection');
|
||||
this.webview.removeEventListener('found-in-page', this.foundInPage);
|
||||
this.searchInput.removeEventListener('keyup', this.handleKeyEvent);
|
||||
}
|
||||
|
||||
findNext = () => {
|
||||
this.webview.findInPage(this.state.searchTxt);
|
||||
};
|
||||
|
||||
find = (keyword) => {
|
||||
this.webview.stopFindInPage('clearSelection');
|
||||
if (keyword) {
|
||||
this.webview.findInPage(keyword);
|
||||
} else {
|
||||
this.setState({
|
||||
matches: '0/0',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
findPrev = () => {
|
||||
this.webview.findInPage(this.state.searchTxt, {forward: false});
|
||||
}
|
||||
|
||||
searchTxt = (event) => {
|
||||
this.setState({searchTxt: event.target.value});
|
||||
this.find(event.target.value);
|
||||
}
|
||||
|
||||
handleKeyEvent = (event) => {
|
||||
if (event.code === 'Escape') {
|
||||
this.props.close();
|
||||
} else if (event.code === 'Enter') {
|
||||
this.findNext();
|
||||
}
|
||||
}
|
||||
|
||||
foundInPage = (event) => {
|
||||
const {matches, activeMatchOrdinal} = event.result;
|
||||
this.setState({
|
||||
foundInPage: true,
|
||||
matches: `${activeMatchOrdinal}/${matches}`,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div id='finder'>
|
||||
<div className='finder'>
|
||||
<div className='finder-input-wrapper'>
|
||||
<input
|
||||
className='finder-input'
|
||||
placeholder=''
|
||||
value={this.state.searchTxt}
|
||||
onChange={this.searchTxt}
|
||||
ref={(input) => {
|
||||
this.searchInput = input;
|
||||
}}
|
||||
/>
|
||||
<span className={this.state.foundInPage ? 'finder-progress' : 'finder-progress finder-progress__disabled'}>{this.state.matches}</span>
|
||||
</div>
|
||||
<button
|
||||
className='finder-prev'
|
||||
onClick={this.findPrev}
|
||||
>{'↑'}</button>
|
||||
<button
|
||||
className='finder-next'
|
||||
onClick={this.findNext}
|
||||
>{'↓'}</button>
|
||||
<button
|
||||
className='finder-close'
|
||||
onClick={this.props.close}
|
||||
>{'✕'}</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Finder.propTypes = {
|
||||
close: PropTypes.func,
|
||||
webviewKey: PropTypes.number,
|
||||
};
|
@@ -11,7 +11,6 @@ import {Grid, Row} from 'react-bootstrap';
|
||||
|
||||
import {ipcRenderer, remote} from 'electron';
|
||||
|
||||
import Finder from '../../main/finder';
|
||||
import Utils from '../../utils/util.js';
|
||||
|
||||
import LoginModal from './LoginModal.jsx';
|
||||
@@ -19,7 +18,7 @@ import MattermostView from './MattermostView.jsx';
|
||||
import TabBar from './TabBar.jsx';
|
||||
import HoveringURL from './HoveringURL.jsx';
|
||||
import PermissionRequestDialog from './PermissionRequestDialog.jsx';
|
||||
|
||||
import Finder from './Finder.jsx';
|
||||
import NewTeamModal from './NewTeamModal.jsx';
|
||||
|
||||
const MainPage = createReactClass({
|
||||
@@ -144,24 +143,20 @@ const MainPage = createReactClass({
|
||||
}
|
||||
});
|
||||
|
||||
const webview = document.getElementById('mattermostView' + this.state.key);
|
||||
this.finder = new Finder(webview);
|
||||
ipcRenderer.on('toggle-find', () => {
|
||||
this.finder.toggle();
|
||||
this.toggleFinder();
|
||||
});
|
||||
},
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.key !== this.state.key) { // i.e. When tab has been changed
|
||||
this.refs[`mattermostView${this.state.key}`].focusOnWebView();
|
||||
this.finder.destroy();
|
||||
const webview = document.getElementById('mattermostView' + this.state.key);
|
||||
this.finder = new Finder(webview);
|
||||
}
|
||||
},
|
||||
handleSelect(key) {
|
||||
const newKey = (this.props.teams.length + key) % this.props.teams.length;
|
||||
this.setState({
|
||||
key: newKey,
|
||||
finderVisible: false,
|
||||
});
|
||||
var webview = document.getElementById('mattermostView' + newKey);
|
||||
ipcRenderer.send('update-title', {
|
||||
@@ -256,13 +251,20 @@ const MainPage = createReactClass({
|
||||
});
|
||||
},
|
||||
|
||||
focusOnWebView() {
|
||||
this.refs[`mattermostView${this.state.key}`].focusOnWebView();
|
||||
focusOnWebView(e) {
|
||||
if (e.target.className !== 'finder-input') {
|
||||
this.refs[`mattermostView${this.state.key}`].focusOnWebView();
|
||||
}
|
||||
},
|
||||
|
||||
toggleFinder() {
|
||||
this.setState({
|
||||
finderVisible: !this.state.finderVisible,
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
var self = this;
|
||||
|
||||
var tabsRow;
|
||||
if (this.props.teams.length > 1) {
|
||||
tabsRow = (
|
||||
@@ -376,6 +378,12 @@ const MainPage = createReactClass({
|
||||
<Grid fluid={true}>
|
||||
{ tabsRow }
|
||||
{ viewsRow }
|
||||
{ this.state.finderVisible ? (
|
||||
<Finder
|
||||
webviewKey={this.state.key}
|
||||
close={this.toggleFinder}
|
||||
/>
|
||||
) : null}
|
||||
</Grid>
|
||||
<TransitionGroup>
|
||||
{ (this.state.targetURL === '') ?
|
||||
|
42
src/browser/css/components/Finder.css
Normal file
42
src/browser/css/components/Finder.css
Normal file
@@ -0,0 +1,42 @@
|
||||
.finder-input-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.finder button {
|
||||
border: 1px solid #d2d2d2;
|
||||
border-radius: 3px;
|
||||
background: white;
|
||||
outline: none;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.finder button:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.finder-input {
|
||||
border: 1px solid #d2d2d2;
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.finder-input:focus {
|
||||
border-color: #35b5f4;
|
||||
box-shadow: 0 0 1px #35b5f4;
|
||||
}
|
||||
|
||||
.finder-progress__disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.finder-progress {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
@@ -25,50 +25,3 @@ div[id*="-permissionDialog"] {
|
||||
border-bottom-right-radius: 5px;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
.finder-input-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.finder button {
|
||||
border: 1px solid #d2d2d2;
|
||||
border-radius: 3px;
|
||||
background: white;
|
||||
outline: none;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.finder button:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.finder-input {
|
||||
border: 1px solid #d2d2d2;
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.finder-input:focus {
|
||||
border-color: #35b5f4;
|
||||
box-shadow: 0 0 1px #35b5f4;
|
||||
}
|
||||
|
||||
.finder__hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.finder-progress__disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.finder-progress {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
@@ -6,3 +6,4 @@
|
||||
@import url("PermissionRequestDialog.css");
|
||||
@import url("TabBar.css");
|
||||
@import url("TeamListItem.css");
|
||||
@import url("Finder.css");
|
||||
|
@@ -1,109 +0,0 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export default class Finder {
|
||||
constructor(target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
return this.opened ? this.close() : this.open();
|
||||
}
|
||||
|
||||
open() {
|
||||
if (!this.initialized) {
|
||||
this.initialize();
|
||||
}
|
||||
this.opened = true;
|
||||
this.$finder.classList.remove('finder__hidden');
|
||||
this.$input.focus();
|
||||
}
|
||||
|
||||
close = () => {
|
||||
this.opened = false;
|
||||
this.target.stopFindInPage('clearSelection');
|
||||
this.$finder.classList.add('finder__hidden');
|
||||
}
|
||||
|
||||
findNext = () => {
|
||||
if (this.$input.value) {
|
||||
this.target.findInPage(this.$input.value);
|
||||
}
|
||||
}
|
||||
|
||||
findPrev = () => {
|
||||
if (this.$input.value) {
|
||||
this.target.findInPage(this.$input.value, {forward: false});
|
||||
}
|
||||
}
|
||||
|
||||
find = (keyword) => {
|
||||
this.target.stopFindInPage('clearSelection');
|
||||
if (keyword) {
|
||||
this.target.findInPage(keyword);
|
||||
} else {
|
||||
this.$progress.textContent = '0/0';
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyEvent = (event) => {
|
||||
if (event.code === 'Escape') {
|
||||
this.close();
|
||||
} else if (event.code === 'Enter') {
|
||||
this.findNext();
|
||||
} else {
|
||||
this.find(event.target.value);
|
||||
}
|
||||
}
|
||||
|
||||
foundInPage = (event) => {
|
||||
const {matches, activeMatchOrdinal} = event.result;
|
||||
this.$progress.classList.remove('finder-progress__disabled');
|
||||
this.$progress.textContent = `${activeMatchOrdinal}/${matches}`;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.initialized = false;
|
||||
if (this.$input) {
|
||||
this.$input.removeEventListener('keyup', this.handleKeyEvent);
|
||||
this.$prev.removeEventListener('click', this.findPrev);
|
||||
this.$next.removeEventListener('click', this.findNext);
|
||||
this.$close.removeEventListener('click', this.close);
|
||||
this.target.removeEventListener('found-in-page', this.foundInPage);
|
||||
const searchDiv = document.getElementById('searchDiv');
|
||||
searchDiv.parentNode.removeChild(searchDiv);
|
||||
}
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.initialized = true;
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.setAttribute('id', 'searchDiv');
|
||||
wrapper.innerHTML = `
|
||||
<div class="finder finder__hidden">
|
||||
<div class="finder-input-wrapper">
|
||||
<input class="finder-input" placeholder="" />
|
||||
<span class="finder-progress finder-progress__disabled"></span>
|
||||
</div>
|
||||
<button class="finder-prev">↑</button>
|
||||
<button class="finder-next">↓</button>
|
||||
<button class="finder-close">✕</button>
|
||||
</div>`;
|
||||
|
||||
document.body.appendChild(wrapper);
|
||||
|
||||
this.$finder = wrapper.querySelector('.finder');
|
||||
this.$progress = this.$finder.querySelector('.finder-progress');
|
||||
this.$input = this.$finder.querySelector('.finder-input');
|
||||
this.$prev = this.$finder.querySelector('.finder-prev');
|
||||
this.$next = this.$finder.querySelector('.finder-next');
|
||||
this.$close = this.$finder.querySelector('.finder-close');
|
||||
|
||||
this.$input.addEventListener('keyup', this.handleKeyEvent);
|
||||
this.$prev.addEventListener('click', this.findPrev);
|
||||
this.$next.addEventListener('click', this.findNext);
|
||||
this.$close.addEventListener('click', this.close);
|
||||
this.target.addEventListener('found-in-page', this.foundInPage);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user