diff options
Diffstat (limited to 'src/components/WifiCard.js')
| -rw-r--r-- | src/components/WifiCard.js | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/components/WifiCard.js b/src/components/WifiCard.js new file mode 100644 index 0000000..645dfa1 --- /dev/null +++ b/src/components/WifiCard.js | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | import { | ||
| 2 | CameraIcon, | ||
| 3 | Card, | ||
| 4 | Heading, | ||
| 5 | MobilePhoneIcon, | ||
| 6 | Pane, | ||
| 7 | Paragraph, | ||
| 8 | Text, | ||
| 9 | TextareaField, | ||
| 10 | } from 'evergreen-ui'; | ||
| 11 | import QRCode from 'qrcode.react'; | ||
| 12 | import { useEffect, useState } from 'react'; | ||
| 13 | import { useTranslation } from 'react-i18next'; | ||
| 14 | import logo from '../../src/images/wifi.png'; | ||
| 15 | import './style.css'; | ||
| 16 | |||
| 17 | export const WifiCard = (props) => { | ||
| 18 | const { t } = useTranslation(); | ||
| 19 | const [qrvalue, setQrvalue] = useState(''); | ||
| 20 | |||
| 21 | const escape = (v) => { | ||
| 22 | const needsEscape = ['"', ';', ',', ':', '\\']; | ||
| 23 | |||
| 24 | let escaped = ''; | ||
| 25 | for (const c of v) { | ||
| 26 | if (needsEscape.includes(c)) { | ||
| 27 | escaped += `\\${c}`; | ||
| 28 | } else { | ||
| 29 | escaped += c; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | return escaped; | ||
| 33 | }; | ||
| 34 | |||
| 35 | useEffect(() => { | ||
| 36 | const ssid = escape(props.settings.ssid); | ||
| 37 | const password = !props.settings.encryptionMode | ||
| 38 | ? '' | ||
| 39 | : escape(props.settings.password); | ||
| 40 | setQrvalue( | ||
| 41 | `WIFI:T:${props.settings.encryptionMode};S:${ssid};P:${password};;` | ||
| 42 | ); | ||
| 43 | }, [props.settings]); | ||
| 44 | |||
| 45 | const portraitWidth = () => { | ||
| 46 | const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); | ||
| 47 | return isMobile ? '100%' : '280px'; | ||
| 48 | }; | ||
| 49 | |||
| 50 | const passwordFieldLabel = () => { | ||
| 51 | const hiddenPassword = | ||
| 52 | props.settings.hidePassword || !props.settings.encryptionMode; | ||
| 53 | return hiddenPassword ? '' : t('wifi.password'); | ||
| 54 | }; | ||
| 55 | |||
| 56 | return ( | ||
| 57 | <Pane> | ||
| 58 | <Card | ||
| 59 | id="print-area" | ||
| 60 | elevation={3} | ||
| 61 | style={{ maxWidth: props.settings.portrait ? portraitWidth() : '100%' }} | ||
| 62 | > | ||
| 63 | <Pane display="flex" paddingBottom={12}> | ||
| 64 | <img alt="icon" src={logo} width="24" height="24" /> | ||
| 65 | <Heading | ||
| 66 | paddingLeft={10} | ||
| 67 | size={700} | ||
| 68 | textAlign={props.settings.portrait ? 'center' : 'unset'} | ||
| 69 | > | ||
| 70 | {t('wifi.login')} | ||
| 71 | </Heading> | ||
| 72 | </Pane> | ||
| 73 | |||
| 74 | <Pane | ||
| 75 | className="details" | ||
| 76 | style={{ flexDirection: props.settings.portrait ? 'column' : 'row' }} | ||
| 77 | > | ||
| 78 | <QRCode | ||
| 79 | className="qrcode" | ||
| 80 | style={ | ||
| 81 | !props.settings.portrait | ||
| 82 | ? props.direction === 'ltr' | ||
| 83 | ? { paddingRight: '1em' } | ||
| 84 | : { paddingLeft: '1em' } | ||
| 85 | : {} | ||
| 86 | } | ||
| 87 | value={qrvalue} | ||
| 88 | size={150} | ||
| 89 | /> | ||
| 90 | |||
| 91 | <Pane width={'100%'}> | ||
| 92 | <TextareaField | ||
| 93 | id="ssid" | ||
| 94 | type="text" | ||
| 95 | marginBottom={5} | ||
| 96 | autoComplete="off" | ||
| 97 | autoCorrect="off" | ||
| 98 | autoCapitalize="none" | ||
| 99 | spellCheck={false} | ||
| 100 | maxLength="32" | ||
| 101 | label={t('wifi.name')} | ||
| 102 | placeholder={t('wifi.name.placeholder')} | ||
| 103 | value={props.settings.ssid} | ||
| 104 | onChange={(e) => props.onSSIDChange(e.target.value)} | ||
| 105 | isInvalid={!!props.ssidError} | ||
| 106 | validationMessage={!!props.ssidError && props.ssidError} | ||
| 107 | /> | ||
| 108 | <TextareaField | ||
| 109 | id="password" | ||
| 110 | type="text" | ||
| 111 | maxLength="63" | ||
| 112 | autoComplete="off" | ||
| 113 | autoCorrect="off" | ||
| 114 | autoCapitalize="none" | ||
| 115 | spellCheck={false} | ||
| 116 | className={` | ||
| 117 | ${ | ||
| 118 | (props.settings.hidePassword || | ||
| 119 | !props.settings.encryptionMode) && | ||
| 120 | 'hidden' | ||
| 121 | } | ||
| 122 | `} | ||
| 123 | height={ | ||
| 124 | props.settings.portrait && props.settings.password.length > 40 | ||
| 125 | ? '5em' | ||
| 126 | : 'auto' | ||
| 127 | } | ||
| 128 | label={passwordFieldLabel()} | ||
| 129 | placeholder={t('wifi.password.placeholder')} | ||
| 130 | value={props.settings.password} | ||
| 131 | onChange={(e) => props.onPasswordChange(e.target.value)} | ||
| 132 | isInvalid={!!props.passwordError} | ||
| 133 | validationMessage={!!props.passwordError && props.passwordError} | ||
| 134 | /> | ||
| 135 | </Pane> | ||
| 136 | </Pane> | ||
| 137 | <hr /> | ||
| 138 | <Paragraph> | ||
| 139 | <CameraIcon /> | ||
| 140 | <MobilePhoneIcon /> | ||
| 141 | <Text size={300} paddingLeft={8}> | ||
| 142 | {t('wifi.tip')} | ||
| 143 | </Text> | ||
| 144 | </Paragraph> | ||
| 145 | </Card> | ||
| 146 | </Pane> | ||
| 147 | ); | ||
| 148 | }; | ||
