From e5bfda37af2d9ea87869429c63cc6869dd7357d1 Mon Sep 17 00:00:00 2001 From: William Grant Date: Mon, 26 Sep 2022 15:52:31 +1000 Subject: [PATCH] feat: primary color switching now persists fixed isDarkMode, will need to confirm when we add ocean themes --- preload.js | 5 +++ .../conversation/SessionEmojiPanel.tsx | 17 +++++--- .../message/reactions/ReactionPopup.tsx | 2 +- ts/components/dialog/BanOrUnbanUserDialog.tsx | 2 +- ts/components/dialog/ModeratorsAddDialog.tsx | 2 +- ts/components/dialog/ReactClearAllModal.tsx | 2 +- ts/components/leftpane/ActionsPanel.tsx | 4 ++ ts/mains/main_node.ts | 12 ++++++ ts/mains/main_renderer.tsx | 4 ++ ts/themes/switchPrimaryColor.tsx | 4 +- ts/themes/{switchTheme.ts => switchTheme.tsx} | 41 +++++++++++++------ 11 files changed, 72 insertions(+), 23 deletions(-) rename ts/themes/{switchTheme.ts => switchTheme.tsx} (95%) diff --git a/preload.js b/preload.js index 43829eec0..4befbbffd 100644 --- a/preload.js +++ b/preload.js @@ -150,6 +150,11 @@ window.readyForUpdates = () => { ipc.send('ready-for-updates'); }; +ipc.on('get-primary-color-setting', () => { + const primaryColor = window.Events.getPrimaryColorSetting(); + ipc.send('get-success-primary-color-setting', primaryColor); +}); + ipc.on('get-theme-setting', () => { const theme = window.Events.getThemeSetting(); ipc.send('get-success-theme-setting', theme); diff --git a/ts/components/conversation/SessionEmojiPanel.tsx b/ts/components/conversation/SessionEmojiPanel.tsx index 55a4118bc..c7e085f75 100644 --- a/ts/components/conversation/SessionEmojiPanel.tsx +++ b/ts/components/conversation/SessionEmojiPanel.tsx @@ -9,8 +9,9 @@ import { getTheme } from '../../state/selectors/theme'; import { noop } from 'lodash'; import { loadEmojiPanelI18n } from '../../util/i18n'; import { FixedBaseEmoji, FixedPickerProps } from '../../types/Reaction'; +import { ThemeStateType } from '../../themes/colors.js'; -export const StyledEmojiPanel = styled.div<{ isModal: boolean; theme: 'light' | 'dark' }>` +export const StyledEmojiPanel = styled.div<{ isModal: boolean; theme: ThemeStateType }>` padding: var(--margins-lg); z-index: 5; opacity: 0; @@ -40,15 +41,20 @@ export const StyledEmojiPanel = styled.div<{ isModal: boolean; theme: 'light' | ${props => { switch (props.theme) { - // TODO Theming - Add Ocean Colors - case 'dark': + case 'ocean-dark': + // TODO Theming + return ``; + case 'ocean-light': + // TODO Theming + return ``; + case 'classic-dark': return ` --background-rgb: 27, 27, 27; // var(--color-cell-background) --rgb-background: 27, 27, 27; --rgb-color: 255, 255, 255; // var(--color-text) --rgb-input: 27, 27, 27; `; - case 'light': + case 'classic-light': default: return ` --background-rgb: 249, 249, 249; // var(--color-cell-background) @@ -97,6 +103,7 @@ const pickerProps: FixedPickerProps = { export const SessionEmojiPanel = forwardRef((props: Props, ref) => { const { onEmojiClicked, show, isModal = false, onKeyDown } = props; const theme = useSelector(getTheme); + const emojiPanelTheme = theme.includes('light') ? 'light' : 'dark'; const pickerRef = ref as MutableRefObject; useEffect(() => { @@ -113,7 +120,7 @@ export const SessionEmojiPanel = forwardRef((props: Props data, ref, i18n, - theme, + theme: emojiPanelTheme, onEmojiSelect: onEmojiClicked, onKeyDown, ...pickerProps, diff --git a/ts/components/conversation/message/reactions/ReactionPopup.tsx b/ts/components/conversation/message/reactions/ReactionPopup.tsx index 04b262abb..f458c4e94 100644 --- a/ts/components/conversation/message/reactions/ReactionPopup.tsx +++ b/ts/components/conversation/message/reactions/ReactionPopup.tsx @@ -96,7 +96,7 @@ const generateContactsString = async ( }; const Contacts = (contacts: Array, count: number) => { - const darkMode = useSelector(getTheme) === 'classic-dark'; + const darkMode = useSelector(getTheme).includes('dark'); if (!Boolean(contacts?.length > 0)) { return; diff --git a/ts/components/dialog/BanOrUnbanUserDialog.tsx b/ts/components/dialog/BanOrUnbanUserDialog.tsx index 914ac7c35..e22162df5 100644 --- a/ts/components/dialog/BanOrUnbanUserDialog.tsx +++ b/ts/components/dialog/BanOrUnbanUserDialog.tsx @@ -67,7 +67,7 @@ export const BanOrUnBanUserDialog = (props: { const { i18n } = window; const isBan = banType === 'ban'; const dispatch = useDispatch(); - const darkMode = useSelector(getTheme) === 'classic-dark'; + const darkMode = useSelector(getTheme).includes('dark'); const convo = getConversationController().get(conversationId); const inputRef = useRef(null); diff --git a/ts/components/dialog/ModeratorsAddDialog.tsx b/ts/components/dialog/ModeratorsAddDialog.tsx index 831a5a123..34d058057 100644 --- a/ts/components/dialog/ModeratorsAddDialog.tsx +++ b/ts/components/dialog/ModeratorsAddDialog.tsx @@ -20,7 +20,7 @@ export const AddModeratorsDialog = (props: Props) => { const { conversationId } = props; const dispatch = useDispatch(); - const darkMode = useSelector(getTheme) === 'classic-dark'; + const darkMode = useSelector(getTheme).includes('dark'); const convo = getConversationController().get(conversationId); const [inputBoxValue, setInputBoxValue] = useState(''); diff --git a/ts/components/dialog/ReactClearAllModal.tsx b/ts/components/dialog/ReactClearAllModal.tsx index 11de49a18..1d0dd99c7 100644 --- a/ts/components/dialog/ReactClearAllModal.tsx +++ b/ts/components/dialog/ReactClearAllModal.tsx @@ -54,7 +54,7 @@ export const ReactClearAllModal = (props: Props): ReactElement => { const [clearingInProgress, setClearingInProgress] = useState(false); const dispatch = useDispatch(); - const darkMode = useSelector(getTheme) === 'classic-dark'; + const darkMode = useSelector(getTheme).includes('dark'); const msgProps = useMessageReactsPropsById(messageId); if (!msgProps) { diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx index 336dd62e4..c7a4a0d17 100644 --- a/ts/components/leftpane/ActionsPanel.tsx +++ b/ts/components/leftpane/ActionsPanel.tsx @@ -52,6 +52,7 @@ import { getLatestReleaseFromFileServer } from '../../session/apis/file_server_a import { switchThemeTo } from '../../session/utils/Theme'; import { ThemeStateType } from '../../themes/colors'; import { getTheme } from '../../state/selectors/theme'; +import { switchPrimaryColor } from '../../themes/switchPrimaryColor'; const Section = (props: { type: SectionType }) => { const ourNumber = useSelector(getOurNumber); @@ -153,6 +154,9 @@ 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); }; diff --git a/ts/mains/main_node.ts b/ts/mains/main_node.ts index 496719de5..6c721168c 100644 --- a/ts/mains/main_node.ts +++ b/ts/mains/main_node.ts @@ -641,6 +641,8 @@ async function showDebugLogWindow() { return; } + // TODO Theming - Use on debug and about pages + const primaryColor = await getPrimaryColorFromMainWindow(); const theme = await getThemeFromMainWindow(); const size = mainWindow.getSize(); const options = { @@ -667,6 +669,7 @@ async function showDebugLogWindow() { captureClicks(debugLogWindow); + // TODO Theming - Check if it needs the priary color await debugLogWindow.loadURL(prepareURL([getAppRootPath(), 'debug_log.html'], { theme })); debugLogWindow.on('closed', () => { @@ -1099,6 +1102,15 @@ ipc.on('set-auto-update-setting', async (_event, enabled) => { } }); +async function getPrimaryColorFromMainWindow() { + return new Promise(resolve => { + ipc.once('get-success-primary-color-setting', (_event, value) => { + resolve(value); + }); + mainWindow?.webContents.send('get-primary-color-setting'); + }); +} + async function getThemeFromMainWindow() { return new Promise(resolve => { ipc.once('get-success-theme-setting', (_event, value) => { diff --git a/ts/mains/main_renderer.tsx b/ts/mains/main_renderer.tsx index f748c2bd4..425ec116f 100644 --- a/ts/mains/main_renderer.tsx +++ b/ts/mains/main_renderer.tsx @@ -127,6 +127,10 @@ Storage.onready(async () => { // These make key operations available to IPC handlers created in preload.js window.Events = { + getPrimaryColorSetting: () => Storage.get('primary-color-setting', 'green'), + setPrimaryColorSetting: async (value: any) => { + await Storage.put('primary-color-setting', value); + }, getThemeSetting: () => Storage.get('theme-setting', 'classic-light'), setThemeSetting: async (value: any) => { await Storage.put('theme-setting', value); diff --git a/ts/themes/switchPrimaryColor.tsx b/ts/themes/switchPrimaryColor.tsx index 4ae7e673f..84cd7b980 100644 --- a/ts/themes/switchPrimaryColor.tsx +++ b/ts/themes/switchPrimaryColor.tsx @@ -2,7 +2,9 @@ import { Dispatch } from 'redux'; import { applyPrimaryColor } from '../state/ducks/primaryColor'; import { COLORS, PrimaryColorStateType } from './colors'; -export function switchPrimaryColor(color: PrimaryColorStateType, dispatch: Dispatch | null) { +export async function switchPrimaryColor(color: PrimaryColorStateType, dispatch: Dispatch | null) { + await window.Events.setPrimaryColorSetting(color); + document.documentElement.style.setProperty( '--primary-color', (COLORS.PRIMARY as any)[`${color.toUpperCase()}`] diff --git a/ts/themes/switchTheme.ts b/ts/themes/switchTheme.tsx similarity index 95% rename from ts/themes/switchTheme.ts rename to ts/themes/switchTheme.tsx index d8880893b..ae0ac358b 100644 --- a/ts/themes/switchTheme.ts +++ b/ts/themes/switchTheme.tsx @@ -1,8 +1,13 @@ import { hexColorToRGB } from '../util/hexColorToRGB'; -import { COLORS, THEMES, ThemeStateType } from './colors'; +import { COLORS, PrimaryColorStateType, THEMES, ThemeStateType } from './colors'; -function loadClassicLight() { - document.documentElement.style.setProperty('--primary-color', THEMES.CLASSIC_LIGHT.PRIMARY); +function loadClassicLight(primaryColor?: PrimaryColorStateType) { + document.documentElement.style.setProperty( + '--primary-color', + primaryColor && primaryColor !== THEMES.CLASSIC_LIGHT.PRIMARY + ? primaryColor + : THEMES.CLASSIC_LIGHT.PRIMARY + ); document.documentElement.style.setProperty('--danger-color', THEMES.CLASSIC_LIGHT.DANGER); document.documentElement.style.setProperty( @@ -354,8 +359,13 @@ function loadClassicLight() { ); } -function loadClassicDark() { - document.documentElement.style.setProperty('--primary-color', THEMES.CLASSIC_DARK.PRIMARY); +function loadClassicDark(primaryColor?: PrimaryColorStateType) { + document.documentElement.style.setProperty( + '--primary-color', + primaryColor && primaryColor !== THEMES.CLASSIC_DARK.PRIMARY + ? primaryColor + : THEMES.CLASSIC_DARK.PRIMARY + ); document.documentElement.style.setProperty('--danger-color', THEMES.CLASSIC_DARK.DANGER); document.documentElement.style.setProperty( @@ -695,26 +705,31 @@ function loadClassicDark() { ); } -function loadOceanLight() {} +function loadOceanLight(primaryColor?: PrimaryColorStateType) {} -function loadOceanDark() {} +function loadOceanDark(primaryColor?: PrimaryColorStateType) {} + +export async function switchTheme(theme: ThemeStateType) { + const selectedPrimaryColor = await window.Events.getPrimaryColorSetting(); + const primaryColor = + (selectedPrimaryColor && (COLORS.PRIMARY as any)[`${selectedPrimaryColor.toUpperCase()}`]) || + null; -export const switchTheme = (theme: ThemeStateType) => { switch (theme) { case 'classic-light': - loadClassicLight(); + loadClassicLight(primaryColor); break; case 'classic-dark': - loadClassicDark(); + loadClassicDark(primaryColor); break; case 'ocean-light': - loadOceanLight(); + loadOceanLight(primaryColor); break; case 'ocean-dark': - loadOceanDark(); + loadOceanDark(primaryColor); break; default: window.log.warn('Unsupported theme:', theme); break; } -}; +}