aboutsummaryrefslogtreecommitdiffstats
path: root/packages/renderer/src/components/locationBar/UrlOverlay.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/renderer/src/components/locationBar/UrlOverlay.tsx')
-rw-r--r--packages/renderer/src/components/locationBar/UrlOverlay.tsx114
1 files changed, 114 insertions, 0 deletions
diff --git a/packages/renderer/src/components/locationBar/UrlOverlay.tsx b/packages/renderer/src/components/locationBar/UrlOverlay.tsx
new file mode 100644
index 0000000..eaa86d2
--- /dev/null
+++ b/packages/renderer/src/components/locationBar/UrlOverlay.tsx
@@ -0,0 +1,114 @@
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
21import { styled } from '@mui/material/styles';
22import React from 'react';
23
24import getAlertColor from './getAlertColor.js';
25
26export type SplitResult =
27 | {
28 type: 'hostOnly';
29 prefix: string;
30 host: string;
31 suffix: string;
32 }
33 | {
34 type: 'wholeString';
35 value: string;
36 }
37 | {
38 type: 'empty';
39 };
40
41function splitUrl(urlString: string | undefined): SplitResult {
42 if (urlString === undefined || urlString === '') {
43 return { type: 'empty' };
44 }
45 let url: URL;
46 try {
47 url = new URL(urlString);
48 } catch {
49 return { type: 'wholeString', value: urlString };
50 }
51 const { protocol, host, username, password, pathname, search, hash } = url;
52 if (host !== '') {
53 return {
54 type: 'hostOnly',
55 prefix: `${protocol}//${
56 username === ''
57 ? ''
58 : `${username}${password === '' ? '' : `:${password}`}@`
59 }`,
60 host,
61 suffix: `${pathname}${search}${hash}`,
62 };
63 }
64 return { type: 'wholeString', value: urlString };
65}
66
67const PrimaryFragment = styled('span', {
68 name: 'LocationOverlayInput',
69 slot: 'PrimaryFragment',
70 shouldForwardProp: (prop) => prop !== 'alert',
71})<{ alert: boolean }>(({ theme, alert }) => ({
72 color: getAlertColor(theme, alert),
73}));
74
75const SecondaryFragment = styled('span', {
76 name: 'LocationOverlayInput',
77 slot: 'SecondaryFragment',
78})(({ theme }) => ({
79 color: theme.palette.text.secondary,
80}));
81
82export default function UrlOverlay({
83 url,
84 alert,
85}: {
86 url: string | undefined;
87 alert: boolean;
88}): JSX.Element {
89 const splitResult = splitUrl(url);
90 const { type } = splitResult;
91 switch (type) {
92 case 'hostOnly': {
93 const { prefix, host, suffix } = splitResult;
94 return (
95 <>
96 <SecondaryFragment>{prefix}</SecondaryFragment>
97 <PrimaryFragment alert={alert}>{host}</PrimaryFragment>
98 <SecondaryFragment>{suffix}</SecondaryFragment>
99 </>
100 );
101 }
102 case 'wholeString': {
103 const { value } = splitResult;
104 return <PrimaryFragment alert={alert}>{value}</PrimaryFragment>;
105 }
106 case 'empty':
107 return <PrimaryFragment alert={alert} />;
108 default:
109 /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions --
110 Error handling for impossible case.
111 */
112 throw new Error(`Unexpected SplitResult: ${type}`);
113 }
114}