From a6970986d1e8dcbec39fd7b23decee642a434e9c Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Wed, 14 Feb 2024 23:25:11 -0800 Subject: [PATCH] adding localization for identity component --- net/web/src/constants/Colors.js | 2 +- net/web/src/constants/Strings.js | 26 +++++++++ .../src/context/useSettingsContext.hook.js | 55 +++++++++++++++---- net/web/src/index.css | 8 +++ net/web/src/session/Session.jsx | 2 +- net/web/src/session/identity/Identity.jsx | 40 +++++++------- .../src/session/identity/Identity.styled.js | 52 +++--------------- .../src/session/identity/useIdentity.hook.js | 10 ++++ 8 files changed, 119 insertions(+), 76 deletions(-) create mode 100644 net/web/src/constants/Strings.js diff --git a/net/web/src/constants/Colors.js b/net/web/src/constants/Colors.js index c01af4ba..89c390e6 100644 --- a/net/web/src/constants/Colors.js +++ b/net/web/src/constants/Colors.js @@ -62,7 +62,7 @@ export const DarkTheme = { headerArea: '#111111', footerArea: '#111111', itemArea: '#222222', - hoverArea: '#444444', + hoverArea: '#2f2f2f', selectedArea: '#333333', enabledArea: '#448866', disabledArea: '#888888', diff --git a/net/web/src/constants/Strings.js b/net/web/src/constants/Strings.js new file mode 100644 index 00000000..b5b72010 --- /dev/null +++ b/net/web/src/constants/Strings.js @@ -0,0 +1,26 @@ +export const en = { + code: 'en', + account: 'Account', + contacts: 'Contacts', + logout: 'Logout', + confirmLogout: 'Are you sure you want to logout?', + contactsUpdated: 'Updated contact status', + disconnected: 'Disconnected from server', + allDevices: 'Logout of all devices', + ok: 'OK', + cancel: 'Cancel', +}; + +export const fr = { + code: 'fr', + account: 'Compte', + contacts: 'Contacts', + logout: 'Déconnexion', + confirmLogout: 'Êtes-vous sûr de vouloir vous déconnecter?', + contactsUpdated: 'Vos contacts ont changer', + disconnected: 'Déconnecté du serveur', + allDevices: 'Déconnexion de tous les appareils', + ok: 'OK', + cancel: 'Annuler', +}; + diff --git a/net/web/src/context/useSettingsContext.hook.js b/net/web/src/context/useSettingsContext.hook.js index 21df784e..f59623f7 100644 --- a/net/web/src/context/useSettingsContext.hook.js +++ b/net/web/src/context/useSettingsContext.hook.js @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react'; import { LightTheme, DarkTheme } from 'constants/Colors'; +import { en, fr } from 'constants/Strings'; export function useSettingsContext() { @@ -7,8 +8,11 @@ export function useSettingsContext() { display: null, width: null, height: null, - darkTheme: DarkTheme, - lightTheme: LightTheme, + theme: null, + colors: {}, + menuStyle: {}, + language: 'en', + strings: en, }); const SMALL_MEDIUM = 650; @@ -44,13 +48,26 @@ export function useSettingsContext() { const scheme = localStorage.getItem('color_scheme'); if (scheme === 'dark') { - updateState({ darkTheme: DarkTheme, lightTheme: DarkTheme }); + updateState({ theme: scheme, colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.headerArea, color: DarkTheme.mainText } }); } else if (scheme === 'light') { - updateState({ darkTheme: LightTheme, lightTheme: LightTheme }); + updateState({ theme: scheme, colors: LightTheme, menuStyle: { backgroundColor: LightTheme.headerArea, color: LightTheme.mainText } }) } else { - updateState({ darkTheme: DarkTheme, lightTheme: LightTheme }); + if(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + updateState({ theme: null, colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.headerArea, color: DarkTheme.mainText } }); + } + else { + updateState({ theme: null, colors: LightTheme, menuStyle: { backgroundColor: LightTheme.headerArea, color: LightTheme.mainText } }); + } + } + + const language = localStorage.getItem('language'); + if (language && language.startsWith('fr')) { + updateState({ language: 'fr', strings: fr }); + } + else { + updateState({ language: 'en', strings: en }); } return () => { @@ -61,18 +78,32 @@ export function useSettingsContext() { }, []); const actions = { - setDarkTheme() { + setDarkTheme: () => { localStorage.setItem('color_scheme', 'dark'); - updateState({ darkTheme: DarkTheme, lightTheme: DarkTheme }); + updateState({ theme: 'dark', colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.headerArea, color: DarkTheme.mainText } }); }, - setLightTheme() { + setLightTheme : () => { localStorage.setItem('color_scheme', 'light'); - updateState({ darkTheme: LightTheme, lightTheme: LightTheme }); + updateState({ theme: 'light', colors: LightTheme, menuStyle: { backgroundColor: LightTheme.headerArea, color: LightTheme.mainText } }); }, - steDefaultTheme() { + setDefaultTheme: () => { localStorage.clearItem('color_scheme'); - updateState({ darkTheme: DarkTheme, lightTheme: LightTheme }); - } + if(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + updateState({ theme: null, colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.headerArea, color: DarkTheme.mainText } }); + } + else { + updateState({ theme: null, colors: LightTheme, menuStyle: { backgroundColor: LightTheme.headerArea, color: LightTheme.mainText } }); + } + }, + setLanguage: (code: string) => { + localStorage.setItem('language', code); + if (code && code.startsWith('fr')) { + updateState({ language: 'fr', strings: fr }); + } + else { + updateState({ language: 'en', strings: en }); + } + }, } return { state, actions } diff --git a/net/web/src/index.css b/net/web/src/index.css index 7b437532..14c3ba3a 100644 --- a/net/web/src/index.css +++ b/net/web/src/index.css @@ -14,6 +14,14 @@ padding-bottom: 16px !important; } +.ant-switch { + background: #888888 !important; +} + +.ant-switch-checked { + background: #448866 !important; +} + body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', diff --git a/net/web/src/session/Session.jsx b/net/web/src/session/Session.jsx index 4a2b80e1..f14e6a7e 100644 --- a/net/web/src/session/Session.jsx +++ b/net/web/src/session/Session.jsx @@ -159,7 +159,7 @@ export function Session() { } return ( - + { (state.display === 'xlarge') && (
diff --git a/net/web/src/session/identity/Identity.jsx b/net/web/src/session/identity/Identity.jsx index a41a00d8..16095378 100644 --- a/net/web/src/session/identity/Identity.jsx +++ b/net/web/src/session/identity/Identity.jsx @@ -13,30 +13,32 @@ export function Identity({ openAccount, openCards, cardUpdated }) { const logout = () => { modal.confirm({ - title: 'Are you sure you want to logout?', + title: {state.strings.confirmLogout}, icon: , content: e.stopPropagation()}> - Logout of All Devices - {all.current = e}} size="small" /> + { state.strings.allDevices } + all.current = e} size="small" /> , - bodyStyle: { padding: 16 }, + bodyStyle: { padding: 16, ...state.menuStyle }, + okText: state.strings.ok, onOk() { actions.logout(all.current); }, + cancelText: state.strings.cancel, onCancel() {}, }); } const menu = ( - - -
Account
+ + +
{ state.strings.account }
- -
Contacts
+ +
{ state.strings.contacts }
- -
Logout
+ +
{ state.strings.logout }
); @@ -48,12 +50,12 @@ export function Identity({ openAccount, openCards, cardUpdated }) { { state.init && ( )} -
-
{state.name}
-
-
+
+
{state.name}
+
+
{ state.status !== 'connected' && ( - + @@ -61,9 +63,9 @@ export function Identity({ openAccount, openCards, cardUpdated }) { )}
{state.handle}
-
+
{ cardUpdated && ( - + @@ -72,7 +74,7 @@ export function Identity({ openAccount, openCards, cardUpdated }) {
-
+
diff --git a/net/web/src/session/identity/Identity.styled.js b/net/web/src/session/identity/Identity.styled.js index 59c0c4c4..3326536e 100644 --- a/net/web/src/session/identity/Identity.styled.js +++ b/net/web/src/session/identity/Identity.styled.js @@ -1,5 +1,4 @@ import styled from 'styled-components'; -import { Colors } from 'constants/Colors'; export const IdentityWrapper = styled.div` width: 100%; @@ -9,26 +8,14 @@ export const IdentityWrapper = styled.div` align-items: center; padding-left: 16px; padding-right: 16px; - @media (prefers-color-scheme: light) { - background-color: ${props => props.theme.light.headerArea}; - border-bottom: 1px solid ${props => props.theme.light.sectionLine}; - color: ${props => props.theme.light.mainText}; - } - @media (prefers-color-scheme: dark) { - background-color: ${props => props.theme.dark.headerArea}; - border-bottom: 1px solid ${props => props.theme.dark.sectionLine}; - color: ${props => props.theme.dark.mainText}; - } + background-color: ${props => props.theme.headerArea}; + border-bottom: 1px solid ${props => props.theme.sectionLine}; + color: ${props => props.theme.mainText}; flex-shrink: 0; &:hover { cursor: pointer; - @media (prefers-color-scheme: light) { - background-color: ${props => props.theme.light.hoverArea}; - } - @media (prefers-color-scheme: dark) { - background-color: ${props => props.theme.dark.hoverArea}; - } + background-color: ${props => props.theme.hoverArea}; .drop { font-weight: bold; @@ -39,14 +26,8 @@ export const IdentityWrapper = styled.div` padding-left: 4px; padding-right: 4px; border-radius: 8px; - @media (prefers-color-scheme: light) { - border: 1px solid ${props => props.theme.light.sectionLine}; - color: ${props => props.theme.light.mainText}; - } - @media (prefers-color-scheme: dark) { - border: 1px solid ${props => props.theme.dark.sectionLine}; - color: ${props => props.theme.dark.mainText}; - } + border: 1px solid ${props => props.theme.sectionLine}; + color: ${props => props.theme.mainText}; } .label { @@ -88,30 +69,15 @@ export const LogoutContent = styled.div` .logoutMode { padding-right: 8px; - @media (prefers-color-scheme: light) { - color: ${props => props.theme.light.mainText}; - } - @media (prefers-color-scheme: dark) { - color: ${props => props.theme.dark.mainText}; - } + color: ${props => props.theme.mainText}; } ` export const ErrorNotice = styled.div` - @media (prefers-color-scheme: light) { - color: ${props => props.theme.light.alertText}; - } - @media (prefers-color-scheme: dark) { - color: ${props => props.theme.dark.alertText}; - } + color: ${props => props.theme.alertText}; ` export const InfoNotice = styled.div` - @media (prefers-color-scheme: light) { - color: ${props => props.theme.light.linkText}; - } - @media (prefers-color-scheme: dark) { - color: ${props => props.theme.dark.linkText}; - } + color: ${props => props.theme.linkText}; ` diff --git a/net/web/src/session/identity/useIdentity.hook.js b/net/web/src/session/identity/useIdentity.hook.js index 911e4c95..44a17056 100644 --- a/net/web/src/session/identity/useIdentity.hook.js +++ b/net/web/src/session/identity/useIdentity.hook.js @@ -1,6 +1,7 @@ import { useState, useEffect, useContext } from 'react'; import { ProfileContext } from 'context/ProfileContext'; import { AppContext } from 'context/AppContext'; +import { SettingsContext } from 'context/SettingsContext'; export function useIdentity() { @@ -10,10 +11,14 @@ export function useIdentity() { handle: null, status: null, init: false, + strings: {}, + colors: {}, + menuStyle: {}, }); const app = useContext(AppContext); const profile = useContext(ProfileContext); + const settings = useContext(SettingsContext); const updateState = (value) => { setState((s) => ({ ...s, ...value })); @@ -32,6 +37,11 @@ export function useIdentity() { updateState({ status }); }, [app.state]); + useEffect(() => { + const { colors, strings, menuStyle } = settings.state; + updateState({ colors, strings, menuStyle }); + }, [settings.state]); + const actions = { logout: (all) => { app.actions.logout(all);