aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/webControls/containers/WebControlsScreen.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/webControls/containers/WebControlsScreen.tsx')
-rw-r--r--src/features/webControls/containers/WebControlsScreen.tsx163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/features/webControls/containers/WebControlsScreen.tsx b/src/features/webControls/containers/WebControlsScreen.tsx
new file mode 100644
index 000000000..f6f1cddb8
--- /dev/null
+++ b/src/features/webControls/containers/WebControlsScreen.tsx
@@ -0,0 +1,163 @@
1import { Component, ReactElement } from 'react';
2import { observer, inject } from 'mobx-react';
3import {
4 autorun,
5 action,
6 makeObservable,
7 observable,
8 IReactionDisposer,
9} from 'mobx';
10import ElectronWebView from 'react-electron-web-view';
11import WebControls from '../components/WebControls';
12import Service from '../../../models/Service';
13import { SEARCH_ENGINE_URLS } from '../../../config';
14import { StoresProps } from '../../../@types/ferdium-components.types';
15
16const URL_EVENTS = [
17 'load-commit',
18 'will-navigate',
19 'did-navigate',
20 'did-navigate-in-page',
21];
22
23interface IProps extends Partial<StoresProps> {
24 service: Service;
25}
26
27@inject('stores', 'actions')
28@observer
29class WebControlsScreen extends Component<IProps> {
30 @observable url = '';
31
32 @observable canGoBack = false;
33
34 @observable canGoForward = false;
35
36 webview: ElectronWebView | null = null;
37
38 autorunDisposer: IReactionDisposer | null = null;
39
40 constructor(props) {
41 super(props);
42
43 makeObservable(this);
44 }
45
46 componentDidMount(): void {
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) {
57 return;
58 }
59 this._setUrlAndHistory(e.url);
60 });
61 }
62 }
63 });
64 }
65
66 componentWillUnmount(): void {
67 if (this.autorunDisposer) {
68 this.autorunDisposer();
69 }
70 }
71
72 @action
73 _setUrl(value): void {
74 this.url = value;
75 }
76
77 @action
78 _setUrlAndHistory(value): void {
79 this._setUrl(value);
80 this.canGoBack = this.webview.canGoBack();
81 this.canGoForward = this.webview.canGoForward();
82 }
83
84 goHome(): void {
85 if (!this.webview) {
86 return;
87 }
88 this.webview.goToIndex(0);
89 }
90
91 reload(): void {
92 if (!this.webview) {
93 return;
94 }
95
96 this.webview.reload();
97 }
98
99 goBack(): void {
100 if (!this.webview) {
101 return;
102 }
103
104 this.webview.goBack();
105 }
106
107 goForward(): void {
108 if (!this.webview) {
109 return;
110 }
111
112 this.webview.goForward();
113 }
114
115 navigate(url: string): void {
116 if (!this.webview) {
117 return;
118 }
119
120 try {
121 url = new URL(url).toString();
122 } catch {
123 url =
124 /^((?!-))(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(
125 url,
126 )
127 ? `http://${url}`
128 : SEARCH_ENGINE_URLS[this.props.stores!.settings.app.searchEngine]({
129 searchTerm: url,
130 });
131 }
132
133 this.webview.loadURL(url);
134 this._setUrl(url);
135 }
136
137 openInBrowser(): void {
138 const { openExternalUrl } = this.props.actions!.app;
139 if (!this.webview) {
140 return;
141 }
142
143 openExternalUrl({ url: this.url });
144 }
145
146 render(): ReactElement {
147 return (
148 <WebControls
149 goHome={() => this.goHome()}
150 reload={() => this.reload()}
151 openInBrowser={() => this.openInBrowser()}
152 canGoBack={this.canGoBack}
153 goBack={() => this.goBack()}
154 canGoForward={this.canGoForward}
155 goForward={() => this.goForward()}
156 navigate={url => this.navigate(url)}
157 url={this.url}
158 />
159 );
160 }
161}
162
163export default WebControlsScreen;