mirror of
https://github.com/balzack/databag.git
synced 2025-05-04 23:45:21 +00:00
preparing access page
This commit is contained in:
parent
bb83b87cb3
commit
8471e997c1
77
app/client/web/src/constants/Colors.ts
Normal file
77
app/client/web/src/constants/Colors.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
export const LightTheme = {
|
||||||
|
remoteArea: '#080808',
|
||||||
|
localArea: '#888888',
|
||||||
|
splashArea: '#8fbea7',
|
||||||
|
baseArea: '#8fbea7',
|
||||||
|
frameArea: '#e4e4e4',
|
||||||
|
iconArea: '#ffffff',
|
||||||
|
headerArea: '#f0f0f0',
|
||||||
|
footerArea: '#f0f0f0',
|
||||||
|
modalArea: '#eeeeee',
|
||||||
|
itemArea: '#f4f4f4',
|
||||||
|
inputArea: '#ffffff',
|
||||||
|
hoverArea: '#cccccc',
|
||||||
|
noticeArea: '#8fbea7',
|
||||||
|
selectedArea: '#e8e8e8',
|
||||||
|
enabledArea: '#448866',
|
||||||
|
disabledArea: '#cccccc',
|
||||||
|
mainText: '#444444',
|
||||||
|
descriptionText: '#585858',
|
||||||
|
hintText: '#777777',
|
||||||
|
activeText: '#ffffff',
|
||||||
|
idleText: '#aaaaaa',
|
||||||
|
placeholderText: '#777777',
|
||||||
|
linkText: '#448866',
|
||||||
|
labelText: '#888888',
|
||||||
|
alertText: '#ff8888',
|
||||||
|
itemBorder: '#eeeeee',
|
||||||
|
inputBorder: '#888888',
|
||||||
|
sectionBorder: '#bbbbbb',
|
||||||
|
headerBorder: '#aaaaaa',
|
||||||
|
drawerBorder: '#cccccc',
|
||||||
|
unsaved: '#ffff00',
|
||||||
|
connected: '#44cc44',
|
||||||
|
connecting: '#dd88ff',
|
||||||
|
requested: '#4488ff',
|
||||||
|
pending: '#22aaaa',
|
||||||
|
confirmed: '#aaaaaa',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DarkTheme = {
|
||||||
|
remoteArea: '#080808',
|
||||||
|
localArea: '#888888',
|
||||||
|
splashArea: '#4c4c4c',
|
||||||
|
baseArea: '#080808',
|
||||||
|
frameArea: '#0a0a0a',
|
||||||
|
iconArea: '#ffffff',
|
||||||
|
headerArea: '#111111',
|
||||||
|
footerArea: '#111111',
|
||||||
|
modalArea: '#444444',
|
||||||
|
itemArea: '#222222',
|
||||||
|
inputArea: '#000000',
|
||||||
|
hoverArea: '#555555',
|
||||||
|
noticeArea: '#8fbea7',
|
||||||
|
selectedArea: '#333333',
|
||||||
|
enabledArea: '#448866',
|
||||||
|
disabledArea: '#888888',
|
||||||
|
mainText: '#ffffff',
|
||||||
|
descriptionText: '#999999',
|
||||||
|
hintText: '#aaaaaa',
|
||||||
|
activeText: '#ffffff',
|
||||||
|
idleText: '#aaaaaa',
|
||||||
|
placeholderText: '#686868',
|
||||||
|
linkText: '#66aa88',
|
||||||
|
labelText: '#dddddd',
|
||||||
|
alertText: '#ff8888',
|
||||||
|
itemBorder: '#555555',
|
||||||
|
inputBorder: '#aaaaaa',
|
||||||
|
sectionBorder: '#777777',
|
||||||
|
headerBorder: '#aaaaaa',
|
||||||
|
drawerBorder: '#444444',
|
||||||
|
unsaved: '#ffff00',
|
||||||
|
connected: '#44cc44',
|
||||||
|
connecting: '#dd88ff',
|
||||||
|
requested: '#4488ff',
|
||||||
|
pending: '#22aaaa',
|
||||||
|
confirmed: '#aaaaaa',
|
||||||
|
}
|
1254
app/client/web/src/constants/Strings.ts
Normal file
1254
app/client/web/src/constants/Strings.ts
Normal file
File diff suppressed because it is too large
Load Diff
13
app/client/web/src/context/SettingsContext.tsx
Normal file
13
app/client/web/src/context/SettingsContext.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { ReactNode, createContext } from 'react'
|
||||||
|
import { useSettingsContext } from './useSettingsContext.hook'
|
||||||
|
|
||||||
|
export const SettingsContext = createContext({})
|
||||||
|
|
||||||
|
export function SettingsContextProvider ({ children }: { children: ReactNode }) {
|
||||||
|
const { state, actions } = useSettingsContext()
|
||||||
|
return (
|
||||||
|
<SettingsContext.Provider value={{ state, actions }}>
|
||||||
|
{children}
|
||||||
|
</SettingsContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
229
app/client/web/src/context/useSettingsContext.hook.ts
Normal file
229
app/client/web/src/context/useSettingsContext.hook.ts
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { LightTheme, DarkTheme } from '../constants/Colors'
|
||||||
|
import { en, fr, sp, pt, de, ru } from '../constants/Strings'
|
||||||
|
|
||||||
|
export function useSettingsContext () {
|
||||||
|
const [state, setState] = useState({
|
||||||
|
display: null,
|
||||||
|
width: null,
|
||||||
|
height: null,
|
||||||
|
themes: [{ value: 'dark', label: 'Dark' }, { value: 'light', label: 'Light' }],
|
||||||
|
theme: null,
|
||||||
|
scheme: null,
|
||||||
|
colors: {},
|
||||||
|
menuStyle: {},
|
||||||
|
languages: [{ value: 'en', label: 'English' }, { value: 'fr', label: 'Français' }, { value: 'sp', label: 'Español' }, { value: 'pt', label: 'Português' }, { value: 'de', label: 'Deutsch' }, { value: 'ru', label: 'Русский' }],
|
||||||
|
language: null,
|
||||||
|
strings: en,
|
||||||
|
dateFormat: 'mm/dd',
|
||||||
|
timeFormat: '12h',
|
||||||
|
audioId: null,
|
||||||
|
audioInputs: [],
|
||||||
|
videoId: null,
|
||||||
|
videoInputs: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const SMALL_MEDIUM = 650
|
||||||
|
const MEDIUM_LARGE = 1000
|
||||||
|
const LARGE_XLARGE = 1600
|
||||||
|
|
||||||
|
const updateState = (value: any) => {
|
||||||
|
setState((s) => ({ ...s, ...value }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
if (window.innerWidth < SMALL_MEDIUM) {
|
||||||
|
updateState({ display: 'small', width: window.innerWidth, height: window.innerHeight })
|
||||||
|
} else if (window.innerWidth < MEDIUM_LARGE) {
|
||||||
|
updateState({ display: 'medium', width: window.innerWidth, height: window.innerHeight })
|
||||||
|
} else if (window.innerWidth < LARGE_XLARGE) {
|
||||||
|
updateState({ display: 'large', width: window.innerWidth, height: window.innerHeight })
|
||||||
|
} else {
|
||||||
|
updateState({ display: 'xlarge', width: window.innerWidth, height: window.innerHeight })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDevices = async (type: string) => {
|
||||||
|
if (!navigator || !navigator.mediaDevices) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const filtered = new Map()
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices()
|
||||||
|
|
||||||
|
devices.filter(item => item.kind === type + 'input').forEach(item => {
|
||||||
|
if (item) {
|
||||||
|
const label = item.label ? item.label : state.strings.integrated
|
||||||
|
const entry = filtered.get(item.groupId)
|
||||||
|
if (entry) {
|
||||||
|
if (item.label && label.length < entry.label.length) {
|
||||||
|
filtered.set(item.groupId, { value: item.deviceId, label })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filtered.set(item.groupId, { value: item.deviceId, label })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Array.from(filtered.values())
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDevices('audio').then(audio => {
|
||||||
|
updateState({ audioInputs: audio })
|
||||||
|
})
|
||||||
|
getDevices('video').then(video => {
|
||||||
|
updateState({ videoInputs: video })
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [state.strings]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
setTimeout(handleResize, 100 * i) // cludge for my mobile browser
|
||||||
|
}
|
||||||
|
handleResize()
|
||||||
|
window.addEventListener('resize', handleResize)
|
||||||
|
window.addEventListener('orientationchange', handleResize)
|
||||||
|
|
||||||
|
const scheme = localStorage.getItem('color_scheme')
|
||||||
|
if (scheme === 'dark') {
|
||||||
|
updateState({ theme: scheme, scheme: 'dark', colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.modalArea, color: DarkTheme.mainText } })
|
||||||
|
} else if (scheme === 'light') {
|
||||||
|
updateState({ theme: scheme, scheme: 'light', colors: LightTheme, menuStyle: { backgroundColor: LightTheme.modalArea, color: LightTheme.mainText } })
|
||||||
|
} else {
|
||||||
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
updateState({ theme: null, scheme: 'dark', colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.modalArea, color: DarkTheme.mainText } })
|
||||||
|
} else {
|
||||||
|
updateState({ theme: null, scheme: 'light', colors: LightTheme, menuStyle: { backgroundColor: LightTheme.modalArea, color: LightTheme.mainText } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeFormat = localStorage.getItem('time_format')
|
||||||
|
if (timeFormat === '24h') {
|
||||||
|
updateState({ timeFormat })
|
||||||
|
} else {
|
||||||
|
updateState({ timeFormat: '12h' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateFormat = localStorage.getItem('date_format')
|
||||||
|
if (dateFormat === 'dd/mm') {
|
||||||
|
updateState({ dateFormat })
|
||||||
|
} else {
|
||||||
|
updateState({ dateFormat: 'mm/dd' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const language = localStorage.getItem('language')
|
||||||
|
if (language && language.startsWith('fr')) {
|
||||||
|
updateState({ language: 'fr', strings: fr, themes: [{ value: 'dark', label: fr.dark }, { value: 'light', label: fr.light }] })
|
||||||
|
} else if (language && language.startsWith('sp')) {
|
||||||
|
updateState({ language: 'sp', strings: sp, themes: [{ value: 'dark', label: sp.dark }, { value: 'light', label: sp.light }] })
|
||||||
|
} else if (language && language.startsWith('en')) {
|
||||||
|
updateState({ language: 'en', strings: en, themes: [{ value: 'dark', label: en.dark }, { value: 'light', label: en.light }] })
|
||||||
|
} else if (language && language.startsWith('pt')) {
|
||||||
|
updateState({ language: 'pt', strings: pt, themes: [{ value: 'dark', label: pt.dark }, { value: 'light', label: pt.light }] })
|
||||||
|
} else if (language && language.startsWith('de')) {
|
||||||
|
updateState({ language: 'de', strings: de, themes: [{ value: 'dark', label: de.dark }, { value: 'light', label: de.light }] })
|
||||||
|
} else if (language && language.startsWith('ru')) {
|
||||||
|
updateState({ language: 'ru', strings: ru, themes: [{ value: 'dark', label: ru.dark }, { value: 'light', label: ru.light }] })
|
||||||
|
} else {
|
||||||
|
const browser = navigator.language
|
||||||
|
if (browser && browser.startsWith('fr')) {
|
||||||
|
updateState({ language: null, strings: fr, themes: [{ value: 'dark', label: fr.dark }, { value: 'light', label: fr.light }] })
|
||||||
|
} else if (browser && browser.startsWith('sp')) {
|
||||||
|
updateState({ language: null, strings: sp, themes: [{ value: 'dark', label: sp.dark }, { value: 'light', label: sp.light }] })
|
||||||
|
} else if (browser && browser.startsWith('pt')) {
|
||||||
|
updateState({ language: null, strings: pt, themes: [{ value: 'dark', label: pt.dark }, { value: 'light', label: pt.light }] })
|
||||||
|
} else if (browser && browser.startsWith('de')) {
|
||||||
|
updateState({ language: null, strings: de, themes: [{ value: 'dark', label: de.dark }, { value: 'light', label: de.light }] })
|
||||||
|
} else if (browser && browser.startsWith('ru')) {
|
||||||
|
updateState({ language: null, strings: ru, themes: [{ value: 'dark', label: ru.dark }, { value: 'light', label: ru.light }] })
|
||||||
|
} else {
|
||||||
|
updateState({ language: null, strings: en, themes: [{ value: 'dark', label: en.dark }, { value: 'light', label: en.light }] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const audioId = localStorage.getItem('audio_input')
|
||||||
|
const videoId = localStorage.getItem('video_input')
|
||||||
|
updateState({ audioId, videoId })
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', handleResize)
|
||||||
|
window.removeEventListener('orientationchange', handleResize)
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
setTheme: (theme: string) => {
|
||||||
|
if (theme === 'dark') {
|
||||||
|
localStorage.setItem('color_scheme', 'dark')
|
||||||
|
updateState({ theme: 'dark', scheme: 'dark', colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.modalArea, color: DarkTheme.mainText } })
|
||||||
|
} else if (theme === 'light') {
|
||||||
|
localStorage.setItem('color_scheme', 'light')
|
||||||
|
updateState({ theme: 'light', scheme: 'light', colors: LightTheme, menuStyle: { backgroundColor: LightTheme.modalArea, color: LightTheme.mainText } })
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('color_scheme')
|
||||||
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
updateState({ theme: null, scheme: 'dark', colors: DarkTheme, menuStyle: { backgroundColor: DarkTheme.modalArea, color: DarkTheme.mainText } })
|
||||||
|
} else {
|
||||||
|
updateState({ theme: null, scheme: 'ligth', colors: LightTheme, menuStyle: { backgroundColor: LightTheme.modalArea, color: LightTheme.mainText } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setLanguage: (code: string) => {
|
||||||
|
if (code && code.startsWith('fr')) {
|
||||||
|
localStorage.setItem('language', 'fr')
|
||||||
|
updateState({ language: 'fr', strings: fr, themes: [{ value: 'dark', label: fr.dark }, { value: 'light', label: fr.light }] })
|
||||||
|
} else if (code && code.startsWith('sp')) {
|
||||||
|
localStorage.setItem('language', 'sp')
|
||||||
|
updateState({ language: 'sp', strings: sp, themes: [{ value: 'dark', label: sp.dark }, { value: 'light', label: sp.light }] })
|
||||||
|
} else if (code && code.startsWith('en')) {
|
||||||
|
localStorage.setItem('language', 'en')
|
||||||
|
updateState({ language: 'en', strings: en, themes: [{ value: 'dark', label: en.dark }, { value: 'light', label: en.light }] })
|
||||||
|
} else if (code && code.startsWith('pt')) {
|
||||||
|
localStorage.setItem('language', 'pt')
|
||||||
|
updateState({ language: 'pt', strings: pt, themes: [{ value: 'dark', label: pt.dark }, { value: 'light', label: pt.light }] })
|
||||||
|
} else if (code && code.startsWith('de')) {
|
||||||
|
localStorage.setItem('language', 'de')
|
||||||
|
updateState({ language: 'de', strings: de, themes: [{ value: 'dark', label: de.dark }, { value: 'light', label: de.light }] })
|
||||||
|
} else if (code && code.startsWith('ru')) {
|
||||||
|
localStorage.setItem('language', 'ru')
|
||||||
|
updateState({ language: 'ru', strings: ru, themes: [{ value: 'dark', label: ru.dark }, { value: 'light', label: ru.light }] })
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('language')
|
||||||
|
const browser = navigator.language
|
||||||
|
if (browser && browser.startsWith('fr')) {
|
||||||
|
updateState({ language: null, strings: fr, themes: [{ value: 'dark', label: fr.dark }, { value: 'light', label: fr.light }] })
|
||||||
|
} else if (browser && browser.startsWith('sp')) {
|
||||||
|
updateState({ language: null, strings: sp, themes: [{ value: 'dark', label: sp.dark }, { value: 'light', label: sp.light }] })
|
||||||
|
} else if (browser && browser.startsWith('pt')) {
|
||||||
|
updateState({ language: null, strings: pt, themes: [{ value: 'dark', label: pt.dark }, { value: 'light', label: pt.light }] })
|
||||||
|
} else if (browser && browser.startsWith('de')) {
|
||||||
|
updateState({ language: null, strings: de, themes: [{ value: 'dark', label: de.dark }, { value: 'light', label: de.light }] })
|
||||||
|
} else if (browser && browser.startsWith('ru')) {
|
||||||
|
updateState({ language: null, strings: ru, themes: [{ value: 'dark', label: ru.dark }, { value: 'light', label: ru.light }] })
|
||||||
|
} else {
|
||||||
|
updateState({ language: null, strings: en, themes: [{ value: 'dark', label: en.dark }, { value: 'light', label: en.light }] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setDateFormat: (dateFormat: string) => {
|
||||||
|
localStorage.setItem('date_format', dateFormat)
|
||||||
|
updateState({ dateFormat })
|
||||||
|
},
|
||||||
|
setTimeFormat: (timeFormat: string) => {
|
||||||
|
localStorage.setItem('time_format', timeFormat)
|
||||||
|
updateState({ timeFormat })
|
||||||
|
},
|
||||||
|
setAudioInput: (audioId: string) => {
|
||||||
|
localStorage.setItem('audio_input', audioId)
|
||||||
|
updateState({ audioId })
|
||||||
|
},
|
||||||
|
setVideoInput: (videoId: string) => {
|
||||||
|
localStorage.setItem('video_input', videoId)
|
||||||
|
updateState({ videoId })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return { state, actions }
|
||||||
|
}
|
@ -3,6 +3,7 @@ import { createRoot } from 'react-dom/client'
|
|||||||
import { App } from '@/App'
|
import { App } from '@/App'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import { AppContextProvider } from './context/AppContext'
|
import { AppContextProvider } from './context/AppContext'
|
||||||
|
import { SettingsContextProvider } from './context/SettingsContext'
|
||||||
|
|
||||||
const rootElement = document.querySelector('[data-js="root"]')
|
const rootElement = document.querySelector('[data-js="root"]')
|
||||||
|
|
||||||
@ -12,9 +13,11 @@ if (!rootElement) {
|
|||||||
|
|
||||||
const root = createRoot(rootElement)
|
const root = createRoot(rootElement)
|
||||||
root.render(
|
root.render(
|
||||||
<AppContextProvider>
|
<SettingsContextProvider>
|
||||||
<StrictMode>
|
<AppContextProvider>
|
||||||
<App />
|
<StrictMode>
|
||||||
</StrictMode>
|
<App />
|
||||||
</AppContextProvider>,
|
</StrictMode>
|
||||||
|
</AppContextProvider>
|
||||||
|
</SettingsContextProvider>,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user