diff options
Diffstat (limited to 'src/features/webControls/components/WebControls.js')
-rw-r--r-- | src/features/webControls/components/WebControls.js | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/src/features/webControls/components/WebControls.js b/src/features/webControls/components/WebControls.js new file mode 100644 index 000000000..c6331073b --- /dev/null +++ b/src/features/webControls/components/WebControls.js | |||
@@ -0,0 +1,243 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import injectSheet from 'react-jss'; | ||
5 | import { Icon } from '@meetfranz/ui'; | ||
6 | import { defineMessages, intlShape } from 'react-intl'; | ||
7 | |||
8 | import { | ||
9 | mdiReload, mdiArrowRight, mdiArrowLeft, mdiHomeOutline, mdiEarth, | ||
10 | } from '@mdi/js'; | ||
11 | |||
12 | const messages = defineMessages({ | ||
13 | goHome: { | ||
14 | id: 'webControls.goHome', | ||
15 | defaultMessage: '!!!Home', | ||
16 | }, | ||
17 | openInBrowser: { | ||
18 | id: 'webControls.openInBrowser', | ||
19 | defaultMessage: '!!!Open in Browser', | ||
20 | }, | ||
21 | back: { | ||
22 | id: 'webControls.back', | ||
23 | defaultMessage: '!!!Back', | ||
24 | }, | ||
25 | forward: { | ||
26 | id: 'webControls.forward', | ||
27 | defaultMessage: '!!!Forward', | ||
28 | }, | ||
29 | reload: { | ||
30 | id: 'webControls.reload', | ||
31 | defaultMessage: '!!!Reload', | ||
32 | }, | ||
33 | }); | ||
34 | |||
35 | const styles = theme => ({ | ||
36 | root: { | ||
37 | background: theme.colorBackground, | ||
38 | position: 'relative', | ||
39 | borderLeft: [1, 'solid', theme.todos.todosLayer.borderLeftColor], | ||
40 | zIndex: 300, | ||
41 | height: 50, | ||
42 | display: 'flex', | ||
43 | flexDirection: 'row', | ||
44 | alignItems: 'center', | ||
45 | padding: [0, 10], | ||
46 | |||
47 | '& + div': { | ||
48 | height: 'calc(100% - 50px)', | ||
49 | }, | ||
50 | }, | ||
51 | button: { | ||
52 | width: 30, | ||
53 | height: 50, | ||
54 | transition: 'opacity 0.25s', | ||
55 | |||
56 | '&:hover': { | ||
57 | opacity: 0.8, | ||
58 | }, | ||
59 | |||
60 | '&:disabled': { | ||
61 | opacity: 0.5, | ||
62 | }, | ||
63 | }, | ||
64 | icon: { | ||
65 | width: '20px !important', | ||
66 | height: 20, | ||
67 | marginTop: 5, | ||
68 | }, | ||
69 | input: { | ||
70 | marginBottom: 0, | ||
71 | height: 'auto', | ||
72 | margin: [0, 10], | ||
73 | flex: 1, | ||
74 | border: 0, | ||
75 | padding: [4, 10], | ||
76 | borderRadius: theme.borderRadius, | ||
77 | background: theme.inputBackground, | ||
78 | color: theme.inputColor, | ||
79 | }, | ||
80 | inputButton: { | ||
81 | color: theme.colorText, | ||
82 | }, | ||
83 | }); | ||
84 | |||
85 | @injectSheet(styles) @observer | ||
86 | class WebControls extends Component { | ||
87 | static propTypes = { | ||
88 | classes: PropTypes.object.isRequired, | ||
89 | goHome: PropTypes.func.isRequired, | ||
90 | canGoBack: PropTypes.bool.isRequired, | ||
91 | goBack: PropTypes.func.isRequired, | ||
92 | canGoForward: PropTypes.bool.isRequired, | ||
93 | goForward: PropTypes.func.isRequired, | ||
94 | reload: PropTypes.func.isRequired, | ||
95 | openInBrowser: PropTypes.func.isRequired, | ||
96 | url: PropTypes.string.isRequired, | ||
97 | navigate: PropTypes.func.isRequired, | ||
98 | } | ||
99 | |||
100 | static contextTypes = { | ||
101 | intl: intlShape, | ||
102 | }; | ||
103 | |||
104 | static getDerivedStateFromProps(props, state) { | ||
105 | const { url } = props; | ||
106 | const { editUrl } = state; | ||
107 | |||
108 | if (!editUrl) { | ||
109 | return { | ||
110 | inputUrl: url, | ||
111 | editUrl: state.editUrl, | ||
112 | }; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | inputRef = React.createRef(); | ||
117 | |||
118 | state = { | ||
119 | inputUrl: '', | ||
120 | editUrl: false, | ||
121 | } | ||
122 | |||
123 | render() { | ||
124 | const { | ||
125 | classes, | ||
126 | goHome, | ||
127 | canGoBack, | ||
128 | goBack, | ||
129 | canGoForward, | ||
130 | goForward, | ||
131 | reload, | ||
132 | openInBrowser, | ||
133 | url, | ||
134 | navigate, | ||
135 | } = this.props; | ||
136 | |||
137 | const { | ||
138 | inputUrl, | ||
139 | editUrl, | ||
140 | } = this.state; | ||
141 | |||
142 | const { intl } = this.context; | ||
143 | |||
144 | return ( | ||
145 | <div className={classes.root}> | ||
146 | <button | ||
147 | onClick={goHome} | ||
148 | type="button" | ||
149 | className={classes.button} | ||
150 | data-tip={intl.formatMessage(messages.goHome)} | ||
151 | data-place="bottom" | ||
152 | > | ||
153 | <Icon | ||
154 | icon={mdiHomeOutline} | ||
155 | className={classes.icon} | ||
156 | /> | ||
157 | </button> | ||
158 | <button | ||
159 | onClick={goBack} | ||
160 | type="button" | ||
161 | className={classes.button} | ||
162 | disabled={!canGoBack} | ||
163 | data-tip={intl.formatMessage(messages.back)} | ||
164 | data-place="bottom" | ||
165 | > | ||
166 | <Icon | ||
167 | icon={mdiArrowLeft} | ||
168 | className={classes.icon} | ||
169 | /> | ||
170 | </button> | ||
171 | <button | ||
172 | onClick={goForward} | ||
173 | type="button" | ||
174 | className={classes.button} | ||
175 | disabled={!canGoForward} | ||
176 | data-tip={intl.formatMessage(messages.forward)} | ||
177 | data-place="bottom" | ||
178 | > | ||
179 | <Icon | ||
180 | icon={mdiArrowRight} | ||
181 | className={classes.icon} | ||
182 | /> | ||
183 | </button> | ||
184 | <button | ||
185 | onClick={reload} | ||
186 | type="button" | ||
187 | className={classes.button} | ||
188 | data-tip={intl.formatMessage(messages.reload)} | ||
189 | data-place="bottom" | ||
190 | > | ||
191 | <Icon | ||
192 | icon={mdiReload} | ||
193 | className={classes.icon} | ||
194 | /> | ||
195 | </button> | ||
196 | <input | ||
197 | value={editUrl ? inputUrl : url} | ||
198 | className={classes.input} | ||
199 | onChange={event => this.setState({ | ||
200 | inputUrl: event.target.value, | ||
201 | })} | ||
202 | onFocus={(event) => { | ||
203 | console.log('on focus event'); | ||
204 | event.target.select(); | ||
205 | this.setState({ | ||
206 | editUrl: true, | ||
207 | }); | ||
208 | }} | ||
209 | onKeyDown={(event) => { | ||
210 | if (event.key === 'Enter') { | ||
211 | this.setState({ | ||
212 | editUrl: false, | ||
213 | }); | ||
214 | navigate(inputUrl); | ||
215 | this.inputRef.current.blur(); | ||
216 | } else if (event.key === 'Escape') { | ||
217 | this.setState({ | ||
218 | editUrl: false, | ||
219 | inputUrl: url, | ||
220 | }); | ||
221 | event.target.blur(); | ||
222 | } | ||
223 | }} | ||
224 | ref={this.inputRef} | ||
225 | /> | ||
226 | <button | ||
227 | onClick={openInBrowser} | ||
228 | type="button" | ||
229 | className={classes.button} | ||
230 | data-tip={intl.formatMessage(messages.openInBrowser)} | ||
231 | data-place="bottom" | ||
232 | > | ||
233 | <Icon | ||
234 | icon={mdiEarth} | ||
235 | className={classes.icon} | ||
236 | /> | ||
237 | </button> | ||
238 | </div> | ||
239 | ); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | export default WebControls; | ||