aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared/src/stores/ServiceBase.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/shared/src/stores/ServiceBase.ts')
-rw-r--r--packages/shared/src/stores/ServiceBase.ts115
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
21import { type IAnyModelType, type Instance, types } from 'mobx-state-tree';
22
23import ServiceSettingsBase from './ServiceSettingsBase.js';
24import ServiceState from './ServiceState.js';
25
26export enum SecurityLabelKind {
27 Empty = 'empty',
28 SecureConnection = 'secureConnection',
29 NotSecureConnection = 'notSecureConnection',
30 CertificateError = 'certificateError',
31 InvalidURL = 'invalidURL',
32}
33
34export 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
106const 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*/
113interface ServiceBase extends Instance<typeof ServiceBase> {}
114
115export default ServiceBase;