diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-04-20 00:28:38 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-05-16 00:55:01 +0200 |
commit | 9462cec9a7dc5b6722df464559721cd2445636e6 (patch) | |
tree | 08a266cc2c6d65e55ffe76b279f310d1cf517bdd /packages/shared | |
parent | fix(renderer): Improve appearance in small windows (diff) | |
download | sophie-9462cec9a7dc5b6722df464559721cd2445636e6.tar.gz sophie-9462cec9a7dc5b6722df464559721cd2445636e6.tar.zst sophie-9462cec9a7dc5b6722df464559721cd2445636e6.zip |
feat: Always show location bar on error
The location bar should be visible on error page to let people see and
change the URL if needed.
Additionally, it must be visible on insecure connections to show people
that the connection if not secure.
In the future, the location bar should also be shown if the loaded
website is uncommon in the context of the current service, i.e., it is
not explcitly allowlisted by the recipe.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/shared')
-rw-r--r-- | packages/shared/src/index.ts | 1 | ||||
-rw-r--r-- | packages/shared/src/stores/ServiceBase.ts | 55 | ||||
-rw-r--r-- | packages/shared/src/stores/SharedStoreBase.ts | 39 |
3 files changed, 80 insertions, 15 deletions
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 95af73a..e3da192 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts | |||
@@ -56,6 +56,7 @@ export { default as ProfileSettings } from './stores/ProfileSettings'; | |||
56 | export { | 56 | export { |
57 | default as ServiceBase, | 57 | default as ServiceBase, |
58 | defineServiceModel, | 58 | defineServiceModel, |
59 | SecurityLabelKind, | ||
59 | } from './stores/ServiceBase'; | 60 | } from './stores/ServiceBase'; |
60 | 61 | ||
61 | export type { | 62 | export type { |
diff --git a/packages/shared/src/stores/ServiceBase.ts b/packages/shared/src/stores/ServiceBase.ts index a19f59e..0e4be97 100644 --- a/packages/shared/src/stores/ServiceBase.ts +++ b/packages/shared/src/stores/ServiceBase.ts | |||
@@ -25,6 +25,14 @@ import type Profile from './Profile'; | |||
25 | import ServiceSettingsBase from './ServiceSettingsBase'; | 25 | import ServiceSettingsBase from './ServiceSettingsBase'; |
26 | import ServiceState from './ServiceState'; | 26 | import ServiceState from './ServiceState'; |
27 | 27 | ||
28 | export enum SecurityLabelKind { | ||
29 | Empty = 'empty', | ||
30 | SecureConnection = 'secureConnection', | ||
31 | NotSecureConnection = 'notSecureConnection', | ||
32 | CertificateError = 'certificateError', | ||
33 | InvalidURL = 'invalidURL', | ||
34 | } | ||
35 | |||
28 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | 36 | export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { |
29 | return types | 37 | return types |
30 | .model('Service', { | 38 | .model('Service', { |
@@ -48,6 +56,38 @@ export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | |||
48 | get crashed(): boolean { | 56 | get crashed(): boolean { |
49 | return self.state.type === 'crashed'; | 57 | return self.state.type === 'crashed'; |
50 | }, | 58 | }, |
59 | isCertificateTemporarilyTrusted( | ||
60 | certificate: CertificateSnapshotIn, | ||
61 | ): boolean { | ||
62 | return ( | ||
63 | self.settings.profile as Profile | ||
64 | ).isCertificateTemporarilyTrusted(certificate); | ||
65 | }, | ||
66 | get securityLabel(): SecurityLabelKind { | ||
67 | const { | ||
68 | state: { type: stateType }, | ||
69 | currentUrl, | ||
70 | } = self; | ||
71 | if (stateType === 'certificateError') { | ||
72 | return SecurityLabelKind.CertificateError; | ||
73 | } | ||
74 | if (currentUrl === undefined || currentUrl === '') { | ||
75 | return SecurityLabelKind.Empty; | ||
76 | } | ||
77 | try { | ||
78 | const parsedUrl = new URL(currentUrl); | ||
79 | switch (parsedUrl.protocol) { | ||
80 | case 'https:': | ||
81 | return SecurityLabelKind.SecureConnection; | ||
82 | case 'http:': | ||
83 | return SecurityLabelKind.NotSecureConnection; | ||
84 | default: | ||
85 | return SecurityLabelKind.InvalidURL; | ||
86 | } | ||
87 | } catch { | ||
88 | return SecurityLabelKind.InvalidURL; | ||
89 | } | ||
90 | }, | ||
51 | })) | 91 | })) |
52 | .views((self) => ({ | 92 | .views((self) => ({ |
53 | get hasError(): boolean { | 93 | get hasError(): boolean { |
@@ -57,12 +97,17 @@ export function defineServiceModel<TS extends IAnyModelType>(settings: TS) { | |||
57 | self.state.type === 'certificateError' | 97 | self.state.type === 'certificateError' |
58 | ); | 98 | ); |
59 | }, | 99 | }, |
60 | isCertificateTemporarilyTrusted( | 100 | get hasSecurityLabelWarning(): boolean { |
61 | certificate: CertificateSnapshotIn, | 101 | const { securityLabel } = self; |
62 | ): boolean { | ||
63 | return ( | 102 | return ( |
64 | self.settings.profile as Profile | 103 | securityLabel !== SecurityLabelKind.Empty && |
65 | ).isCertificateTemporarilyTrusted(certificate); | 104 | securityLabel !== SecurityLabelKind.SecureConnection |
105 | ); | ||
106 | }, | ||
107 | })) | ||
108 | .views((self) => ({ | ||
109 | get alwaysShowLocationBar(): boolean { | ||
110 | return self.hasError || self.hasSecurityLabelWarning; | ||
66 | }, | 111 | }, |
67 | })); | 112 | })); |
68 | } | 113 | } |
diff --git a/packages/shared/src/stores/SharedStoreBase.ts b/packages/shared/src/stores/SharedStoreBase.ts index bd71cea..e4b3a38 100644 --- a/packages/shared/src/stores/SharedStoreBase.ts +++ b/packages/shared/src/stores/SharedStoreBase.ts | |||
@@ -39,16 +39,35 @@ export function defineSharedStoreModel< | |||
39 | TP extends IAnyModelType, | 39 | TP extends IAnyModelType, |
40 | TS extends IAnyModelType, | 40 | TS extends IAnyModelType, |
41 | >(globalSettings: TG, profile: TP, service: TS) { | 41 | >(globalSettings: TG, profile: TP, service: TS) { |
42 | return types.model('SharedStore', { | 42 | return types |
43 | settings: types.optional(globalSettings, {}), | 43 | .model('SharedStore', { |
44 | profilesById: types.map(profile), | 44 | settings: types.optional(globalSettings, {}), |
45 | profiles: types.array(types.reference(profile)), | 45 | profilesById: types.map(profile), |
46 | servicesById: types.map(service), | 46 | profiles: types.array(types.reference(profile)), |
47 | services: types.array(types.reference(service)), | 47 | servicesById: types.map(service), |
48 | shouldUseDarkColors: false, | 48 | services: types.array(types.reference(service)), |
49 | language: FALLBACK_LOCALE, | 49 | shouldUseDarkColors: false, |
50 | writingDirection: types.optional(WritingDirection, 'ltr'), | 50 | language: FALLBACK_LOCALE, |
51 | }); | 51 | writingDirection: types.optional(WritingDirection, 'ltr'), |
52 | }) | ||
53 | .views((self) => ({ | ||
54 | get alwaysShowLocationBar(): boolean { | ||
55 | const settings = self.settings as GlobalSettingsBase; | ||
56 | const selectedService = settings.selectedService as | ||
57 | | ServiceBase | ||
58 | | undefined; | ||
59 | return selectedService?.alwaysShowLocationBar ?? false; | ||
60 | }, | ||
61 | })) | ||
62 | .views((self) => ({ | ||
63 | get locationBarVisible(): boolean { | ||
64 | const settings = self.settings as GlobalSettingsBase; | ||
65 | return settings.showLocationBar || self.alwaysShowLocationBar; | ||
66 | }, | ||
67 | get canToggleLocationBar(): boolean { | ||
68 | return !self.alwaysShowLocationBar; | ||
69 | }, | ||
70 | })); | ||
52 | } | 71 | } |
53 | 72 | ||
54 | const SharedStoreBase = /* @__PURE__ */ (() => | 73 | const SharedStoreBase = /* @__PURE__ */ (() => |