From 8c88d45c8e5977988160904f987f5c8ac0e98332 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 May 2022 19:19:08 -0500 Subject: [PATCH 1/5] Break out useSystemTheme into a hook --- app/soapbox/containers/soapbox.tsx | 17 +++-------------- app/soapbox/hooks/index.ts | 1 + app/soapbox/hooks/useSystemTheme.ts | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 app/soapbox/hooks/useSystemTheme.ts diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index 500a7b67d..028f47ef5 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -20,7 +20,7 @@ import PublicLayout from 'soapbox/features/public_layout'; import NotificationsContainer from 'soapbox/features/ui/containers/notifications_container'; import WaitlistPage from 'soapbox/features/verification/waitlist_page'; import { createGlobals } from 'soapbox/globals'; -import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures, useSoapboxConfig, useSettings } from 'soapbox/hooks'; +import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures, useSoapboxConfig, useSettings, useSystemTheme } from 'soapbox/hooks'; import MESSAGES from 'soapbox/locales/messages'; import { generateThemeCss } from 'soapbox/utils/theme'; @@ -82,17 +82,12 @@ const SoapboxMount = () => { const [localeLoading, setLocaleLoading] = useState(true); const [isLoaded, setIsLoaded] = useState(false); - const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)'); - const [isSystemDarkMode, setSystemDarkMode] = useState(colorSchemeQueryList.matches); + const systemTheme = useSystemTheme(); const userTheme = settings.get('themeMode'); - const darkMode = userTheme === 'dark' || (userTheme === 'system' && isSystemDarkMode); + const darkMode = userTheme === 'dark' || (userTheme === 'system' && systemTheme === 'dark'); const themeCss = generateThemeCss(soapboxConfig); - const handleSystemModeChange = (event: MediaQueryListEvent) => { - setSystemDarkMode(event.matches); - }; - // Load the user's locale useEffect(() => { MESSAGES[locale]().then(messages => { @@ -110,12 +105,6 @@ const SoapboxMount = () => { }); }, []); - useEffect(() => { - colorSchemeQueryList.addEventListener('change', handleSystemModeChange); - - return () => colorSchemeQueryList.removeEventListener('change', handleSystemModeChange); - }, []); - // @ts-ignore: I don't actually know what these should be, lol const shouldUpdateScroll = (prevRouterProps, { location }) => { return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prevRouterProps?.location?.state?.soapboxModalKey); diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 0c6698988..66fd31059 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -6,3 +6,4 @@ export { useOnScreen } from './useOnScreen'; export { useOwnAccount } from './useOwnAccount'; export { useSettings } from './useSettings'; export { useSoapboxConfig } from './useSoapboxConfig'; +export { useSystemTheme } from './useSystemTheme'; diff --git a/app/soapbox/hooks/useSystemTheme.ts b/app/soapbox/hooks/useSystemTheme.ts new file mode 100644 index 000000000..3258851f5 --- /dev/null +++ b/app/soapbox/hooks/useSystemTheme.ts @@ -0,0 +1,21 @@ +import { useState, useEffect } from 'react'; + +type SystemTheme = 'light' | 'dark'; + +/** Get the system color scheme of the system. */ +export const useSystemTheme = (): SystemTheme => { + const query = window.matchMedia('(prefers-color-scheme: dark)'); + const [dark, setDark] = useState(query.matches); + + const handleChange = (event: MediaQueryListEvent) => { + setDark(event.matches); + }; + + useEffect(() => { + query.addEventListener('change', handleChange); + + return () => query.removeEventListener('change', handleChange); + }, []); + + return dark ? 'dark' : 'light'; +}; From 56f339a61964fbcf6ca565e34fbfdfde4e98ded9 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 May 2022 19:21:59 -0500 Subject: [PATCH 2/5] SitePreview: take advantage of useSystemTheme --- .../features/soapbox_config/components/site-preview.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/soapbox/features/soapbox_config/components/site-preview.tsx b/app/soapbox/features/soapbox_config/components/site-preview.tsx index 12a5a1de3..82b35974a 100644 --- a/app/soapbox/features/soapbox_config/components/site-preview.tsx +++ b/app/soapbox/features/soapbox_config/components/site-preview.tsx @@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl'; import { defaultSettings } from 'soapbox/actions/settings'; import BackgroundShapes from 'soapbox/features/ui/components/background_shapes'; +import { useSystemTheme } from 'soapbox/hooks'; import { normalizeSoapboxConfig } from 'soapbox/normalizers'; import { generateThemeCss } from 'soapbox/utils/theme'; @@ -17,7 +18,10 @@ const SitePreview: React.FC = ({ soapbox }) => { const soapboxConfig = useMemo(() => normalizeSoapboxConfig(soapbox), [soapbox]); const settings = defaultSettings.mergeDeep(soapboxConfig.defaultSettings); - const dark = settings.get('themeMode') === 'dark'; + const userTheme = settings.get('themeMode'); + const systemTheme = useSystemTheme(); + + const dark = userTheme === 'dark' || (userTheme === 'system' && systemTheme === 'dark'); const bodyClass = classNames( 'site-preview', From 01ec7bc279ee93ed6b5c6c78fbcf295264a01bb1 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 May 2022 19:54:23 -0500 Subject: [PATCH 3/5] Replace logos throughout the UI with SiteLogo component --- app/soapbox/components/sidebar_menu.tsx | 14 ++------- app/soapbox/components/site-logo.tsx | 30 +++++++++++++++++++ app/soapbox/features/auth_layout/index.tsx | 15 ++-------- .../public_layout/components/header.tsx | 9 ++---- .../components/modals/landing-page-modal.tsx | 4 +-- app/soapbox/features/ui/components/navbar.tsx | 29 +++++------------- .../features/verification/waitlist_page.js | 8 ++--- 7 files changed, 50 insertions(+), 59 deletions(-) create mode 100644 app/soapbox/components/site-logo.tsx diff --git a/app/soapbox/components/sidebar_menu.tsx b/app/soapbox/components/sidebar_menu.tsx index 2a0946e6e..5339247f5 100644 --- a/app/soapbox/components/sidebar_menu.tsx +++ b/app/soapbox/components/sidebar_menu.tsx @@ -9,9 +9,10 @@ import { fetchOwnAccounts } from 'soapbox/actions/auth'; import { getSettings } from 'soapbox/actions/settings'; import { closeSidebar } from 'soapbox/actions/sidebar'; import Account from 'soapbox/components/account'; +import SiteLogo from 'soapbox/components/site-logo'; import { Stack } from 'soapbox/components/ui'; import ProfileStats from 'soapbox/features/ui/components/profile_stats'; -import { useAppSelector, useSoapboxConfig, useFeatures } from 'soapbox/hooks'; +import { useAppSelector, useFeatures } from 'soapbox/hooks'; import { makeGetAccount, makeGetOtherAccounts } from 'soapbox/selectors'; import { getBaseURL } from 'soapbox/utils/accounts'; @@ -66,7 +67,6 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { const intl = useIntl(); const dispatch = useDispatch(); - const { logo } = useSoapboxConfig(); const features = useFeatures(); const getAccount = makeGetAccount(); const instance = useAppSelector((state) => state.instance); @@ -141,15 +141,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { - {logo ? ( - Logo - ) : ( - - )} + > = (props) => { + const { logo, logoDarkMode } = useSoapboxConfig(); + const settings = useSettings(); + + const systemTheme = useSystemTheme(); + const userTheme = settings.get('themeMode'); + const darkMode = userTheme === 'dark' || (userTheme === 'system' && systemTheme === 'dark'); + + // Use the right logo if provided, then use fallbacks. + const getSrc = () => { + // In demo mode, use the Soapbox logo. + if (settings.get('demo')) return require('images/soapbox-logo.svg'); + + return (darkMode && logoDarkMode) + ? logoDarkMode + : logo || logoDarkMode || require('@tabler/icons/icons/home.svg'); + }; + + return ( + // eslint-disable-next-line jsx-a11y/alt-text + + ); +}; + +export default SiteLogo; diff --git a/app/soapbox/features/auth_layout/index.tsx b/app/soapbox/features/auth_layout/index.tsx index c694f173b..f96904580 100644 --- a/app/soapbox/features/auth_layout/index.tsx +++ b/app/soapbox/features/auth_layout/index.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { Link, Redirect, Route, Switch } from 'react-router-dom'; import LandingGradient from 'soapbox/components/landing-gradient'; -import SvgIcon from 'soapbox/components/ui/icon/svg-icon'; +import SiteLogo from 'soapbox/components/site-logo'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { NotificationsContainer } from 'soapbox/features/ui/util/async-components'; -import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks'; +import { useAppSelector } from 'soapbox/hooks'; import { Card, CardBody } from '../../components/ui'; import LoginPage from '../auth_login/components/login_page'; @@ -18,7 +18,6 @@ import Verification from '../verification'; import EmailPassthru from '../verification/email_passthru'; const AuthLayout = () => { - const { logo } = useSoapboxConfig(); const siteTitle = useAppSelector(state => state.instance.title); return ( @@ -29,15 +28,7 @@ const AuthLayout = () => {
- {logo ? ( - {siteTitle} - ) : ( - - )} +
diff --git a/app/soapbox/features/public_layout/components/header.tsx b/app/soapbox/features/public_layout/components/header.tsx index 63e03c472..985fca476 100644 --- a/app/soapbox/features/public_layout/components/header.tsx +++ b/app/soapbox/features/public_layout/components/header.tsx @@ -1,4 +1,3 @@ -import classNames from 'classnames'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; @@ -6,6 +5,7 @@ import { Link, Redirect } from 'react-router-dom'; import { logIn, verifyCredentials } from 'soapbox/actions/auth'; import { fetchInstance } from 'soapbox/actions/instance'; +import SiteLogo from 'soapbox/components/site-logo'; import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks'; import { openModal } from '../../../actions/modals'; @@ -31,7 +31,6 @@ const Header = () => { const soapboxConfig = useSoapboxConfig(); const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true; - const { logo, logoDarkMode } = soapboxConfig; const features = useFeatures(); const instance = useAppSelector((state) => state.instance); const isOpen = features.accountCreation && instance.registrations; @@ -80,11 +79,7 @@ const Header = () => {
- Logo - {logoDarkMode && ( - Logo - )} - + {intl.formatMessage(messages.home)} diff --git a/app/soapbox/features/ui/components/modals/landing-page-modal.tsx b/app/soapbox/features/ui/components/modals/landing-page-modal.tsx index 583a1a144..c2f7d54d3 100644 --- a/app/soapbox/features/ui/components/modals/landing-page-modal.tsx +++ b/app/soapbox/features/ui/components/modals/landing-page-modal.tsx @@ -2,6 +2,7 @@ import classNames from 'classnames'; import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; +import SiteLogo from 'soapbox/components/site-logo'; import { Button } from 'soapbox/components/ui'; import { Modal } from 'soapbox/components/ui'; import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks'; @@ -23,7 +24,6 @@ const LandingPageModal: React.FC = ({ onClose }) => { const soapboxConfig = useSoapboxConfig(); const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true; - const { logo } = soapboxConfig; const instance = useAppSelector((state) => state.instance); const features = useFeatures(); @@ -32,7 +32,7 @@ const LandingPageModal: React.FC = ({ onClose }) => { return ( } + title={} onClose={() => onClose('LANDING_PAGE')} >
diff --git a/app/soapbox/features/ui/components/navbar.tsx b/app/soapbox/features/ui/components/navbar.tsx index 25085f6d7..7e76e9844 100644 --- a/app/soapbox/features/ui/components/navbar.tsx +++ b/app/soapbox/features/ui/components/navbar.tsx @@ -4,9 +4,10 @@ import { FormattedMessage } from 'react-intl'; import { useDispatch } from 'react-redux'; import { Link } from 'react-router-dom'; -import { Avatar, Button, Icon } from 'soapbox/components/ui'; +import SiteLogo from 'soapbox/components/site-logo'; +import { Avatar, Button } from 'soapbox/components/ui'; import Search from 'soapbox/features/compose/components/search'; -import { useOwnAccount, useSoapboxConfig, useSettings } from 'soapbox/hooks'; +import { useOwnAccount, useSoapboxConfig } from 'soapbox/hooks'; import { openSidebar } from '../../../actions/sidebar'; @@ -17,14 +18,9 @@ const Navbar = () => { const node = React.useRef(null); const account = useOwnAccount(); - const settings = useSettings(); const soapboxConfig = useSoapboxConfig(); const singleUserMode = soapboxConfig.get('singleUserMode'); - // In demo mode, use the Soapbox logo - const logo = settings.get('demo') ? require('images/soapbox-logo.svg') : soapboxConfig.logo; - const logoDarkMode = soapboxConfig.logoDarkMode; - const onOpenSidebar = () => dispatch(openSidebar()); return ( @@ -46,21 +42,10 @@ const Navbar = () => { 'justify-start': !account, })} > - {logo ? ( - - Logo - {logoDarkMode && ( - Logo - )} - - - - ) : ( - - - - - )} + + + + {account && (
diff --git a/app/soapbox/features/verification/waitlist_page.js b/app/soapbox/features/verification/waitlist_page.js index ef2d573ae..606038c56 100644 --- a/app/soapbox/features/verification/waitlist_page.js +++ b/app/soapbox/features/verification/waitlist_page.js @@ -1,11 +1,11 @@ import PropTypes from 'prop-types'; import React from 'react'; import { useIntl } from 'react-intl'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; import { Link } from 'react-router-dom'; -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import LandingGradient from 'soapbox/components/landing-gradient'; +import SiteLogo from 'soapbox/components/site-logo'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { NotificationsContainer } from 'soapbox/features/ui/util/async-components'; @@ -16,8 +16,6 @@ const WaitlistPage = ({ account }) => { const dispatch = useDispatch(); const intl = useIntl(); - const logo = useSelector((state) => getSoapboxConfig(state).get('logo')); - const onClickLogOut = (event) => { event.preventDefault(); dispatch(logOut(intl)); @@ -31,7 +29,7 @@ const WaitlistPage = ({ account }) => {
- Logo +
From 056a5e78472814c1d87b37c4f82452a0432d7c21 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 May 2022 19:56:28 -0500 Subject: [PATCH 4/5] Delete legacy site_logo and site_banner components --- .../public_layout/components/site_banner.js | 25 ------------------- .../public_layout/components/site_logo.js | 25 ------------------- 2 files changed, 50 deletions(-) delete mode 100644 app/soapbox/features/public_layout/components/site_banner.js delete mode 100644 app/soapbox/features/public_layout/components/site_logo.js diff --git a/app/soapbox/features/public_layout/components/site_banner.js b/app/soapbox/features/public_layout/components/site_banner.js deleted file mode 100644 index cdf685a9d..000000000 --- a/app/soapbox/features/public_layout/components/site_banner.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; - -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; - -const mapStateToProps = (state, props) => ({ - instance: state.get('instance'), - soapbox: getSoapboxConfig(state), -}); - -class SiteBanner extends ImmutablePureComponent { - - render() { - const { instance, soapbox } = this.props; - const logos = { - imgLogo: ({instance.get('title')}), - textLogo: (

{instance.get('title')}

), - }; - return soapbox.getIn(['banner']) ? logos.imgLogo : logos.textLogo; - } - -} - -export default connect(mapStateToProps)(SiteBanner); diff --git a/app/soapbox/features/public_layout/components/site_logo.js b/app/soapbox/features/public_layout/components/site_logo.js deleted file mode 100644 index 0ee382e7b..000000000 --- a/app/soapbox/features/public_layout/components/site_logo.js +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { connect } from 'react-redux'; - -import { getSoapboxConfig } from 'soapbox/actions/soapbox'; - -const mapStateToProps = (state, props) => ({ - instance: state.get('instance'), - soapbox: getSoapboxConfig(state), -}); - -class SiteLogo extends ImmutablePureComponent { - - render() { - const { instance, soapbox } = this.props; - const logos = { - imgLogo: ({instance.get('title')}), - textLogo: (

{instance.get('title')}

), - }; - return soapbox.getIn(['logo']) ? logos.imgLogo : logos.textLogo; - } - -} - -export default connect(mapStateToProps)(SiteLogo); From 71e114d0492b91597ea4951e139a9f9a7f8b3b82 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 11 May 2022 20:47:21 -0500 Subject: [PATCH 5/5] SiteLogo: fall back to Soapbox logo instead of Tabler's home.svg --- app/images/soapbox-logo-white.svg | 1 + app/soapbox/components/site-logo.tsx | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 app/images/soapbox-logo-white.svg diff --git a/app/images/soapbox-logo-white.svg b/app/images/soapbox-logo-white.svg new file mode 100644 index 000000000..f09e910ea --- /dev/null +++ b/app/images/soapbox-logo-white.svg @@ -0,0 +1 @@ + diff --git a/app/soapbox/components/site-logo.tsx b/app/soapbox/components/site-logo.tsx index 9e05b2490..8a614d08c 100644 --- a/app/soapbox/components/site-logo.tsx +++ b/app/soapbox/components/site-logo.tsx @@ -11,14 +11,19 @@ const SiteLogo: React.FC> = (props) => { const userTheme = settings.get('themeMode'); const darkMode = userTheme === 'dark' || (userTheme === 'system' && systemTheme === 'dark'); + /** Soapbox logo. */ + const soapboxLogo = darkMode + ? require('images/soapbox-logo-white.svg') + : require('images/soapbox-logo.svg'); + // Use the right logo if provided, then use fallbacks. const getSrc = () => { // In demo mode, use the Soapbox logo. - if (settings.get('demo')) return require('images/soapbox-logo.svg'); + if (settings.get('demo')) return soapboxLogo; return (darkMode && logoDarkMode) ? logoDarkMode - : logo || logoDarkMode || require('@tabler/icons/icons/home.svg'); + : logo || logoDarkMode || soapboxLogo; }; return (