feat: refactor theme state

added hooks for is light or dark theme and cleaned up any references
pull/3083/head
William Grant 10 months ago
parent c20bda442e
commit 4f44a7a5fa

@ -1,7 +1,7 @@
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { getLeftPaneConversationIdsCount } from '../state/selectors/conversations'; import { getLeftPaneConversationIdsCount } from '../state/selectors/conversations';
import { getTheme } from '../state/selectors/theme'; import { useIsDarkTheme } from '../state/selectors/theme';
import { isSignWithRecoveryPhrase } from '../util/storage'; import { isSignWithRecoveryPhrase } from '../util/storage';
import { Flex } from './basic/Flex'; import { Flex } from './basic/Flex';
import { Spacer2XL, SpacerXS } from './basic/Text'; import { Spacer2XL, SpacerXS } from './basic/Text';
@ -67,7 +67,7 @@ const StyledNoConversations = styled(StyledP)`
`; `;
export const EmptyMessageView = () => { export const EmptyMessageView = () => {
const theme = useSelector(getTheme); const isDarkTheme = useIsDarkTheme();
const conversationCount = useSelector(getLeftPaneConversationIdsCount); const conversationCount = useSelector(getLeftPaneConversationIdsCount);
const isSignInWithRecoveryPhrase = isSignWithRecoveryPhrase(); const isSignInWithRecoveryPhrase = isSignWithRecoveryPhrase();
@ -89,7 +89,7 @@ export const EmptyMessageView = () => {
<Spacer2XL /> <Spacer2XL />
<StyledHeading>{window.i18n('onboardingAccountCreated')}</StyledHeading> <StyledHeading>{window.i18n('onboardingAccountCreated')}</StyledHeading>
<StyledSessionWelcome <StyledSessionWelcome
color={theme.includes('dark') ? 'var(--primary-color)' : 'var(--text-primary-color)'} color={isDarkTheme ? 'var(--primary-color)' : 'var(--text-primary-color)'}
> >
{window.i18n('onboardingBubbleWelcomeToSession')} {window.i18n('onboardingBubbleWelcomeToSession')}
</StyledSessionWelcome> </StyledSessionWelcome>

@ -1,6 +1,6 @@
import styled from 'styled-components'; import styled from 'styled-components';
export const SessionHeaderSearchInput = styled.input<{ darkMode: boolean }>` export const SessionHeaderSearchInput = styled.input<{ isDarkTheme: boolean }>`
color: var(--search-bar-text-control-color); color: var(--search-bar-text-control-color);
background-color: var(--search-bar-background-color); background-color: var(--search-bar-background-color);
border: 1px solid var(--input-border-color); border: 1px solid var(--input-border-color);
@ -25,7 +25,7 @@ export const SessionHeaderSearchInput = styled.input<{ darkMode: boolean }>`
&:focus { &:focus {
border: solid 1px border: solid 1px
${props => (props.darkMode ? 'var(--primary-color)' : 'var(--search-bar-text-user-color)')}; ${props => (props.isDarkTheme ? 'var(--primary-color)' : 'var(--search-bar-text-user-color)')};
color: var(--search-bar-text-user-color); color: var(--search-bar-text-user-color);
outline: none; outline: none;
} }

@ -1,10 +1,12 @@
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { CSSProperties, MouseEvent, useCallback, useEffect, useState } from 'react'; import { MouseEvent, useCallback, useEffect, useState } from 'react';
import { QRCode } from 'react-qrcode-logo'; import { QRCode } from 'react-qrcode-logo';
import useMount from 'react-use/lib/useMount'; import useMount from 'react-use/lib/useMount';
import styled from 'styled-components'; import styled, { CSSProperties } from 'styled-components';
import { ThemeStateType } from '../themes/constants/colors';
import { THEME_GLOBALS, getThemeValue } from '../themes/globals'; import { THEME_GLOBALS, getThemeValue } from '../themes/globals';
import { saveQRCode } from '../util/saveQRCode'; import { saveQRCode } from '../util/saveQRCode';
import { checkDarkTheme } from '../util/theme';
import { AnimatedFlex } from './basic/Flex'; import { AnimatedFlex } from './basic/Flex';
/** AnimatedFlex because we fade in the QR code to hide the logo flickering on first render /** AnimatedFlex because we fade in the QR code to hide the logo flickering on first render
@ -37,7 +39,7 @@ export type SessionQRCodeProps = {
logoWidth?: number; logoWidth?: number;
logoHeight?: number; logoHeight?: number;
logoIsSVG?: boolean; logoIsSVG?: boolean;
theme?: string; theme?: ThemeStateType;
ignoreTheme?: boolean; ignoreTheme?: boolean;
ariaLabel?: string; ariaLabel?: string;
dataTestId?: string; dataTestId?: string;
@ -77,7 +79,7 @@ export function SessionQRCode(props: SessionQRCodeProps) {
svgString = svgString.replaceAll( svgString = svgString.replaceAll(
'black', 'black',
getThemeValue( getThemeValue(
theme.includes('dark') ? '--background-primary-color' : '--text-primary-color' checkDarkTheme(theme) ? '--background-primary-color' : '--text-primary-color'
) )
); );
} }

@ -5,7 +5,7 @@ import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { getPrimaryColor } from '../../state/selectors/primaryColor'; import { getPrimaryColor } from '../../state/selectors/primaryColor';
import { getTheme, isDarkTheme } from '../../state/selectors/theme'; import { useIsDarkTheme, useTheme } from '../../state/selectors/theme';
import { import {
COLORS, COLORS,
ColorsType, ColorsType,
@ -105,8 +105,8 @@ const pickerProps = {
export const SessionEmojiPanel = forwardRef<HTMLDivElement, Props>((props: Props, ref) => { export const SessionEmojiPanel = forwardRef<HTMLDivElement, Props>((props: Props, ref) => {
const { onEmojiClicked, show, isModal = false, onKeyDown } = props; const { onEmojiClicked, show, isModal = false, onKeyDown } = props;
const primaryColor = useSelector(getPrimaryColor); const primaryColor = useSelector(getPrimaryColor);
const theme = useSelector(getTheme); const theme = useTheme();
const isDarkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
let panelBackgroundRGB = hexColorToRGB(THEMES.CLASSIC_DARK.COLOR1); let panelBackgroundRGB = hexColorToRGB(THEMES.CLASSIC_DARK.COLOR1);
let panelTextRGB = hexColorToRGB(THEMES.CLASSIC_DARK.COLOR6); let panelTextRGB = hexColorToRGB(THEMES.CLASSIC_DARK.COLOR6);
@ -142,7 +142,7 @@ export const SessionEmojiPanel = forwardRef<HTMLDivElement, Props>((props: Props
ref={ref} ref={ref}
> >
<Picker <Picker
theme={isDarkMode ? 'dark' : 'light'} theme={isDarkTheme ? 'dark' : 'light'}
i18n={i18nEmojiData} i18n={i18nEmojiData}
onEmojiSelect={onEmojiClicked} onEmojiSelect={onEmojiClicked}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}

@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { useScrollToLoadedMessage } from '../../contexts/ScrollToLoadedMessage'; import { useScrollToLoadedMessage } from '../../contexts/ScrollToLoadedMessage';
import { getQuotedMessageToAnimate } from '../../state/selectors/conversations'; import { getQuotedMessageToAnimate } from '../../state/selectors/conversations';
import { isDarkTheme } from '../../state/selectors/theme'; import { useIsDarkTheme } from '../../state/selectors/theme';
const LastSeenBar = styled.div` const LastSeenBar = styled.div`
height: 2px; height: 2px;
@ -24,7 +24,7 @@ const LastSeenText = styled.div`
margin-inline: 1rem; margin-inline: 1rem;
`; `;
const LastSeenBarContainer = styled.div<{ darkMode?: boolean }>` const LastSeenBarContainer = styled.div<{ isDarkTheme?: boolean }>`
padding-bottom: 35px; padding-bottom: 35px;
max-width: 300px; max-width: 300px;
align-self: center; align-self: center;
@ -36,11 +36,11 @@ const LastSeenBarContainer = styled.div<{ darkMode?: boolean }>`
${LastSeenBar} { ${LastSeenBar} {
background-color: ${props => background-color: ${props =>
props.darkMode ? 'var(--primary-color)' : 'var(--text-primary-color)'}; props.isDarkTheme ? 'var(--primary-color)' : 'var(--text-primary-color)'};
} }
${LastSeenText} { ${LastSeenText} {
color: ${props => (props.darkMode ? 'var(--primary-color)' : 'var(--text-primary-color)')}; color: ${props => (props.isDarkTheme ? 'var(--primary-color)' : 'var(--text-primary-color)')};
} }
`; `;
@ -49,7 +49,7 @@ export const SessionLastSeenIndicator = (props: {
didScroll: boolean; didScroll: boolean;
setDidScroll: (scroll: boolean) => void; setDidScroll: (scroll: boolean) => void;
}) => { }) => {
const darkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
// if this unread-indicator is not unique it's going to cause issues // if this unread-indicator is not unique it's going to cause issues
const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate); const quotedMessageToAnimate = useSelector(getQuotedMessageToAnimate);
const scrollToLoadedMessage = useScrollToLoadedMessage(); const scrollToLoadedMessage = useScrollToLoadedMessage();
@ -74,7 +74,7 @@ export const SessionLastSeenIndicator = (props: {
}); });
return ( return (
<LastSeenBarContainer id="unread-indicator" darkMode={darkMode}> <LastSeenBarContainer id="unread-indicator" isDarkTheme={isDarkTheme}>
<LastSeenBar /> <LastSeenBar />
<LastSeenText>{window.i18n('unreadMessages')}</LastSeenText> <LastSeenText>{window.i18n('unreadMessages')}</LastSeenText>

@ -1,10 +1,9 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { Data } from '../../../../data/data'; import { Data } from '../../../../data/data';
import { findAndFormatContact } from '../../../../models/message'; import { findAndFormatContact } from '../../../../models/message';
import { PubKey } from '../../../../session/types/PubKey'; import { PubKey } from '../../../../session/types/PubKey';
import { isDarkTheme } from '../../../../state/selectors/theme'; import { useIsDarkTheme } from '../../../../state/selectors/theme';
import { nativeEmojiData } from '../../../../util/emoji'; import { nativeEmojiData } from '../../../../util/emoji';
export type TipPosition = 'center' | 'left' | 'right'; export type TipPosition = 'center' | 'left' | 'right';
@ -66,8 +65,8 @@ const StyledContacts = styled.span`
} }
`; `;
const StyledOthers = styled.span<{ darkMode: boolean }>` const StyledOthers = styled.span<{ isDarkTheme: boolean }>`
color: ${props => (props.darkMode ? 'var(--primary-color)' : 'var(--text-primary-color)')}; color: ${props => (props.isDarkTheme ? 'var(--primary-color)' : 'var(--text-primary-color)')};
`; `;
const generateContactsString = async ( const generateContactsString = async (
@ -97,7 +96,7 @@ const generateContactsString = async (
}; };
const Contacts = (contacts: Array<string>, count: number) => { const Contacts = (contacts: Array<string>, count: number) => {
const darkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
if (!(contacts?.length > 0)) { if (!(contacts?.length > 0)) {
return null; return null;
@ -123,7 +122,7 @@ const Contacts = (contacts: Array<string>, count: number) => {
return ( return (
<StyledContacts> <StyledContacts>
{window.i18n('reactionPopupMany', [contacts[0], contacts[1], contacts[3]])}{' '} {window.i18n('reactionPopupMany', [contacts[0], contacts[1], contacts[3]])}{' '}
<StyledOthers darkMode={darkMode}> <StyledOthers isDarkTheme={isDarkTheme}>
{window.i18n(reactors === 4 ? 'otherSingular' : 'otherPlural', [`${count - 3}`])} {window.i18n(reactors === 4 ? 'otherSingular' : 'otherPlural', [`${count - 3}`])}
</StyledOthers>{' '} </StyledOthers>{' '}
<span>{window.i18n('reactionPopup')}</span> <span>{window.i18n('reactionPopup')}</span>

@ -1,5 +1,5 @@
import { ChangeEvent, useRef, useState } from 'react'; import { ChangeEvent, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useFocusMount } from '../../hooks/useFocusMount'; import { useFocusMount } from '../../hooks/useFocusMount';
import { useConversationPropsById } from '../../hooks/useParamSelector'; import { useConversationPropsById } from '../../hooks/useParamSelector';
@ -12,7 +12,7 @@ import { getConversationController } from '../../session/conversations/Conversat
import { PubKey } from '../../session/types'; import { PubKey } from '../../session/types';
import { ToastUtils } from '../../session/utils'; import { ToastUtils } from '../../session/utils';
import { BanType, updateBanOrUnbanUserModal } from '../../state/ducks/modalDialog'; import { BanType, updateBanOrUnbanUserModal } from '../../state/ducks/modalDialog';
import { isDarkTheme } from '../../state/selectors/theme'; import { useIsDarkTheme } from '../../state/selectors/theme';
import { SessionHeaderSearchInput } from '../SessionHeaderSearchInput'; import { SessionHeaderSearchInput } from '../SessionHeaderSearchInput';
import { SessionWrapperModal } from '../SessionWrapperModal'; import { SessionWrapperModal } from '../SessionWrapperModal';
import { Flex } from '../basic/Flex'; import { Flex } from '../basic/Flex';
@ -68,7 +68,7 @@ export const BanOrUnBanUserDialog = (props: {
const { i18n } = window; const { i18n } = window;
const isBan = banType === 'ban'; const isBan = banType === 'ban';
const dispatch = useDispatch(); const dispatch = useDispatch();
const darkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
const convo = getConversationController().get(conversationId); const convo = getConversationController().get(conversationId);
const inputRef = useRef(null); const inputRef = useRef(null);
@ -133,7 +133,7 @@ export const BanOrUnBanUserDialog = (props: {
<SessionHeaderSearchInput <SessionHeaderSearchInput
ref={inputRef} ref={inputRef}
type="text" type="text"
darkMode={darkMode} isDarkTheme={isDarkTheme}
placeholder={i18n('accountIdEnter')} placeholder={i18n('accountIdEnter')}
dir="auto" dir="auto"
onChange={onPubkeyBoxChanges} onChange={onPubkeyBoxChanges}

@ -1,12 +1,12 @@
import { useState } from 'react'; import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { sogsV3AddAdmin } from '../../session/apis/open_group_api/sogsv3/sogsV3AddRemoveMods'; import { sogsV3AddAdmin } from '../../session/apis/open_group_api/sogsv3/sogsV3AddRemoveMods';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { PubKey } from '../../session/types'; import { PubKey } from '../../session/types';
import { ToastUtils } from '../../session/utils'; import { ToastUtils } from '../../session/utils';
import { updateAddModeratorsModal } from '../../state/ducks/modalDialog'; import { updateAddModeratorsModal } from '../../state/ducks/modalDialog';
import { isDarkTheme } from '../../state/selectors/theme'; import { useIsDarkTheme } from '../../state/selectors/theme';
import { SessionHeaderSearchInput } from '../SessionHeaderSearchInput'; import { SessionHeaderSearchInput } from '../SessionHeaderSearchInput';
import { SessionWrapperModal } from '../SessionWrapperModal'; import { SessionWrapperModal } from '../SessionWrapperModal';
import { Flex } from '../basic/Flex'; import { Flex } from '../basic/Flex';
@ -21,7 +21,7 @@ export const AddModeratorsDialog = (props: Props) => {
const { conversationId } = props; const { conversationId } = props;
const dispatch = useDispatch(); const dispatch = useDispatch();
const darkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
const convo = getConversationController().get(conversationId); const convo = getConversationController().get(conversationId);
const [inputBoxValue, setInputBoxValue] = useState(''); const [inputBoxValue, setInputBoxValue] = useState('');
@ -85,7 +85,7 @@ export const AddModeratorsDialog = (props: Props) => {
<p>Add Moderator:</p> <p>Add Moderator:</p>
<SessionHeaderSearchInput <SessionHeaderSearchInput
type="text" type="text"
darkMode={darkMode} isDarkTheme={isDarkTheme}
placeholder={i18n('accountIdEnter')} placeholder={i18n('accountIdEnter')}
dir="auto" dir="auto"
onChange={onPubkeyBoxChanges} onChange={onPubkeyBoxChanges}

@ -1,6 +1,5 @@
import { useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { getTheme } from '../../../state/selectors/theme'; import { useIsDarkTheme, useTheme } from '../../../state/selectors/theme';
import { getThemeValue } from '../../../themes/globals'; import { getThemeValue } from '../../../themes/globals';
import { SessionQRCode } from '../../SessionQRCode'; import { SessionQRCode } from '../../SessionQRCode';
import { Avatar, AvatarSize } from '../../avatar/Avatar'; import { Avatar, AvatarSize } from '../../avatar/Avatar';
@ -9,7 +8,8 @@ import { SpacerSM } from '../../basic/Text';
import { SessionIconButton } from '../../icon'; import { SessionIconButton } from '../../icon';
export const QRView = ({ sessionID }: { sessionID: string }) => { export const QRView = ({ sessionID }: { sessionID: string }) => {
const theme = useSelector(getTheme); const theme = useTheme();
const isDarkTheme = useIsDarkTheme();
return ( return (
<SessionQRCode <SessionQRCode
@ -17,10 +17,10 @@ export const QRView = ({ sessionID }: { sessionID: string }) => {
value={sessionID} value={sessionID}
size={170} size={170}
backgroundColor={getThemeValue( backgroundColor={getThemeValue(
theme.includes('dark') ? '--text-primary-color' : '--background-primary-color' isDarkTheme ? '--text-primary-color' : '--background-primary-color'
)} )}
foregroundColor={getThemeValue( foregroundColor={getThemeValue(
theme.includes('dark') ? '--background-primary-color' : '--text-primary-color' isDarkTheme ? '--background-primary-color' : '--text-primary-color'
)} )}
logoImage={'./images/session/qr/brand.svg'} logoImage={'./images/session/qr/brand.svg'}
logoWidth={40} logoWidth={40}

@ -43,7 +43,7 @@ import {
getFreshSwarmFor, getFreshSwarmFor,
} from '../../session/apis/snode_api/snodePool'; } from '../../session/apis/snode_api/snodePool';
import { ConfigurationSync } from '../../session/utils/job_runners/jobs/ConfigurationSyncJob'; import { ConfigurationSync } from '../../session/utils/job_runners/jobs/ConfigurationSyncJob';
import { isDarkTheme } from '../../state/selectors/theme'; import { useIsDarkTheme } from '../../state/selectors/theme';
import { switchThemeTo } from '../../themes/switchTheme'; import { switchThemeTo } from '../../themes/switchTheme';
import { ReleasedFeatures } from '../../util/releaseFeature'; import { ReleasedFeatures } from '../../util/releaseFeature';
import { getOppositeTheme } from '../../util/theme'; import { getOppositeTheme } from '../../util/theme';
@ -55,7 +55,7 @@ const Section = (props: { type: SectionType }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { type } = props; const { type } = props;
const isDarkMode = useSelector(isDarkTheme); const isDarkTheme = useIsDarkTheme();
const focusedSection = useSelector(getFocusedSection); const focusedSection = useSelector(getFocusedSection);
const isSelected = focusedSection === props.type; const isSelected = focusedSection === props.type;
@ -132,7 +132,7 @@ const Section = (props: { type: SectionType }) => {
return ( return (
<SessionIconButton <SessionIconButton
iconSize="medium" iconSize="medium"
iconType={isDarkMode ? 'moon' : 'sun'} iconType={isDarkTheme ? 'moon' : 'sun'}
dataTestId="theme-section" dataTestId="theme-section"
onClick={handleClick} onClick={handleClick}
isSelected={isSelected} isSelected={isSelected}

@ -10,7 +10,7 @@ import {
import { disableRecoveryPhrasePrompt } from '../../state/ducks/userConfig'; import { disableRecoveryPhrasePrompt } from '../../state/ducks/userConfig';
import { getFocusedSection, getLeftOverlayMode } from '../../state/selectors/section'; import { getFocusedSection, getLeftOverlayMode } from '../../state/selectors/section';
import { useHideRecoveryPasswordEnabled } from '../../state/selectors/settings'; import { useHideRecoveryPasswordEnabled } from '../../state/selectors/settings';
import { getTheme } from '../../state/selectors/theme'; import { useIsDarkTheme } from '../../state/selectors/theme';
import { getShowRecoveryPhrasePrompt } from '../../state/selectors/userConfig'; import { getShowRecoveryPhrasePrompt } from '../../state/selectors/userConfig';
import { isSignWithRecoveryPhrase } from '../../util/storage'; import { isSignWithRecoveryPhrase } from '../../util/storage';
import { Flex } from '../basic/Flex'; import { Flex } from '../basic/Flex';
@ -80,7 +80,7 @@ const StyledLeftPaneBanner = styled.div`
`; `;
export const LeftPaneBanner = () => { export const LeftPaneBanner = () => {
const theme = useSelector(getTheme); const isDarkTheme = useIsDarkTheme();
const section = useSelector(getFocusedSection); const section = useSelector(getFocusedSection);
const isSignInWithRecoveryPhrase = isSignWithRecoveryPhrase(); const isSignInWithRecoveryPhrase = isSignWithRecoveryPhrase();
const hideRecoveryPassword = useHideRecoveryPasswordEnabled(); const hideRecoveryPassword = useHideRecoveryPasswordEnabled();
@ -112,7 +112,7 @@ export const LeftPaneBanner = () => {
<Flex container={true} width={'100%'} alignItems="flex-start"> <Flex container={true} width={'100%'} alignItems="flex-start">
<StyledBannerTitle>{window.i18n('saveRecoveryPassword')}</StyledBannerTitle> <StyledBannerTitle>{window.i18n('saveRecoveryPassword')}</StyledBannerTitle>
<SessionIcon <SessionIcon
iconType={theme.includes('dark') ? 'recoveryPasswordFill' : 'recoveryPasswordOutline'} iconType={isDarkTheme ? 'recoveryPasswordFill' : 'recoveryPasswordOutline'}
iconSize="medium" iconSize="medium"
iconColor="var(--text-primary-color)" iconColor="var(--text-primary-color)"
/> />

@ -1,7 +1,7 @@
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { getPrimaryColor } from '../../state/selectors/primaryColor'; import { getPrimaryColor } from '../../state/selectors/primaryColor';
import { getTheme } from '../../state/selectors/theme'; import { useTheme } from '../../state/selectors/theme';
import { import {
StyleSessionSwitcher, StyleSessionSwitcher,
getPrimaryColors, getPrimaryColors,
@ -73,7 +73,7 @@ const ThemePreview = (props: { style: StyleSessionSwitcher }) => {
const Themes = () => { const Themes = () => {
const themes = getThemeColors(); const themes = getThemeColors();
const selectedTheme = useSelector(getTheme); const selectedTheme = useTheme();
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (

@ -1,6 +1,6 @@
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useState } from 'react'; import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import useMount from 'react-use/lib/useMount'; import useMount from 'react-use/lib/useMount';
import styled from 'styled-components'; import styled from 'styled-components';
import { usePasswordModal } from '../../../hooks/usePasswordModal'; import { usePasswordModal } from '../../../hooks/usePasswordModal';
@ -8,7 +8,7 @@ import { mnDecode } from '../../../session/crypto/mnemonic';
import { updateHideRecoveryPasswordModel } from '../../../state/ducks/modalDialog'; import { updateHideRecoveryPasswordModel } from '../../../state/ducks/modalDialog';
import { showSettingsSection } from '../../../state/ducks/section'; import { showSettingsSection } from '../../../state/ducks/section';
import { useHideRecoveryPasswordEnabled } from '../../../state/selectors/settings'; import { useHideRecoveryPasswordEnabled } from '../../../state/selectors/settings';
import { getTheme } from '../../../state/selectors/theme'; import { useIsDarkTheme, useTheme } from '../../../state/selectors/theme';
import { THEME_GLOBALS, getThemeValue } from '../../../themes/globals'; import { THEME_GLOBALS, getThemeValue } from '../../../themes/globals';
import { getCurrentRecoveryPhrase } from '../../../util/storage'; import { getCurrentRecoveryPhrase } from '../../../util/storage';
import { SessionQRCode } from '../../SessionQRCode'; import { SessionQRCode } from '../../SessionQRCode';
@ -61,7 +61,8 @@ export const SettingsCategoryRecoveryPassword = () => {
dispatch(showSettingsSection('privacy')); dispatch(showSettingsSection('privacy'));
}, },
}); });
const theme = useSelector(getTheme); const theme = useTheme();
const isDarkTheme = useIsDarkTheme();
const fetchRecoverPhrase = () => { const fetchRecoverPhrase = () => {
const newRecoveryPhrase = getCurrentRecoveryPhrase(); const newRecoveryPhrase = getCurrentRecoveryPhrase();
@ -103,10 +104,10 @@ export const SettingsCategoryRecoveryPassword = () => {
value={hexEncodedSeed} value={hexEncodedSeed}
size={240} size={240}
backgroundColor={getThemeValue( backgroundColor={getThemeValue(
theme.includes('dark') ? '--text-primary-color' : '--background-primary-color' isDarkTheme ? '--text-primary-color' : '--background-primary-color'
)} )}
foregroundColor={getThemeValue( foregroundColor={getThemeValue(
theme.includes('dark') ? '--background-primary-color' : '--text-primary-color' isDarkTheme ? '--background-primary-color' : '--text-primary-color'
)} )}
logoImage={'./images/session/qr/shield.svg'} logoImage={'./images/session/qr/shield.svg'}
logoWidth={56} logoWidth={56}
@ -124,7 +125,7 @@ export const SettingsCategoryRecoveryPassword = () => {
justifyContent={'space-between'} justifyContent={'space-between'}
alignItems={'center'} alignItems={'center'}
width={'100%'} width={'100%'}
color={theme.includes('dark') ? 'var(--primary-color)' : 'var(--text-primary-color)'} color={isDarkTheme ? 'var(--primary-color)' : 'var(--text-primary-color)'}
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
animate={{ opacity: 1 }} animate={{ opacity: 1 }}
transition={{ duration: THEME_GLOBALS['--default-duration-seconds'] }} transition={{ duration: THEME_GLOBALS['--default-duration-seconds'] }}

@ -102,9 +102,9 @@ async function copyFromQuotedMessage(
: quotedMessage.propsForMessage.text) || ''; : quotedMessage.propsForMessage.text) || '';
if (isMessageModel(quotedMessage)) { if (isMessageModel(quotedMessage)) {
window.inboxStore.dispatch(pushQuotedMessageDetails(quotedMessage.getMessageModelProps())); window.inboxStore?.dispatch(pushQuotedMessageDetails(quotedMessage.getMessageModelProps()));
} else { } else {
window.inboxStore.dispatch(pushQuotedMessageDetails(quotedMessage)); window.inboxStore?.dispatch(pushQuotedMessageDetails(quotedMessage));
} }
// no attachments, just save the quote with the body // no attachments, just save the quote with the body

@ -1,12 +1,12 @@
import { bindActionCreators, Dispatch } from '@reduxjs/toolkit'; import { bindActionCreators, Dispatch } from '@reduxjs/toolkit';
import { actions as search } from './ducks/search';
import { actions as conversations } from './ducks/conversations'; import { actions as conversations } from './ducks/conversations';
import { actions as user } from './ducks/user';
import { actions as sections } from './ducks/section';
import { actions as theme } from './ducks/theme';
import { actions as modalDialog } from './ducks/modalDialog'; import { actions as modalDialog } from './ducks/modalDialog';
import { actions as primaryColor } from './ducks/primaryColor'; import { actions as primaryColor } from './ducks/primaryColor';
import { actions as search } from './ducks/search';
import { actions as sections } from './ducks/section';
import { actions as theme } from './ducks/theme';
import { actions as user } from './ducks/user';
export function mapDispatchToProps(dispatch: Dispatch): object { export function mapDispatchToProps(dispatch: Dispatch): object {
return { return {

@ -1,34 +1,19 @@
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { ThemeStateType } from '../../themes/constants/colors'; import { ThemeStateType } from '../../themes/constants/colors';
export const APPLY_THEME = 'APPLY_THEME'; // TODO Move primary color into this slice
export const initialThemeState: ThemeStateType = 'classic-dark' as ThemeStateType;
export const applyTheme = (theme: ThemeStateType) => { const themeSlice = createSlice({
return { name: 'theme',
type: APPLY_THEME, initialState: initialThemeState,
payload: theme, reducers: {
}; updateTheme(_, action: PayloadAction<ThemeStateType>) {
}; return action.payload;
},
},
});
export const initialThemeState: ThemeStateType = 'classic-dark'; export const { actions, reducer } = themeSlice;
export const { updateTheme } = actions;
export const reducer = ( export const defaultThemeReducer = reducer;
state: any = initialThemeState,
{
type,
payload,
}: {
type: string;
payload: ThemeStateType;
}
): ThemeStateType => {
switch (type) {
case APPLY_THEME:
return payload;
default:
return state;
}
};
export const actions = {
applyTheme,
};

@ -1,9 +1,17 @@
import { createSelector } from '@reduxjs/toolkit';
import { useSelector } from 'react-redux';
import { ThemeStateType } from '../../themes/constants/colors'; import { ThemeStateType } from '../../themes/constants/colors';
import { StateType } from '../reducer';
import { checkDarkTheme, checkLightTheme } from '../../util/theme'; import { checkDarkTheme, checkLightTheme } from '../../util/theme';
import { StateType } from '../reducer';
export const getTheme = (state: StateType): ThemeStateType => state.theme; export const getTheme = (state: StateType): ThemeStateType => state.theme;
export const isDarkTheme = (state: StateType): boolean => checkDarkTheme(state.theme); const getIsDarkTheme = createSelector(getTheme, (state): boolean => checkDarkTheme(state));
const getIsLightTheme = createSelector(getTheme, (state): boolean => checkLightTheme(state));
export const useTheme = () => useSelector(getTheme);
export const useIsDarkTheme = () => useSelector(getIsDarkTheme);
export const isLightTheme = (state: StateType): boolean => checkLightTheme(state.theme); export const useIsLightTheme = () => useSelector(getIsLightTheme);

@ -1,6 +1,6 @@
import { Dispatch } from '@reduxjs/toolkit'; import { Dispatch } from '@reduxjs/toolkit';
import { classicDark, classicLight, oceanDark, oceanLight } from '.'; import { classicDark, classicLight, oceanDark, oceanLight } from '.';
import { applyTheme } from '../state/ducks/theme'; import { updateTheme } from '../state/ducks/theme';
import { THEMES, ThemeStateType, convertThemeStateToName } from './constants/colors'; import { THEMES, ThemeStateType, convertThemeStateToName } from './constants/colors';
import { setThemeValues } from './globals'; import { setThemeValues } from './globals';
import { findPrimaryColorId, switchPrimaryColorTo } from './switchPrimaryColor'; import { findPrimaryColorId, switchPrimaryColorTo } from './switchPrimaryColor';
@ -43,7 +43,7 @@ export async function switchThemeTo(props: SwitchThemeProps) {
} }
if (dispatch) { if (dispatch) {
dispatch(applyTheme(newTheme)); dispatch(updateTheme(newTheme));
if (usePrimaryColor) { if (usePrimaryColor) {
// Set primary color after the theme is loaded so that it's not overwritten // Set primary color after the theme is loaded so that it's not overwritten
const primaryColor = window.Events.getPrimaryColorSetting(); const primaryColor = window.Events.getPrimaryColorSetting();

Loading…
Cancel
Save