feat: the primary color is now reset when changing themes

refactored theme and primary color switching functions
This commit is contained in:
William Grant 2022-10-11 11:37:58 +11:00
parent 177e2df768
commit b777d0bcd1
8 changed files with 158 additions and 98 deletions

View file

@ -36,7 +36,11 @@ export const AboutView = () => {
useEffect(() => {
if ((window as any).theme) {
void switchThemeTo((window as any).theme, null, false);
void switchThemeTo({
theme: (window as any).theme,
mainWindow: false,
resetPrimaryColor: false,
});
}
}, []);

View file

@ -101,7 +101,11 @@ const DebugLogViewAndSave = () => {
export const DebugLogView = () => {
useEffect(() => {
if ((window as any).theme) {
void switchThemeTo((window as any).theme, null, false);
void switchThemeTo({
theme: (window as any).theme,
mainWindow: false,
resetPrimaryColor: false,
});
}
}, []);

View file

@ -192,7 +192,11 @@ class SessionPasswordPromptInner extends React.PureComponent<{}, State> {
export const SessionPasswordPrompt = () => {
useEffect(() => {
if ((window as any).theme) {
void switchThemeTo((window as any).theme, null, false);
void switchThemeTo({
theme: (window as any).theme,
mainWindow: false,
resetPrimaryColor: false,
});
}
}, []);

View file

@ -49,10 +49,10 @@ import { ipcRenderer } from 'electron';
import { UserUtils } from '../../session/utils';
import { getLatestReleaseFromFileServer } from '../../session/apis/file_server_api/FileServerApi';
import { switchThemeTo } from '../../session/utils/Theme';
import { switchThemeTo } from '../../themes/switchTheme';
import { ThemeStateType } from '../../themes/constants/colors';
import { getTheme } from '../../state/selectors/theme';
import { switchPrimaryColor } from '../../themes/switchPrimaryColor';
import { switchPrimaryColorTo } from '../../themes/switchPrimaryColor';
const Section = (props: { type: SectionType }) => {
const ourNumber = useSelector(getOurNumber);
@ -74,7 +74,12 @@ const Section = (props: { type: SectionType }) => {
? currentTheme.replace('light', 'dark')
: currentTheme.replace('dark', 'light')) as ThemeStateType;
await switchThemeTo(newTheme, dispatch);
await switchThemeTo({
theme: newTheme,
mainWindow: true,
resetPrimaryColor: true,
dispatch,
});
} else if (type === SectionType.PathIndicator) {
// Show Path Indicator Modal
dispatch(onionPathModal({}));
@ -154,11 +159,18 @@ const cleanUpMediasInterval = DURATION.MINUTES * 60;
const fetchReleaseFromFileServerInterval = 1000 * 60; // try to fetch the latest release from the fileserver every minute
const setupTheme = async () => {
const primaryColor = window.Events.getPrimaryColorSetting();
await switchPrimaryColor(primaryColor, window?.inboxStore?.dispatch || null);
const theme = window.Events.getThemeSetting();
await switchThemeTo(theme, window?.inboxStore?.dispatch || null);
// We don't want to reset the primary color on startup
await switchThemeTo({
theme,
mainWindow: true,
resetPrimaryColor: false,
dispatch: window?.inboxStore?.dispatch || undefined,
});
// Set primary color after the theme is loaded so that it's not overwritten
const primaryColor = window.Events.getPrimaryColorSetting();
await switchPrimaryColorTo(primaryColor, window?.inboxStore?.dispatch || null);
};
// Do this only if we created a new Session ID, or if we already received the initial configuration message

View file

@ -1,13 +1,17 @@
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { switchThemeTo } from '../../session/utils/Theme';
import { switchThemeTo } from '../../themes/switchTheme';
import { getTheme } from '../../state/selectors/theme';
import { SessionRadio, SessionRadioPrimaryColors } from '../basic/SessionRadio';
import { SpacerLG, SpacerMD } from '../basic/Text';
import { StyledDescriptionSettingsItem, StyledTitleSettingsItem } from './SessionSettingListItem';
import { getPrimaryColors, THEMES, ThemeStateType } from '../../themes/constants/colors';
import { switchPrimaryColor } from '../../themes/switchPrimaryColor';
import {
getPrimaryColors,
getThemeColors,
StyleSessionSwitcher,
} from '../../themes/constants/colors';
import { switchPrimaryColorTo } from '../../themes/switchPrimaryColor';
import { getPrimaryColor } from '../../state/selectors/primaryColor';
// tslint:disable: use-simple-attributes
@ -47,19 +51,6 @@ const ThemesContainer = styled.div`
gap: var(--margins-lg);
`;
type ThemeType = {
id: ThemeStateType;
title: string;
style: StyleSessionSwitcher;
};
type StyleSessionSwitcher = {
background: string;
border: string;
receivedBackground: string;
sentBackground: string;
};
const StyledPreview = styled.svg`
max-height: 100%;
`;
@ -84,49 +75,7 @@ const ThemePreview = (props: { style: StyleSessionSwitcher }) => {
};
const Themes = () => {
const themes: Array<ThemeType> = [
{
id: 'classic-dark',
title: window.i18n('classicDarkThemeTitle'),
style: {
background: THEMES.CLASSIC_DARK.COLOR0,
border: THEMES.CLASSIC_DARK.COLOR3,
receivedBackground: THEMES.CLASSIC_DARK.COLOR2,
sentBackground: THEMES.CLASSIC_DARK.PRIMARY,
},
},
{
id: 'classic-light',
title: window.i18n('classicLightThemeTitle'),
style: {
background: THEMES.CLASSIC_LIGHT.COLOR6,
border: THEMES.CLASSIC_LIGHT.COLOR3,
receivedBackground: THEMES.CLASSIC_LIGHT.COLOR4,
sentBackground: THEMES.CLASSIC_LIGHT.PRIMARY,
},
},
{
id: 'ocean-dark',
title: window.i18n('oceanDarkThemeTitle'),
style: {
background: THEMES.OCEAN_DARK.COLOR2,
border: THEMES.OCEAN_DARK.COLOR4,
receivedBackground: THEMES.OCEAN_DARK.COLOR4,
sentBackground: THEMES.OCEAN_DARK.PRIMARY,
},
},
{
id: 'ocean-light',
title: window.i18n('oceanLightThemeTitle'),
style: {
background: THEMES.OCEAN_LIGHT.COLOR7!,
border: THEMES.OCEAN_LIGHT.COLOR3,
receivedBackground: THEMES.OCEAN_LIGHT.COLOR1,
sentBackground: THEMES.OCEAN_LIGHT.PRIMARY,
},
},
];
const themes = getThemeColors();
const selectedTheme = useSelector(getTheme);
const dispatch = useDispatch();
@ -135,9 +84,13 @@ const Themes = () => {
{themes.map(theme => (
<ThemeContainer
key={theme.id}
onClick={() => {
// TODO Change to switchTheme function
void switchThemeTo(theme.id, dispatch);
onClick={async () => {
await switchThemeTo({
theme: theme.id,
mainWindow: true,
resetPrimaryColor: true,
dispatch,
});
}}
>
<ThemePreview style={theme.style} />
@ -179,8 +132,8 @@ export const SettingsThemeSwitcher = () => {
inputName="primary-colors"
ariaLabel={item.ariaLabel}
color={item.color}
onClick={() => {
switchPrimaryColor(item.id, dispatch);
onClick={async () => {
await switchPrimaryColorTo(item.id, dispatch);
}}
/>
);

View file

@ -91,22 +91,25 @@ export type PrimaryColorStateType =
type PrimaryColorType = { id: PrimaryColorStateType; ariaLabel: string; color: string };
export const getPrimaryColors = (): Array<PrimaryColorType> => {
return [
{ id: 'green', ariaLabel: window.i18n('primaryColorGreen'), color: COLORS.PRIMARY.GREEN },
{ id: 'blue', ariaLabel: window.i18n('primaryColorBlue'), color: COLORS.PRIMARY.BLUE },
{ id: 'yellow', ariaLabel: window.i18n('primaryColorYellow'), color: COLORS.PRIMARY.YELLOW },
{ id: 'pink', ariaLabel: window.i18n('primaryColorPink'), color: COLORS.PRIMARY.PINK },
{ id: 'purple', ariaLabel: window.i18n('primaryColorPurple'), color: COLORS.PRIMARY.PURPLE },
{ id: 'orange', ariaLabel: window.i18n('primaryColorOrange'), color: COLORS.PRIMARY.ORANGE },
{ id: 'red', ariaLabel: window.i18n('primaryColorRed'), color: COLORS.PRIMARY.RED },
];
};
export const getPrimaryColors = (): Array<PrimaryColorType> => [
{ id: 'green', ariaLabel: window.i18n('primaryColorGreen'), color: COLORS.PRIMARY.GREEN },
{ id: 'blue', ariaLabel: window.i18n('primaryColorBlue'), color: COLORS.PRIMARY.BLUE },
{ id: 'yellow', ariaLabel: window.i18n('primaryColorYellow'), color: COLORS.PRIMARY.YELLOW },
{ id: 'pink', ariaLabel: window.i18n('primaryColorPink'), color: COLORS.PRIMARY.PINK },
{ id: 'purple', ariaLabel: window.i18n('primaryColorPurple'), color: COLORS.PRIMARY.PURPLE },
{ id: 'orange', ariaLabel: window.i18n('primaryColorOrange'), color: COLORS.PRIMARY.ORANGE },
{ id: 'red', ariaLabel: window.i18n('primaryColorRed'), color: COLORS.PRIMARY.RED },
];
// Themes
export type ThemeStateType = 'classic-light' | 'classic-dark' | 'ocean-light' | 'ocean-dark'; // used for redux state
type ThemeNames = 'CLASSIC_LIGHT' | 'CLASSIC_DARK' | 'OCEAN_LIGHT' | 'OCEAN_DARK';
export function convertThemeStateToName(themeState: string): ThemeNames {
return themeState.replace('-', '_').toUpperCase() as ThemeNames;
}
type ThemeColors = {
PRIMARY: string;
DANGER: string;
@ -225,4 +228,60 @@ const THEMES: Themes = {
},
};
type ThemeType = {
id: ThemeStateType;
title: string;
style: StyleSessionSwitcher;
};
export type StyleSessionSwitcher = {
background: string;
border: string;
receivedBackground: string;
sentBackground: string;
};
export const getThemeColors = (): Array<ThemeType> => [
{
id: 'classic-dark',
title: window.i18n('classicDarkThemeTitle'),
style: {
background: THEMES.CLASSIC_DARK.COLOR0,
border: THEMES.CLASSIC_DARK.COLOR3,
receivedBackground: THEMES.CLASSIC_DARK.COLOR2,
sentBackground: THEMES.CLASSIC_DARK.PRIMARY,
},
},
{
id: 'classic-light',
title: window.i18n('classicLightThemeTitle'),
style: {
background: THEMES.CLASSIC_LIGHT.COLOR6,
border: THEMES.CLASSIC_LIGHT.COLOR3,
receivedBackground: THEMES.CLASSIC_LIGHT.COLOR4,
sentBackground: THEMES.CLASSIC_LIGHT.PRIMARY,
},
},
{
id: 'ocean-dark',
title: window.i18n('oceanDarkThemeTitle'),
style: {
background: THEMES.OCEAN_DARK.COLOR2,
border: THEMES.OCEAN_DARK.COLOR4,
receivedBackground: THEMES.OCEAN_DARK.COLOR4,
sentBackground: THEMES.OCEAN_DARK.PRIMARY,
},
},
{
id: 'ocean-light',
title: window.i18n('oceanLightThemeTitle'),
style: {
background: THEMES.OCEAN_LIGHT.COLOR7!,
border: THEMES.OCEAN_LIGHT.COLOR3,
receivedBackground: THEMES.OCEAN_LIGHT.COLOR1,
sentBackground: THEMES.OCEAN_LIGHT.PRIMARY,
},
},
];
export { COLORS, THEMES };

View file

@ -1,8 +1,17 @@
import { find } from 'lodash';
import { Dispatch } from 'redux';
import { applyPrimaryColor } from '../state/ducks/primaryColor';
import { COLORS, PrimaryColorStateType } from './constants/colors';
import { COLORS, getPrimaryColors, PrimaryColorStateType } from './constants/colors';
export async function switchPrimaryColor(color: PrimaryColorStateType, dispatch: Dispatch | null) {
export function findPrimaryColorId(hexCode: string): PrimaryColorStateType | undefined {
const primaryColors = getPrimaryColors();
return find(primaryColors, { color: hexCode })?.id;
}
export async function switchPrimaryColorTo(
color: PrimaryColorStateType,
dispatch: Dispatch | null
) {
await window.Events.setPrimaryColorSetting(color);
document.documentElement.style.setProperty(

View file

@ -1,19 +1,20 @@
import { Dispatch } from 'redux';
import { applyTheme } from '../state/ducks/theme';
import { classicDark, classicLight, oceanDark, oceanLight } from '.';
import { ThemeStateType } from './constants/colors';
import { convertThemeStateToName, THEMES, ThemeStateType } from './constants/colors';
import { switchHtmlToDarkTheme, switchHtmlToLightTheme } from './SessionTheme';
import { loadThemeColors } from './variableColors';
import { findPrimaryColorId, switchPrimaryColorTo } from './switchPrimaryColor';
export async function switchThemeTo(
theme: ThemeStateType,
dispatch: Dispatch | null,
mainWindow: boolean = true
) {
if (mainWindow) {
await window.setTheme(theme);
}
type SwitchThemeProps = {
theme: ThemeStateType;
mainWindow: boolean;
resetPrimaryColor: boolean;
dispatch?: Dispatch;
};
export async function switchThemeTo(props: SwitchThemeProps) {
const { theme, mainWindow = true, resetPrimaryColor = true, dispatch } = props;
let newTheme: ThemeStateType | null = null;
switch (theme) {
@ -41,7 +42,21 @@ export async function switchThemeTo(
window.log.warn('Unsupported theme: ', theme);
}
if (dispatch && newTheme) {
dispatch(applyTheme(newTheme));
if (newTheme) {
if (mainWindow) {
await window.setTheme(theme);
}
if (dispatch) {
dispatch(applyTheme(newTheme));
if (resetPrimaryColor) {
const defaultPrimaryColor = findPrimaryColorId(
THEMES[convertThemeStateToName(newTheme)].PRIMARY
);
if (defaultPrimaryColor) {
await switchPrimaryColorTo(defaultPrimaryColor, dispatch);
}
}
}
}
}