diff options
Diffstat (limited to 'packages/shared/src/stores/ServiceBase.ts')
-rw-r--r-- | packages/shared/src/stores/ServiceBase.ts | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/packages/shared/src/stores/ServiceBase.ts b/packages/shared/src/stores/ServiceBase.ts new file mode 100644 index 0000000..b2aff67 --- /dev/null +++ b/packages/shared/src/stores/ServiceBase.ts | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2021-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 { type IAnyModelType, type Instance, types } from 'mobx-state-tree'; | ||
22 | |||
23 | import ServiceSettingsBase from './ServiceSettingsBase.js'; | ||
24 | import ServiceState from './ServiceState.js'; | ||
25 | |||
26 | export enum SecurityLabelKind { | ||
27 | Empty = 'empty', | ||
28 | SecureConnection = 'secureConnection', | ||
29 | NotSecureConnection = 'notSecureConnection', | ||
30 | CertificateError = 'certificateError', | ||
31 | InvalidURL = 'invalidURL', | ||
32 | } | ||
33 | |||
34 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | ||
35 | return types | ||
36 | .model('Service', { | ||
37 | id: types.identifier, | ||
38 | settings, | ||
39 | currentUrl: types.maybe(types.string), | ||
40 | canGoBack: false, | ||
41 | canGoForward: false, | ||
42 | title: types.maybe(types.string), | ||
43 | state: ServiceState, | ||
44 | directMessageCount: 0, | ||
45 | indirectMessageCount: 0, | ||
46 | popups: types.array(types.string), | ||
47 | }) | ||
48 | .views((self) => ({ | ||
49 | get loading(): boolean { | ||
50 | return ( | ||
51 | self.state.type === 'initializing' || self.state.type === 'loading' | ||
52 | ); | ||
53 | }, | ||
54 | get crashed(): boolean { | ||
55 | return self.state.type === 'crashed'; | ||
56 | }, | ||
57 | get securityLabel(): SecurityLabelKind { | ||
58 | const { | ||
59 | state: { type: stateType }, | ||
60 | currentUrl, | ||
61 | } = self; | ||
62 | if (stateType === 'certificateError') { | ||
63 | return SecurityLabelKind.CertificateError; | ||
64 | } | ||
65 | if (currentUrl === undefined || currentUrl === '') { | ||
66 | return SecurityLabelKind.Empty; | ||
67 | } | ||
68 | try { | ||
69 | const parsedUrl = new URL(currentUrl); | ||
70 | switch (parsedUrl.protocol) { | ||
71 | case 'https:': | ||
72 | return SecurityLabelKind.SecureConnection; | ||
73 | case 'http:': | ||
74 | return SecurityLabelKind.NotSecureConnection; | ||
75 | default: | ||
76 | return SecurityLabelKind.InvalidURL; | ||
77 | } | ||
78 | } catch { | ||
79 | return SecurityLabelKind.InvalidURL; | ||
80 | } | ||
81 | }, | ||
82 | })) | ||
83 | .views((self) => ({ | ||
84 | get hasError(): boolean { | ||
85 | return ( | ||
86 | self.crashed || | ||
87 | self.state.type === 'failed' || | ||
88 | self.state.type === 'certificateError' | ||
89 | ); | ||
90 | }, | ||
91 | get hasSecurityLabelWarning(): boolean { | ||
92 | const { securityLabel } = self; | ||
93 | return ( | ||
94 | securityLabel !== SecurityLabelKind.Empty && | ||
95 | securityLabel !== SecurityLabelKind.SecureConnection | ||
96 | ); | ||
97 | }, | ||
98 | })) | ||
99 | .views((self) => ({ | ||
100 | get alwaysShowLocationBar(): boolean { | ||
101 | return self.hasError || self.hasSecurityLabelWarning; | ||
102 | }, | ||
103 | })); | ||
104 | } | ||
105 | |||
106 | const ServiceBase = /* @__PURE__ */ (() => | ||
107 | defineServiceModel(ServiceSettingsBase))(); | ||
108 | |||
109 | /* | ||
110 | eslint-disable-next-line @typescript-eslint/no-redeclare -- | ||
111 | Intentionally naming the type the same as the store definition. | ||
112 | */ | ||
113 | interface ServiceBase extends Instance<typeof ServiceBase> {} | ||
114 | |||
115 | export default ServiceBase; | ||