aboutsummaryrefslogtreecommitdiffstats
path: root/packages/renderer/src/components/locationBar/LocationTextField.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/renderer/src/components/locationBar/LocationTextField.tsx')
-rw-r--r--packages/renderer/src/components/locationBar/LocationTextField.tsx130
1 files changed, 130 insertions, 0 deletions
diff --git a/packages/renderer/src/components/locationBar/LocationTextField.tsx b/packages/renderer/src/components/locationBar/LocationTextField.tsx
new file mode 100644
index 0000000..9b028b3
--- /dev/null
+++ b/packages/renderer/src/components/locationBar/LocationTextField.tsx
@@ -0,0 +1,130 @@
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 FilledInput from '@mui/material/FilledInput';
22import { styled } from '@mui/material/styles';
23import { autorun } from 'mobx';
24import { observer } from 'mobx-react-lite';
25import React, { useCallback, useEffect, useState } from 'react';
26
27import Service from '../../stores/Service.js';
28
29import GoButton from './GoButton.js';
30import LocationOverlayInput from './LocationOverlayInput.js';
31import SecurityLabel from './SecurityLabel.js';
32import UrlOverlay from './UrlOverlay.js';
33
34const LocationTextFieldRoot = styled(FilledInput, {
35 name: 'LocationTextField',
36 slot: 'Root',
37})(({ theme }) => ({
38 padding: '0 12px',
39 flex: '1 0 200px',
40 borderRadius: 18,
41 '&.Mui-focused': {
42 outline: `2px solid ${theme.palette.primary.main}`,
43 },
44}));
45
46function LocationTextField({ service }: { service: Service }): JSX.Element {
47 const [inputFocused, setInputFocused] = useState(false);
48 const [changed, setChanged] = useState(false);
49 const [value, setValue] = useState('');
50
51 const resetValue = useCallback(() => {
52 setValue(service.currentUrl ?? '');
53 setChanged(false);
54 }, [service]);
55
56 useEffect(
57 () =>
58 autorun(() => {
59 resetValue();
60 }),
61 [resetValue],
62 );
63
64 const inputRefCallback = useCallback(
65 (input: HTMLInputElement) => {
66 setInputFocused(
67 document.activeElement !== null && document.activeElement === input,
68 );
69 },
70 [setInputFocused],
71 );
72
73 return (
74 <LocationTextFieldRoot
75 inputComponent={LocationOverlayInput}
76 inputProps={{
77 'aria-label': 'Location',
78 spellCheck: false,
79 overlayVisible: !inputFocused && !changed,
80 overlay: (
81 <UrlOverlay
82 url={service.currentUrl ?? ''}
83 alert={service.hasSecurityLabelWarning ?? false}
84 />
85 ),
86 }}
87 inputRef={inputRefCallback}
88 onFocus={() => setInputFocused(true)}
89 onBlur={() => setInputFocused(false)}
90 onChange={({ target: { value: newValue } }) => {
91 setValue(newValue);
92 setChanged(true);
93 }}
94 onKeyDown={(event) => {
95 switch (event.key) {
96 case 'Escape':
97 resetValue();
98 break;
99 case 'Enter':
100 service.go(value);
101 break;
102 default:
103 // Nothing to do, let the key event through.
104 return;
105 }
106 event.preventDefault();
107 event.stopPropagation();
108 }}
109 size="small"
110 fullWidth
111 hiddenLabel
112 disableUnderline
113 startAdornment={
114 <SecurityLabel
115 kind={service.securityLabel}
116 changed={changed}
117 position="start"
118 />
119 }
120 endAdornment={
121 changed ? (
122 <GoButton onClick={() => service.go(value)} position="end" />
123 ) : undefined
124 }
125 value={value}
126 />
127 );
128}
129
130export default observer(LocationTextField);