Split up dark and light color settings

Previously it was possible to choose a color combination
that was almost impossible to read (due to contrast).
Now we have prevented this from happening, as well as
giving the user more customizability.
This commit is contained in:
Brandon Presley 2022-11-26 13:15:12 +13:00
parent 0c5a221e0f
commit dc27ae9868
9 changed files with 107 additions and 32 deletions

32
App.tsx
View File

@ -43,10 +43,12 @@ const App = () => {
const [snackbar, setSnackbar] = useState('') const [snackbar, setSnackbar] = useState('')
const [theme, setTheme] = useState('system') const [theme, setTheme] = useState('system')
const [color, setColor] = useState<string>( const [lightColor, setLightColor] = useState<string>(
isDark CombinedDefaultTheme.colors.primary,
? CombinedDarkTheme.colors.primary )
: CombinedDefaultTheme.colors.primary,
const [darkColor, setDarkColor] = useState<string>(
CombinedDarkTheme.colors.primary,
) )
useEffect(() => { useEffect(() => {
@ -55,7 +57,7 @@ const App = () => {
const settings = await settingsRepo.findOne({where: {}}) const settings = await settingsRepo.findOne({where: {}})
console.log(`${App.name}.useEffect:`, {gotSettings: settings}) console.log(`${App.name}.useEffect:`, {gotSettings: settings})
setTheme(settings.theme) setTheme(settings.theme)
if (settings.color) setColor(settings.color) if (settings.lightColor) setLightColor(settings.lightColor)
setInitialized(true) setInitialized(true)
} }
init() init()
@ -70,23 +72,23 @@ const App = () => {
}, []) }, [])
const paperTheme = useMemo(() => { const paperTheme = useMemo(() => {
const darkTheme = color const darkTheme = lightColor
? { ? {
...CombinedDarkTheme, ...CombinedDarkTheme,
colors: {...CombinedDarkTheme.colors, primary: color}, colors: {...CombinedDarkTheme.colors, primary: darkColor},
} }
: CombinedDarkTheme : CombinedDarkTheme
const lightTheme = color const lightTheme = lightColor
? { ? {
...CombinedDefaultTheme, ...CombinedDefaultTheme,
colors: {...CombinedDefaultTheme.colors, primary: color}, colors: {...CombinedDefaultTheme.colors, primary: lightColor},
} }
: CombinedDefaultTheme : CombinedDefaultTheme
let value = isDark ? darkTheme : lightTheme let value = isDark ? darkTheme : lightTheme
if (theme === 'dark') value = darkTheme if (theme === 'dark') value = darkTheme
else if (theme === 'light') value = lightTheme else if (theme === 'light') value = lightTheme
return value return value
}, [isDark, theme, color]) }, [isDark, theme, lightColor, darkColor])
const action = useMemo( const action = useMemo(
() => ({ () => ({
@ -103,7 +105,15 @@ const App = () => {
settings={{icon: props => <MaterialIcon {...props} />}}> settings={{icon: props => <MaterialIcon {...props} />}}>
<NavigationContainer theme={paperTheme}> <NavigationContainer theme={paperTheme}>
{initialized && ( {initialized && (
<ThemeContext.Provider value={{theme, setTheme, color, setColor}}> <ThemeContext.Provider
value={{
theme,
setTheme,
lightColor,
setLightColor,
darkColor,
setDarkColor,
}}>
<Routes /> <Routes />
</ThemeContext.Provider> </ThemeContext.Provider>
)} )}

View File

@ -1,13 +1,12 @@
import {ComponentProps} from 'react' import {ComponentProps} from 'react'
import {FAB} from 'react-native-paper' import {FAB, useTheme} from 'react-native-paper'
import {CombinedDarkTheme, CombinedDefaultTheme} from './App' import {CombinedDarkTheme, CombinedDefaultTheme} from './App'
import {lightColors} from './colors' import {lightColors} from './colors'
import {useTheme} from './use-theme'
export default function MassiveFab(props: Partial<ComponentProps<typeof FAB>>) { export default function MassiveFab(props: Partial<ComponentProps<typeof FAB>>) {
const {color} = useTheme() const {colors} = useTheme()
const fabColor = lightColors.includes(color) const fabColor = lightColors.includes(colors.primary)
? CombinedDarkTheme.colors.background ? CombinedDarkTheme.colors.background
: CombinedDefaultTheme.colors.background : CombinedDefaultTheme.colors.background
@ -19,7 +18,7 @@ export default function MassiveFab(props: Partial<ComponentProps<typeof FAB>>) {
position: 'absolute', position: 'absolute',
right: 20, right: 20,
bottom: 20, bottom: 20,
backgroundColor: color, backgroundColor: colors.primary,
}} }}
{...props} {...props}
/> />

View File

@ -40,7 +40,10 @@ export default function Select({
anchor={ anchor={
<Button <Button
onPress={() => setShow(true)} onPress={() => setShow(true)}
style={{alignSelf: 'flex-start', marginTop: MARGIN}}> style={{
alignSelf: 'flex-start',
marginTop: MARGIN,
}}>
{selected?.label} {selected?.label}
</Button> </Button>
}> }>

View File

@ -36,7 +36,8 @@ export default function SettingsPage() {
const [showUnit, setShowUnit] = useState(false) const [showUnit, setShowUnit] = useState(false)
const [steps, setSteps] = useState(false) const [steps, setSteps] = useState(false)
const [date, setDate] = useState('P') const [date, setDate] = useState('P')
const {theme, setTheme, color, setColor} = useTheme() const {theme, setTheme, lightColor, setLightColor, darkColor, setDarkColor} =
useTheme()
const [showDate, setShowDate] = useState(false) const [showDate, setShowDate] = useState(false)
const [noSound, setNoSound] = useState(false) const [noSound, setNoSound] = useState(false)
const [formatOptions, setFormatOptions] = useState<string[]>(defaultFormats) const [formatOptions, setFormatOptions] = useState<string[]>(defaultFormats)
@ -45,6 +46,7 @@ export default function SettingsPage() {
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
settingsRepo.findOne({where: {}}).then(settings => { settingsRepo.findOne({where: {}}).then(settings => {
console.log(`${SettingsPage.name}.focus:`, settings)
setAlarm(settings.alarm) setAlarm(settings.alarm)
setVibrate(settings.vibrate) setVibrate(settings.vibrate)
setSound(settings.sound) setSound(settings.sound)
@ -193,12 +195,20 @@ export default function SettingsPage() {
return ': ' + split.pop() return ': ' + split.pop()
}, [sound]) }, [sound])
const changeColor = useCallback( const changeDarkColor = useCallback(
(value: string) => { (value: string) => {
setColor(value) setDarkColor(value)
settingsRepo.update({}, {color: value}) settingsRepo.update({}, {darkColor: value})
}, },
[setColor], [setDarkColor],
)
const changeLightColor = useCallback(
(value: string) => {
setLightColor(value)
settingsRepo.update({}, {lightColor: value})
},
[setLightColor],
) )
const renderItem = useCallback( const renderItem = useCallback(
@ -247,10 +257,21 @@ export default function SettingsPage() {
)} )}
{'color'.includes(term.toLowerCase()) && ( {'color'.includes(term.toLowerCase()) && (
<Select <Select
value={color} value={darkColor}
onChange={changeColor} onChange={changeDarkColor}
items={lightColors.concat(darkColors).map(colorOption => ({ items={lightColors.map(colorOption => ({
label: 'Primary color', label: 'Dark color',
value: colorOption,
color: colorOption,
}))}
/>
)}
{'color'.includes(term.toLowerCase()) && (
<Select
value={lightColor}
onChange={changeLightColor}
items={darkColors.map(colorOption => ({
label: 'Light color',
value: colorOption, value: colorOption,
color: colorOption, color: colorOption,
}))} }))}

View File

@ -1,4 +1,7 @@
import {DarkTheme, DefaultTheme} from 'react-native-paper'
export const lightColors = [ export const lightColors = [
DarkTheme.colors.primary,
'#B3E5FC', '#B3E5FC',
'#FA8072', '#FA8072',
'#FFC0CB', '#FFC0CB',
@ -6,7 +9,12 @@ export const lightColors = [
'#BBA1CE', '#BBA1CE',
] ]
export const darkColors = ['#8156A7', '#007AFF', '#000000', '#CD5C5C'] export const darkColors = [
DefaultTheme.colors.primary,
'#007AFF',
'#000000',
'#CD5C5C',
]
export const colorShade = (color: any, amount: number) => { export const colorShade = (color: any, amount: number) => {
color = color.replace(/^#/, '') color = color.replace(/^#/, '')

View File

@ -23,6 +23,7 @@ import {addShowSets1667186443614} from './migrations/1667186443614-add-show-sets
import {addSetsCreated1667186451005} from './migrations/1667186451005-add-sets-created' import {addSetsCreated1667186451005} from './migrations/1667186451005-add-sets-created'
import {addNoSound1667186456118} from './migrations/1667186456118-add-no-sound' import {addNoSound1667186456118} from './migrations/1667186456118-add-no-sound'
import {dropMigrations1667190214743} from './migrations/1667190214743-drop-migrations' import {dropMigrations1667190214743} from './migrations/1667190214743-drop-migrations'
import {splitColor1669420187764} from './migrations/1669420187764-split-color'
import {Plan} from './plan' import {Plan} from './plan'
import Settings from './settings' import Settings from './settings'
@ -57,5 +58,6 @@ export const AppDataSource = new DataSource({
addSetsCreated1667186451005, addSetsCreated1667186451005,
addNoSound1667186456118, addNoSound1667186456118,
dropMigrations1667190214743, dropMigrations1667190214743,
splitColor1669420187764,
], ],
}) })

View File

@ -0,0 +1,24 @@
import {MigrationInterface, QueryRunner, TableColumn} from 'typeorm'
export class splitColor1669420187764 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.addColumn(
'settings',
new TableColumn({name: 'lightColor', type: 'text', isNullable: true}),
)
await queryRunner.addColumn(
'settings',
new TableColumn({name: 'darkColor', type: 'text', isNullable: true}),
)
await queryRunner.dropColumn('settings', 'color')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropColumn('settings', 'darkColor')
await queryRunner.dropColumn('settings', 'lightColor')
await queryRunner.addColumn(
'settings',
new TableColumn({name: 'color', type: 'text', isNullable: true}),
)
}
}

View File

@ -21,7 +21,10 @@ export default class Settings {
showUnit: boolean showUnit: boolean
@Column('text') @Column('text')
color?: string lightColor?: string
@Column('text')
darkColor?: string
@Column('boolean') @Column('boolean')
steps: boolean steps: boolean

View File

@ -1,15 +1,20 @@
import {createContext, useContext} from 'react' import {createContext, useContext} from 'react'
import {DarkTheme, DefaultTheme} from 'react-native-paper'
export const ThemeContext = createContext<{ export const ThemeContext = createContext<{
theme: string theme: string
color: string lightColor: string
setTheme: (value: string) => void setTheme: (value: string) => void
setColor: (value: string) => void setLightColor: (value: string) => void
darkColor: string
setDarkColor: (value: string) => void
}>({ }>({
theme: 'system', theme: 'system',
color: '', lightColor: DefaultTheme.colors.primary,
setTheme: () => null, setTheme: () => null,
setColor: () => null, setLightColor: () => null,
darkColor: DarkTheme.colors.primary,
setDarkColor: () => null,
}) })
export function useTheme() { export function useTheme() {