aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/quickSwitch
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/quickSwitch')
-rw-r--r--src/features/quickSwitch/Component.tsx (renamed from src/features/quickSwitch/Component.js)102
1 files changed, 47 insertions, 55 deletions
diff --git a/src/features/quickSwitch/Component.js b/src/features/quickSwitch/Component.tsx
index 16da22dce..fb85d61e1 100644
--- a/src/features/quickSwitch/Component.js
+++ b/src/features/quickSwitch/Component.tsx
@@ -1,17 +1,16 @@
1import { Component, createRef } from 'react'; 1import { ChangeEvent, Component, createRef, ReactElement } from 'react';
2import { getCurrentWindow } from '@electron/remote'; 2import { getCurrentWindow } from '@electron/remote';
3import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 3import { observer, inject } from 'mobx-react';
5import { reaction } from 'mobx'; 4import { reaction } from 'mobx';
6import injectSheet from 'react-jss'; 5import withStyles, { WithStylesProps } from 'react-jss';
7import { defineMessages, injectIntl } from 'react-intl'; 6import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
8import { compact, invoke } from 'lodash'; 7import { compact, invoke, noop } from 'lodash';
9 8import { StoresProps } from '../../@types/ferdium-components.types';
9import Service from '../../models/Service';
10import Input from '../../components/ui/input/index'; 10import Input from '../../components/ui/input/index';
11import { H1 } from '../../components/ui/headline'; 11import { H1 } from '../../components/ui/headline';
12import Modal from '../../components/ui/Modal'; 12import Modal from '../../components/ui/Modal';
13import { state as ModalState } from './store'; 13import { state as ModalState } from './store';
14import ServicesStore from '../../stores/ServicesStore';
15 14
16const messages = defineMessages({ 15const messages = defineMessages({
17 title: { 16 title: {
@@ -75,17 +74,20 @@ const styles = theme => ({
75 }, 74 },
76}); 75});
77 76
78class QuickSwitchModal extends Component { 77interface IProps
79 static propTypes = { 78 extends WithStylesProps<typeof styles>,
80 classes: PropTypes.object.isRequired, 79 Partial<StoresProps>,
81 }; 80 WrappedComponentProps {}
82 81
83 state = { 82interface IState {
84 selected: 0, 83 selected: number;
85 search: '', 84 search: string;
86 wasPrevVisible: false, 85 wasPrevVisible: boolean;
87 }; 86}
88 87
88@inject('stores', 'actions')
89@observer
90class QuickSwitchModal extends Component<IProps, IState> {
89 ARROW_DOWN = 40; 91 ARROW_DOWN = 40;
90 92
91 ARROW_UP = 38; 93 ARROW_UP = 38;
@@ -94,13 +96,19 @@ class QuickSwitchModal extends Component {
94 96
95 TAB = 9; 97 TAB = 9;
96 98
97 inputRef = createRef(); 99 inputRef = createRef<HTMLDivElement>();
98 100
99 serviceElements = {}; 101 serviceElements = {};
100 102
101 constructor(props) { 103 constructor(props) {
102 super(props); 104 super(props);
103 105
106 this.state = {
107 selected: 0,
108 search: '',
109 wasPrevVisible: false,
110 };
111
104 this._handleKeyDown = this._handleKeyDown.bind(this); 112 this._handleKeyDown = this._handleKeyDown.bind(this);
105 this._handleSearchUpdate = this._handleSearchUpdate.bind(this); 113 this._handleSearchUpdate = this._handleSearchUpdate.bind(this);
106 this._handleVisibilityChange = this._handleVisibilityChange.bind(this); 114 this._handleVisibilityChange = this._handleVisibilityChange.bind(this);
@@ -115,46 +123,46 @@ class QuickSwitchModal extends Component {
115 } 123 }
116 124
117 // Add global keydown listener when component mounts 125 // Add global keydown listener when component mounts
118 componentDidMount() { 126 componentDidMount(): void {
119 document.addEventListener('keydown', this._handleKeyDown); 127 document.addEventListener('keydown', this._handleKeyDown);
120 } 128 }
121 129
122 // Remove global keydown listener when component unmounts 130 // Remove global keydown listener when component unmounts
123 componentWillUnmount() { 131 componentWillUnmount(): void {
124 document.removeEventListener('keydown', this._handleKeyDown); 132 document.removeEventListener('keydown', this._handleKeyDown);
125 } 133 }
126 134
127 // Get currently shown services 135 // Get currently shown services
128 services() { 136 services(): Service[] {
129 let services = []; 137 let services: Service[] = [];
130 if ( 138 if (
131 this.state.search && 139 this.state.search &&
132 compact(invoke(this.state.search, 'match', /^[\da-z]/i)).length > 0 140 compact(invoke(this.state.search, 'match', /^[\da-z]/i)).length > 0
133 ) { 141 ) {
134 // Apply simple search algorythm to list of all services 142 // Apply simple search algorythm to list of all services
135 services = this.props.stores.services.allDisplayed; 143 services = this.props.stores!.services.allDisplayed;
136 services = services.filter( 144 services = services.filter(
137 service => 145 service =>
138 service.name.toLowerCase().search(this.state.search.toLowerCase()) !== 146 service.name.toLowerCase().search(this.state.search.toLowerCase()) !==
139 -1, 147 -1,
140 ); 148 );
141 } else if (this.props.stores.services.allDisplayed.length > 0) { 149 } else if (this.props.stores!.services.allDisplayed.length > 0) {
142 // Add the currently active service first 150 // Add the currently active service first
143 const currentService = this.props.stores.services.active; 151 const currentService = this.props.stores!.services.active;
144 if (currentService) { 152 if (currentService) {
145 services.push(currentService); 153 services.push(currentService);
146 } 154 }
147 155
148 // Add last used services to services array 156 // Add last used services to services array
149 for (const service of this.props.stores.services.lastUsedServices) { 157 for (const service of this.props.stores!.services.lastUsedServices) {
150 const tempService = this.props.stores.services.one(service); 158 const tempService = this.props.stores!.services.one(service);
151 if (tempService && !services.includes(tempService)) { 159 if (tempService && !services.includes(tempService)) {
152 services.push(tempService); 160 services.push(tempService);
153 } 161 }
154 } 162 }
155 163
156 // Add all other services in the default order 164 // Add all other services in the default order
157 for (const service of this.props.stores.services.allDisplayed) { 165 for (const service of this.props.stores!.services.allDisplayed) {
158 if (!services.includes(service)) { 166 if (!services.includes(service)) {
159 services.push(service); 167 services.push(service);
160 } 168 }
@@ -164,10 +172,10 @@ class QuickSwitchModal extends Component {
164 return services; 172 return services;
165 } 173 }
166 174
167 openService(index) { 175 openService(index): void {
168 // Open service 176 // Open service
169 const service = this.services()[index]; 177 const service = this.services()[index];
170 this.props.actions.service.setActive({ serviceId: service.id }); 178 this.props.actions!.service.setActive({ serviceId: service.id });
171 179
172 // Reset and close modal 180 // Reset and close modal
173 this.setState({ 181 this.setState({
@@ -179,7 +187,7 @@ class QuickSwitchModal extends Component {
179 187
180 // Change the selected service 188 // Change the selected service
181 // factor should be -1 or 1 189 // factor should be -1 or 1
182 changeSelected(factor) { 190 changeSelected(factor: number): any {
183 this.setState(state => { 191 this.setState(state => {
184 let newSelected = state.selected + factor; 192 let newSelected = state.selected + factor;
185 const services = this.services().length; 193 const services = this.services().length;
@@ -204,7 +212,7 @@ class QuickSwitchModal extends Component {
204 } 212 }
205 213
206 // Handle global key presses to change the selection 214 // Handle global key presses to change the selection
207 _handleKeyDown(event) { 215 _handleKeyDown(event: KeyboardEvent): void {
208 if (ModalState.isModalVisible) { 216 if (ModalState.isModalVisible) {
209 switch (event.keyCode) { 217 switch (event.keyCode) {
210 case this.ARROW_DOWN: 218 case this.ARROW_DOWN:
@@ -230,13 +238,13 @@ class QuickSwitchModal extends Component {
230 } 238 }
231 239
232 // Handle update of the search query 240 // Handle update of the search query
233 _handleSearchUpdate(evt) { 241 _handleSearchUpdate(event: ChangeEvent<HTMLInputElement>): void {
234 this.setState({ 242 this.setState({
235 search: evt.target.value, 243 search: event.target.value,
236 }); 244 });
237 } 245 }
238 246
239 _handleVisibilityChange() { 247 _handleVisibilityChange(): void {
240 const { isModalVisible } = ModalState; 248 const { isModalVisible } = ModalState;
241 249
242 if (isModalVisible && !this.state.wasPrevVisible) { 250 if (isModalVisible && !this.state.wasPrevVisible) {
@@ -273,21 +281,16 @@ class QuickSwitchModal extends Component {
273 } 281 }
274 282
275 // Close this modal 283 // Close this modal
276 close() { 284 close(): void {
277 ModalState.isModalVisible = false; 285 ModalState.isModalVisible = false;
278 } 286 }
279 287
280 render() { 288 render(): ReactElement {
281 const { isModalVisible } = ModalState; 289 const { isModalVisible } = ModalState;
282
283 const { openService } = this; 290 const { openService } = this;
284 291 const { classes, intl } = this.props;
285 const { classes } = this.props;
286
287 const services = this.services(); 292 const services = this.services();
288 293
289 const { intl } = this.props;
290
291 return ( 294 return (
292 <Modal 295 <Modal
293 isOpen={isModalVisible} 296 isOpen={isModalVisible}
@@ -316,6 +319,7 @@ class QuickSwitchModal extends Component {
316 : '' 319 : ''
317 } service`} 320 } service`}
318 onClick={() => openService(index)} 321 onClick={() => openService(index)}
322 onKeyDown={noop}
319 key={service.id} 323 key={service.id}
320 ref={el => { 324 ref={el => {
321 this.serviceElements[index] = el; 325 this.serviceElements[index] = el;
@@ -340,18 +344,6 @@ class QuickSwitchModal extends Component {
340 } 344 }
341} 345}
342 346
343QuickSwitchModal.propTypes = {
344 stores: PropTypes.shape({
345 services: PropTypes.instanceOf(ServicesStore).isRequired,
346 }).isRequired,
347 actions: PropTypes.shape({
348 service: PropTypes.instanceOf(ServicesStore).isRequired,
349 }).isRequired,
350 classes: PropTypes.object.isRequired,
351};
352
353export default injectIntl( 347export default injectIntl(
354 injectSheet(styles, { injectTheme: true })( 348 withStyles(styles, { injectTheme: true })(QuickSwitchModal),
355 inject('stores', 'actions')(observer(QuickSwitchModal)),
356 ),
357); 349);