diff options
Diffstat (limited to 'packages/renderer/src/stores/Service.ts')
-rw-r--r-- | packages/renderer/src/stores/Service.ts | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/packages/renderer/src/stores/Service.ts b/packages/renderer/src/stores/Service.ts new file mode 100644 index 0000000..ff01964 --- /dev/null +++ b/packages/renderer/src/stores/Service.ts | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com> | ||
3 | * | ||
4 | * This file is part of Sophie. | ||
5 | * | ||
6 | * Sophie is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Affero General Public License as | ||
8 | * published by the Free Software Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * SPDX-License-Identifier: AGPL-3.0-only | ||
19 | */ | ||
20 | |||
21 | import { | ||
22 | BrowserViewBounds, | ||
23 | defineServiceModel, | ||
24 | ServiceAction, | ||
25 | } from '@sophie/shared'; | ||
26 | import { Instance } from 'mobx-state-tree'; | ||
27 | |||
28 | import { getEnv } from './RendererEnv.js'; | ||
29 | import ServiceSettings from './ServiceSettings.js'; | ||
30 | |||
31 | const Service = defineServiceModel(ServiceSettings) | ||
32 | .views((self) => ({ | ||
33 | get canReconnectSecurely(): boolean { | ||
34 | const { currentUrl } = self; | ||
35 | if (currentUrl === undefined) { | ||
36 | return false; | ||
37 | } | ||
38 | try { | ||
39 | const { protocol } = new URL(currentUrl); | ||
40 | return protocol === 'http:'; | ||
41 | } catch { | ||
42 | return false; | ||
43 | } | ||
44 | }, | ||
45 | })) | ||
46 | .actions((self) => { | ||
47 | function dispatch(serviceAction: ServiceAction): void { | ||
48 | getEnv(self).dispatchMainAction({ | ||
49 | action: 'dispatch-service-action', | ||
50 | serviceId: self.id, | ||
51 | serviceAction, | ||
52 | }); | ||
53 | } | ||
54 | |||
55 | return { | ||
56 | setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { | ||
57 | dispatch({ | ||
58 | action: 'set-browser-view-bounds', | ||
59 | browserViewBounds, | ||
60 | }); | ||
61 | }, | ||
62 | goBack(): void { | ||
63 | dispatch({ | ||
64 | action: 'back', | ||
65 | }); | ||
66 | }, | ||
67 | goForward(): void { | ||
68 | dispatch({ | ||
69 | action: 'forward', | ||
70 | }); | ||
71 | }, | ||
72 | reload(ignoreCache = false): void { | ||
73 | dispatch({ | ||
74 | action: 'reload', | ||
75 | ignoreCache, | ||
76 | }); | ||
77 | }, | ||
78 | stop(): void { | ||
79 | dispatch({ | ||
80 | action: 'stop', | ||
81 | }); | ||
82 | }, | ||
83 | go(url: string): void { | ||
84 | dispatch({ | ||
85 | action: 'go', | ||
86 | url, | ||
87 | }); | ||
88 | }, | ||
89 | goHome(): void { | ||
90 | dispatch({ | ||
91 | action: 'go-home', | ||
92 | }); | ||
93 | }, | ||
94 | temporarilyTrustCurrentCertificate(): void { | ||
95 | if (self.state.type !== 'certificateError') { | ||
96 | throw new Error('No certificate to accept'); | ||
97 | } | ||
98 | dispatch({ | ||
99 | action: 'temporarily-trust-current-certificate', | ||
100 | fingerprint: self.state.certificate.fingerprint, | ||
101 | }); | ||
102 | }, | ||
103 | openCurrentURLInExternalBrowser(): void { | ||
104 | dispatch({ | ||
105 | action: 'open-current-url-in-external-browser', | ||
106 | }); | ||
107 | }, | ||
108 | followPopup(url: string): void { | ||
109 | dispatch({ | ||
110 | action: 'follow-popup', | ||
111 | url, | ||
112 | }); | ||
113 | }, | ||
114 | openPopupInExternalBrowser(url: string): void { | ||
115 | dispatch({ | ||
116 | action: 'open-popup-in-external-browser', | ||
117 | url, | ||
118 | }); | ||
119 | }, | ||
120 | openAllPopupsInExternalBrowser(): void { | ||
121 | dispatch({ | ||
122 | action: 'open-all-popups-in-external-browser', | ||
123 | }); | ||
124 | }, | ||
125 | dismissPopup(url: string): void { | ||
126 | dispatch({ | ||
127 | action: 'dismiss-popup', | ||
128 | url, | ||
129 | }); | ||
130 | }, | ||
131 | dismissAllPopups(): void { | ||
132 | dispatch({ | ||
133 | action: 'dismiss-all-popups', | ||
134 | }); | ||
135 | }, | ||
136 | downloadCertificate(fingerprint: string): void { | ||
137 | dispatch({ | ||
138 | action: 'download-certificate', | ||
139 | fingerprint, | ||
140 | }); | ||
141 | }, | ||
142 | }; | ||
143 | }) | ||
144 | .actions((self) => ({ | ||
145 | reconnectSecurely(): void { | ||
146 | const { currentUrl, canReconnectSecurely } = self; | ||
147 | if (currentUrl === undefined || !canReconnectSecurely) { | ||
148 | return; | ||
149 | } | ||
150 | const url = new URL(currentUrl); | ||
151 | url.protocol = 'https:'; | ||
152 | self.go(url.toString()); | ||
153 | }, | ||
154 | })); | ||
155 | |||
156 | /* | ||
157 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
158 | Intentionally naming the type the same as the store definition. | ||
159 | */ | ||
160 | interface Service extends Instance<typeof Service> {} | ||
161 | |||
162 | export default Service; | ||