aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/webControls/containers/WebControlsScreen.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/webControls/containers/WebControlsScreen.jsx')
-rw-r--r--src/features/webControls/containers/WebControlsScreen.jsx151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/features/webControls/containers/WebControlsScreen.jsx b/src/features/webControls/containers/WebControlsScreen.jsx
new file mode 100644
index 000000000..25e14060d
--- /dev/null
+++ b/src/features/webControls/containers/WebControlsScreen.jsx
@@ -0,0 +1,151 @@
1import { Component } from 'react';
2import { observer, inject } from 'mobx-react';
3import PropTypes from 'prop-types';
4
5import { autorun, action, makeObservable, observable } from 'mobx';
6import WebControls from '../components/WebControls';
7import ServicesStore from '../../../stores/ServicesStore';
8import Service from '../../../models/Service';
9import { SEARCH_ENGINE_URLS } from '../../../config';
10import AppStore from '../../../stores/AppStore';
11
12const URL_EVENTS = [
13 'load-commit',
14 'will-navigate',
15 'did-navigate',
16 'did-navigate-in-page',
17];
18
19class WebControlsScreen extends Component {
20 @observable url = '';
21
22 @observable canGoBack = false;
23
24 @observable canGoForward = false;
25
26 webview = null;
27
28 autorunDisposer = null;
29
30 @action _setUrl(value) {
31 this.url = value;
32 }
33
34 @action _setUrlAndHistory(value) {
35 this._setUrl(value);
36 this.canGoBack = this.webview.canGoBack();
37 this.canGoForward = this.webview.canGoForward();
38 }
39
40 constructor(props) {
41 super(props);
42
43 makeObservable(this);
44 }
45
46 componentDidMount() {
47 const { service } = this.props;
48
49 this.autorunDisposer = autorun(() => {
50 if (service.isAttached) {
51 this.webview = service.webview;
52 this._setUrl(this.webview.getURL());
53
54 for (const event of URL_EVENTS) {
55 this.webview.addEventListener(event, e => {
56 if (!e.isMainFrame) return;
57
58 this._setUrlAndHistory(e.url);
59 });
60 }
61 }
62 });
63 }
64
65 componentWillUnmount() {
66 this.autorunDisposer();
67 }
68
69 goHome() {
70 if (!this.webview) return;
71 this.webview.goToIndex(0);
72 }
73
74 reload() {
75 if (!this.webview) return;
76
77 this.webview.reload();
78 }
79
80 goBack() {
81 if (!this.webview) return;
82
83 this.webview.goBack();
84 }
85
86 goForward() {
87 if (!this.webview) return;
88
89 this.webview.goForward();
90 }
91
92 navigate(newUrl) {
93 if (!this.webview) return;
94
95 let url = newUrl;
96
97 try {
98 url = new URL(url).toString();
99 } catch {
100 url =
101 // eslint-disable-next-line no-useless-escape
102 /^((?!-))(xn--)?[\da-z][\d_a-z-]{0,61}[\da-z]{0,1}\.(xn--)?([\da-z\-]{1,61}|[\da-z-]{1,30}\.[a-z]{2,})$/.test(
103 url,
104 )
105 ? `http://${url}`
106 : SEARCH_ENGINE_URLS[this.settings.app.searchEngine]({
107 searchTerm: url,
108 });
109 }
110
111 this.webview.loadURL(url);
112 this._setUrl(url);
113 }
114
115 openInBrowser() {
116 const { openExternalUrl } = this.props.actions.app;
117
118 if (!this.webview) return;
119
120 openExternalUrl({ url: this.url });
121 }
122
123 render() {
124 return (
125 <WebControls
126 goHome={() => this.goHome()}
127 reload={() => this.reload()}
128 openInBrowser={() => this.openInBrowser()}
129 canGoBack={this.canGoBack}
130 goBack={() => this.goBack()}
131 canGoForward={this.canGoForward}
132 goForward={() => this.goForward()}
133 navigate={url => this.navigate(url)}
134 url={this.url}
135 />
136 );
137 }
138}
139
140export default inject('stores', 'actions')(observer(WebControlsScreen));
141
142WebControlsScreen.propTypes = {
143 service: PropTypes.instanceOf(Service).isRequired,
144 stores: PropTypes.shape({
145 services: PropTypes.instanceOf(ServicesStore).isRequired,
146 }).isRequired,
147 actions: PropTypes.shape({
148 app: PropTypes.instanceOf(AppStore).isRequired,
149 service: PropTypes.instanceOf(ServicesStore).isRequired,
150 }).isRequired,
151};