Add CTRL+F shortcut to work as browser search
* Add new finder for each webview contents
This commit is contained in:
parent
e0943cc7fd
commit
e95c8cc3c5
2
.babelrc
2
.babelrc
|
@ -8,5 +8,5 @@
|
|||
}],
|
||||
"react"
|
||||
],
|
||||
"plugins": ["transform-object-rest-spread"]
|
||||
"plugins": ["transform-object-rest-spread", "transform-class-properties"]
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ 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';
|
||||
|
@ -45,6 +46,7 @@ const MainPage = createReactClass({
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
key,
|
||||
unreadCounts: new Array(this.props.teams.length),
|
||||
|
@ -141,10 +143,19 @@ const MainPage = createReactClass({
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
const webview = document.getElementById('mattermostView' + this.state.key);
|
||||
this.finder = new Finder(webview);
|
||||
ipcRenderer.on('toggle-find', () => {
|
||||
this.finder.toggle();
|
||||
});
|
||||
},
|
||||
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) {
|
||||
|
@ -152,13 +163,13 @@ const MainPage = createReactClass({
|
|||
this.setState({
|
||||
key: newKey,
|
||||
});
|
||||
this.handleOnTeamFocused(newKey);
|
||||
|
||||
var webview = document.getElementById('mattermostView' + newKey);
|
||||
ipcRenderer.send('update-title', {
|
||||
title: webview.getTitle(),
|
||||
});
|
||||
this.handleOnTeamFocused(newKey);
|
||||
},
|
||||
|
||||
handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned) {
|
||||
var unreadCounts = this.state.unreadCounts;
|
||||
var mentionCounts = this.state.mentionCounts;
|
||||
|
|
|
@ -11,3 +11,64 @@
|
|||
div[id*="-permissionDialog"] {
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.finder {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 20px;
|
||||
padding: 5px;
|
||||
background: #eee;
|
||||
border: 1px solid #d7d7d7;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-bottom-left-radius: 5px;
|
||||
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;
|
||||
}
|
||||
|
|
109
src/main/finder.js
Normal file
109
src/main/finder.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
|
@ -95,6 +95,12 @@ function createTemplate(mainWindow, config, isDev) {
|
|||
template.push({
|
||||
label: '&View',
|
||||
submenu: [{
|
||||
label: 'Find..',
|
||||
accelerator: 'CmdOrCtrl+F',
|
||||
click(item, focusedWindow) {
|
||||
focusedWindow.webContents.send('toggle-find');
|
||||
},
|
||||
}, {
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click(item, focusedWindow) {
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports = merge(base, {
|
|||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.jsx$/,
|
||||
test: /\.(js|jsx)?$/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue