diff options
| author | Ben Woodward <ben@bdw.to> | 2026-01-24 20:46:24 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-24 20:46:24 -0800 |
| commit | e1927f633cab988ceeb8bcd51dd03aaa5b3f2392 (patch) | |
| tree | a776d7287d2c9583151f2567d9cf4f22d010aeed /src/components | |
| parent | fbde2cd27669ac29e1c0bc9393f9a83ffa93f8c6 (diff) | |
Updates jan 2026 (#313)
* Update dependencies to latest versions and migrate to React 19
- Update all dependencies to latest versions
- Migrate to React 19 createRoot API (replaces deprecated ReactDOM.render)
- Update qrcode.react import to v4 named export (QRCodeSVG)
* Format CSS with prettier
* Add Hebrew translation
* Add Slovak translation
* Add Malagasy translation
* Add Bangla translation
* Init field
* Change the logic concerning number of cards to print
* fix/clean
* Fix Increment-field-ID-in-the-print-area
* Increment-field-ID-in-the-print-area
* Review id implementation logic
* Fix git commit
* Handle Query parameter
* Fix package.json
* Fix query parameter for language
* fix query parameter for language
* Fix EncryptionModeChange query parameters // Error when non in query
* Fix EncryptionModeChange query parameters // Error when empty in query
* clean Setting.js don't need to import i18n
* clean file App.js
* first iteration for Hash
* Add Esperanto translation
* Update translations for Occitan
2 lines added
* Update translations.js
Added Swiss German to the Translations JavaScript-File
* Update translations.js
Removed custom Translations-Strings of my own Version.
* Update README.md
* Format translations.js with prettier
---------
Co-authored-by: Ido Bronfeld <idobronfeld@gmail.com>
Co-authored-by: Matej Kubinec <matej.kubinec@outlook.com>
Co-authored-by: mpilasy <88362233+mpilasy@users.noreply.github.com>
Co-authored-by: Tarek Hasan <94107336+Tarek-Hasan@users.noreply.github.com>
Co-authored-by: ofostier <ofostier@gmail.com>
Co-authored-by: zeecho <30541894+zeecho@users.noreply.github.com>
Co-authored-by: Mejans <61360811+Mejans@users.noreply.github.com>
Co-authored-by: Jan Zehnder <44242812+NZehnder@users.noreply.github.com>
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/Settings.js | 1 | ||||
| -rw-r--r-- | src/components/WifiCard.js | 13 | ||||
| -rw-r--r-- | src/components/style.css | 7 | ||||
| -rw-r--r-- | src/components/useHashParam.js | 48 |
4 files changed, 64 insertions, 5 deletions
diff --git a/src/components/Settings.js b/src/components/Settings.js index 837b4f0..0485aaf 100644 --- a/src/components/Settings.js +++ b/src/components/Settings.js | |||
| @@ -20,6 +20,7 @@ export const Settings = (props) => { | |||
| 20 | { label: 'WEP', value: 'WEP' }, | 20 | { label: 'WEP', value: 'WEP' }, |
| 21 | ]; | 21 | ]; |
| 22 | const eapMethods = [{ label: 'PWD', value: 'PWD' }]; | 22 | const eapMethods = [{ label: 'PWD', value: 'PWD' }]; |
| 23 | |||
| 23 | const langSelectDefaultValue = () => { | 24 | const langSelectDefaultValue = () => { |
| 24 | const t = Translations.filter((t) => t.id === i18n.language); | 25 | const t = Translations.filter((t) => t.id === i18n.language); |
| 25 | if (t.length !== 1) { | 26 | if (t.length !== 1) { |
diff --git a/src/components/WifiCard.js b/src/components/WifiCard.js index 70e1189..e977ac8 100644 --- a/src/components/WifiCard.js +++ b/src/components/WifiCard.js | |||
| @@ -8,7 +8,7 @@ import { | |||
| 8 | Text, | 8 | Text, |
| 9 | TextareaField, | 9 | TextareaField, |
| 10 | } from 'evergreen-ui'; | 10 | } from 'evergreen-ui'; |
| 11 | import QRCode from 'qrcode.react'; | 11 | import { QRCodeSVG as QRCode } from 'qrcode.react'; |
| 12 | import { useEffect, useState } from 'react'; | 12 | import { useEffect, useState } from 'react'; |
| 13 | import { useTranslation } from 'react-i18next'; | 13 | import { useTranslation } from 'react-i18next'; |
| 14 | import logo from '../../src/images/wifi.png'; | 14 | import logo from '../../src/images/wifi.png'; |
| @@ -71,6 +71,9 @@ export const WifiCard = (props) => { | |||
| 71 | return !eapIdentityFieldLabel() ? '' : t('wifi.encryption.eapMethod'); | 71 | return !eapIdentityFieldLabel() ? '' : t('wifi.encryption.eapMethod'); |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | const keyid = props.keyid || ''; | ||
| 75 | const suffixKeyID = (prefix) => `${prefix}-${keyid}`; | ||
| 76 | |||
| 74 | return ( | 77 | return ( |
| 75 | <Card | 78 | <Card |
| 76 | className="card-print" | 79 | className="card-print" |
| @@ -102,7 +105,7 @@ export const WifiCard = (props) => { | |||
| 102 | 105 | ||
| 103 | <Pane width={'100%'}> | 106 | <Pane width={'100%'}> |
| 104 | <TextareaField | 107 | <TextareaField |
| 105 | id="ssid" | 108 | id={suffixKeyID('ssid')} |
| 106 | type="text" | 109 | type="text" |
| 107 | marginBottom={5} | 110 | marginBottom={5} |
| 108 | autoComplete="off" | 111 | autoComplete="off" |
| @@ -120,7 +123,7 @@ export const WifiCard = (props) => { | |||
| 120 | {props.settings.encryptionMode === 'WPA2-EAP' && ( | 123 | {props.settings.encryptionMode === 'WPA2-EAP' && ( |
| 121 | <> | 124 | <> |
| 122 | <TextareaField | 125 | <TextareaField |
| 123 | id="eapmethod" | 126 | id={suffixKeyID('eapmethod')} |
| 124 | type="text" | 127 | type="text" |
| 125 | marginBottom={5} | 128 | marginBottom={5} |
| 126 | readOnly={true} | 129 | readOnly={true} |
| @@ -130,7 +133,7 @@ export const WifiCard = (props) => { | |||
| 130 | /> | 133 | /> |
| 131 | 134 | ||
| 132 | <TextareaField | 135 | <TextareaField |
| 133 | id="identity" | 136 | id={suffixKeyID('identity')} |
| 134 | type="text" | 137 | type="text" |
| 135 | marginBottom={5} | 138 | marginBottom={5} |
| 136 | autoComplete="off" | 139 | autoComplete="off" |
| @@ -150,7 +153,7 @@ export const WifiCard = (props) => { | |||
| 150 | )} | 153 | )} |
| 151 | {!(props.settings.hidePassword || !props.settings.encryptionMode) && ( | 154 | {!(props.settings.hidePassword || !props.settings.encryptionMode) && ( |
| 152 | <TextareaField | 155 | <TextareaField |
| 153 | id="password" | 156 | id={suffixKeyID('password')} |
| 154 | type="text" | 157 | type="text" |
| 155 | maxLength="63" | 158 | maxLength="63" |
| 156 | autoComplete="off" | 159 | autoComplete="off" |
diff --git a/src/components/style.css b/src/components/style.css index 10eac9b..87ba63a 100644 --- a/src/components/style.css +++ b/src/components/style.css | |||
| @@ -67,6 +67,13 @@ button { | |||
| 67 | #print-area, | 67 | #print-area, |
| 68 | #print-area * { | 68 | #print-area * { |
| 69 | visibility: visible; | 69 | visibility: visible; |
| 70 | /* For printing, use a font stack that prioritizes system fonts | ||
| 71 | to ensure CJK characters are rendered correctly in Chrome. */ | ||
| 72 | font-family: | ||
| 73 | 'PingFang SC', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans JP', | ||
| 74 | 'Noto Sans KR', 'Microsoft YaHei', serif; | ||
| 75 | font-weight: 500; | ||
| 76 | font-style: semibold; | ||
| 70 | } | 77 | } |
| 71 | #print-area { | 78 | #print-area { |
| 72 | position: absolute; | 79 | position: absolute; |
diff --git a/src/components/useHashParam.js b/src/components/useHashParam.js new file mode 100644 index 0000000..e43e1e4 --- /dev/null +++ b/src/components/useHashParam.js | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | import { useState, useEffect, useCallback } from 'react'; | ||
| 2 | |||
| 3 | const getHashSearchParams = (location) => { | ||
| 4 | const hash = location.hash.slice(1); | ||
| 5 | const [prefix, query] = hash.split('?'); | ||
| 6 | |||
| 7 | return [prefix, new URLSearchParams(query)]; | ||
| 8 | }; | ||
| 9 | |||
| 10 | const getHashParam = (key, location = window.location) => { | ||
| 11 | const [_, searchParams] = getHashSearchParams(location); | ||
| 12 | return searchParams.get(key); | ||
| 13 | }; | ||
| 14 | |||
| 15 | const setHashParam = (key, value, location = window.location) => { | ||
| 16 | const [prefix, searchParams] = getHashSearchParams(location); | ||
| 17 | |||
| 18 | if (typeof value === 'undefined') { | ||
| 19 | searchParams.delete(key); | ||
| 20 | } else { | ||
| 21 | searchParams.set(key, value); | ||
| 22 | } | ||
| 23 | |||
| 24 | const search = searchParams.toString(); | ||
| 25 | location.hash = search ? `${prefix}?${search}` : prefix; | ||
| 26 | }; | ||
| 27 | |||
| 28 | const useHashParam = (key) => { | ||
| 29 | const [innerValue, setInnerValue] = useState(); | ||
| 30 | |||
| 31 | useEffect(() => { | ||
| 32 | const handleHashChange = () => setInnerValue(getHashParam(key)); | ||
| 33 | handleHashChange(); | ||
| 34 | window.addEventListener('hashchange', handleHashChange); | ||
| 35 | return () => window.removeEventListener('hashchange', handleHashChange); | ||
| 36 | }, [key]); | ||
| 37 | |||
| 38 | const setValue = useCallback( | ||
| 39 | (value) => { | ||
| 40 | setHashParam(key, value); | ||
| 41 | }, | ||
| 42 | [key] | ||
| 43 | ); | ||
| 44 | |||
| 45 | return [innerValue, setValue]; | ||
| 46 | }; | ||
| 47 | |||
| 48 | export default useHashParam; | ||
