From 949c2fc3a875db415297ad4c492f746981742add Mon Sep 17 00:00:00 2001 From: Jack Works Date: Sun, 3 Apr 2022 18:51:45 +0800 Subject: [PATCH 1/3] refactor: pick theme refactor from GH-6009 --- packages/mask/src/UIRoot.tsx | 9 +- .../options-page/DashboardDialogs/Base.tsx | 13 +- packages/mask/src/extension/popups/UI.tsx | 6 +- .../popups/components/PopupFrame/index.tsx | 2 +- .../src/extension/popups/pages/Swap/index.tsx | 5 +- .../plugins/ITO/SNSAdaptor/ClaimAllDialog.tsx | 2 +- .../plugins/VCent/SNSAdaptor/TweetDialog.tsx | 2 +- .../SNSAdaptor/RiskWarningDialog/index.tsx | 10 +- .../facebook.com/customization/custom.ts | 2 +- .../minds.com/customization/custom.ts | 2 +- .../twitter.com/customization/custom.ts | 2 +- packages/mask/src/utils/index.ts | 1 - packages/mask/src/utils/theme/MaskTheme.ts | 96 ++++++++ .../{theme-tools.ts => theme/color-tools.ts} | 8 +- packages/mask/src/utils/theme/index.ts | 9 + .../src/utils/{ => theme}/theme-global.d.ts | 0 .../theme/useClassicMaskFullPageTheme.ts | 26 +++ .../src/utils/theme/useClassicMaskSNSTheme.ts | 28 +++ .../mask/src/utils/theme/useColorStyles.ts | 18 ++ .../mask/src/utils/theme/useErrorStyles.ts | 21 ++ .../{theme.ts => theme/useSwapPageTheme.ts} | 205 +----------------- .../mask/src/utils/theme/useThemeLanguage.ts | 28 +++ packages/theme/src/index.ts | 1 + 23 files changed, 267 insertions(+), 229 deletions(-) create mode 100644 packages/mask/src/utils/theme/MaskTheme.ts rename packages/mask/src/utils/{theme-tools.ts => theme/color-tools.ts} (94%) create mode 100644 packages/mask/src/utils/theme/index.ts rename packages/mask/src/utils/{ => theme}/theme-global.d.ts (100%) create mode 100644 packages/mask/src/utils/theme/useClassicMaskFullPageTheme.ts create mode 100644 packages/mask/src/utils/theme/useClassicMaskSNSTheme.ts create mode 100644 packages/mask/src/utils/theme/useColorStyles.ts create mode 100644 packages/mask/src/utils/theme/useErrorStyles.ts rename packages/mask/src/utils/{theme.ts => theme/useSwapPageTheme.ts} (52%) create mode 100644 packages/mask/src/utils/theme/useThemeLanguage.ts diff --git a/packages/mask/src/UIRoot.tsx b/packages/mask/src/UIRoot.tsx index aa9a5f12c085..9a9dc2b98630 100644 --- a/packages/mask/src/UIRoot.tsx +++ b/packages/mask/src/UIRoot.tsx @@ -1,6 +1,6 @@ import { Suspense } from 'react' import { Web3Provider } from '@masknet/web3-shared-evm' -import { CssBaseline, StyledEngineProvider, Theme } from '@mui/material' +import { StyledEngineProvider, Theme } from '@mui/material' import { NetworkPluginID, PluginsWeb3ContextProvider, useAllPluginsWeb3State } from '@masknet/plugin-infra' import { I18NextProviderHMR, SharedContextProvider } from '@masknet/shared' import { ErrorBoundary, ErrorBoundaryBuildInfoContext, useValueRef } from '@masknet/shared-base-ui' @@ -57,10 +57,9 @@ export function MaskUIRoot({ children, kind, useTheme }: MaskUIRootProps) { useMaskIconPalette={useMaskIconPalette} CustomSnackbarOffsetY={isFacebook(activatedSocialNetworkUI) ? 80 : undefined} useTheme={useTheme} - baseline={kind === 'page'}> - - {jsx} - + baseline={kind === 'page'} + children={jsx} + /> ), (jsx) => {jsx}, ) diff --git a/packages/mask/src/extension/options-page/DashboardDialogs/Base.tsx b/packages/mask/src/extension/options-page/DashboardDialogs/Base.tsx index 94633995c73a..57b1986d4599 100644 --- a/packages/mask/src/extension/options-page/DashboardDialogs/Base.tsx +++ b/packages/mask/src/extension/options-page/DashboardDialogs/Base.tsx @@ -10,9 +10,13 @@ import { IconButtonProps, } from '@mui/material' import { makeStyles } from '@masknet/theme' -import { ThemeProvider } from '@mui/material/styles' +import { Theme, ThemeOptions, ThemeProvider } from '@mui/material/styles' import CloseIcon from '@mui/icons-material/Close' -import { extendsTheme, useClassicMaskFullPageTheme, useMatchXS } from '../../../utils' +import { useMatchXS } from '../../../utils' +import { useClassicMaskFullPageTheme } from '../../../utils/theme/useClassicMaskFullPageTheme' +import { appearanceSettings, languageSettings } from '../../../settings/settings' +import { useValueRef } from '@masknet/shared-base-ui' +import { cloneDeep, merge } from 'lodash-unified' const useStyles = makeStyles()((theme) => ({ root: { @@ -101,7 +105,7 @@ export function useModal @@ -160,6 +164,9 @@ const useDashboardDialogWrapperStyles = makeStyles( }, })) +function extendsTheme(extend: (theme: Theme) => ThemeOptions) { + return (theme: Theme) => merge(cloneDeep(theme), extend(theme)) +} const dialogTheme = extendsTheme((theme) => ({ components: { MuiOutlinedInput: { diff --git a/packages/mask/src/extension/popups/UI.tsx b/packages/mask/src/extension/popups/UI.tsx index c50ed7a8e8ef..e5fd019066b6 100644 --- a/packages/mask/src/extension/popups/UI.tsx +++ b/packages/mask/src/extension/popups/UI.tsx @@ -2,16 +2,18 @@ import { lazy } from 'react' import { Navigate, Route, Routes, HashRouter } from 'react-router-dom' import { createInjectHooksRenderer, useActivatedPluginsDashboard } from '@masknet/plugin-infra' import { PopupRoutes } from '@masknet/shared-base' -import { useClassicMaskFullPageTheme } from '../../utils' +import { useClassicMaskFullPageTheme } from '../../utils/theme/useClassicMaskFullPageTheme' import '../../social-network-adaptor/browser-action' import { Web3Provider } from '@masknet/web3-shared-evm' import { PopupWeb3Context } from '../../web3/context' import { PopupFrame } from './components/PopupFrame' import { Appearance } from '@masknet/theme' import { MaskUIRoot } from '../../UIRoot' +import { useValueRef } from '@masknet/shared-base-ui' +import { languageSettings } from '../../settings/settings' function useAlwaysLightTheme() { - return useClassicMaskFullPageTheme({ forcePalette: Appearance.light }) + return useClassicMaskFullPageTheme(Appearance.light, useValueRef(languageSettings)) } const Wallet = lazy(() => import('./pages/Wallet')) const Personas = lazy(() => import('./pages/Personas')) diff --git a/packages/mask/src/extension/popups/components/PopupFrame/index.tsx b/packages/mask/src/extension/popups/components/PopupFrame/index.tsx index 21881ee4d917..b33b6f700f59 100644 --- a/packages/mask/src/extension/popups/components/PopupFrame/index.tsx +++ b/packages/mask/src/extension/popups/components/PopupFrame/index.tsx @@ -17,7 +17,7 @@ function GlobalCss() { overflowX: 'hidden', margin: '0 auto !important', maxWidth: '100%', - '-webkit-font-smoothing': 'subpixel-antialiased', + WebkitFontSmoothing: 'subpixel-antialiased', '&::-webkit-scrollbar': { display: 'none', }, diff --git a/packages/mask/src/extension/popups/pages/Swap/index.tsx b/packages/mask/src/extension/popups/pages/Swap/index.tsx index 4adb25540b66..a4475eba395b 100644 --- a/packages/mask/src/extension/popups/pages/Swap/index.tsx +++ b/packages/mask/src/extension/popups/pages/Swap/index.tsx @@ -9,7 +9,8 @@ import { WalletStateBarUI } from '../../components/WalletStateBar' import { SwapBox } from './SwapBox' import { SwapWeb3Context } from '../../../../web3/context' import { PopupRoutes } from '@masknet/shared-base' -import { useI18N, usePopupsMaskFullPageTheme } from '../../../../utils' +import { useI18N } from '../../../../utils' +import { useSwapPageTheme } from '../../../../utils/theme/useSwapPageTheme' import { NetworkPluginID, useReverseAddress } from '@masknet/plugin-infra' import { TargetChainIdContext } from '../../../../plugins/Trader/trader/useTargetChainIdContext' import { AllProviderTradeContext } from '../../../../plugins/Trader/trader/useAllProviderTradeContext' @@ -68,7 +69,7 @@ export default function SwapPage() { const { t } = useI18N() const { classes } = useStyles() const chainId = useChainId() - const theme = usePopupsMaskFullPageTheme() + const theme = useSwapPageTheme() const { value: pendingTransactions = [] } = useRecentTransactions({ status: TransactionStatusType.NOT_DEPEND, }) diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/ClaimAllDialog.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/ClaimAllDialog.tsx index d58a66ae9710..6beab8740f0e 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/ClaimAllDialog.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/ClaimAllDialog.tsx @@ -95,7 +95,7 @@ const useStyles = makeStyles()((theme, props) => { width: '100%', alignItems: 'center', justifyContent: 'space-between', - '-webkit-font-smoothing': 'antialiased', + WebkitFontSmoothing: 'antialiased', fontSize: 14, }, cardHeaderLocked: { diff --git a/packages/mask/src/plugins/VCent/SNSAdaptor/TweetDialog.tsx b/packages/mask/src/plugins/VCent/SNSAdaptor/TweetDialog.tsx index e67ab12d39da..e5d41cb662e7 100644 --- a/packages/mask/src/plugins/VCent/SNSAdaptor/TweetDialog.tsx +++ b/packages/mask/src/plugins/VCent/SNSAdaptor/TweetDialog.tsx @@ -1,7 +1,7 @@ import { first } from 'lodash-unified' import { Button } from '@mui/material' import { makeStyles } from '@masknet/theme' -import { isDarkTheme } from '../../../utils/theme-tools' +import { isDarkTheme } from '../../../utils/theme' import { ETHIcon } from '../icons/ETH' import { VCentIconLight, VCentIconDark } from '../icons/VCent' import { VALUABLES_VCENT_URL } from '../constants' diff --git a/packages/mask/src/plugins/Wallet/SNSAdaptor/RiskWarningDialog/index.tsx b/packages/mask/src/plugins/Wallet/SNSAdaptor/RiskWarningDialog/index.tsx index 0c01a034f884..19b6b54280de 100644 --- a/packages/mask/src/plugins/Wallet/SNSAdaptor/RiskWarningDialog/index.tsx +++ b/packages/mask/src/plugins/Wallet/SNSAdaptor/RiskWarningDialog/index.tsx @@ -50,9 +50,9 @@ const useStyles = makeStyles()((theme) => ({ marginTop: theme.spacing(2), padding: theme.spacing(2), borderRadius: theme.spacing(1), - '&> :first-child': { - paddingBottom: theme.spacing(1), - }, + }, + texts: { + paddingBottom: theme.spacing(1), }, })) @@ -104,10 +104,10 @@ export function WalletRiskWarningDialog() { children={{t('wallet_risk_warning_content')}} /> - + {t('nft_wallet_label')} - + {isMobile ? formatEthereumAddress(account, 5) : account} diff --git a/packages/mask/src/social-network-adaptor/facebook.com/customization/custom.ts b/packages/mask/src/social-network-adaptor/facebook.com/customization/custom.ts index 2d163de13460..2042d879c223 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/customization/custom.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/customization/custom.ts @@ -5,7 +5,7 @@ import { useMemo } from 'react' import { useValueRef } from '@masknet/shared-base-ui' import { SubscriptionFromValueRef } from '@masknet/shared-base' import type { SocialNetworkUI } from '../../../social-network' -import { fromRGB, isDark, shade, toRGB } from '../../../utils/theme-tools' +import { fromRGB, isDark, shade, toRGB } from '../../../utils/theme' const primaryColorRef = new ValueRef(toRGB([29, 161, 242])) const primaryColorContrastColorRef = new ValueRef(toRGB([255, 255, 255])) diff --git a/packages/mask/src/social-network-adaptor/minds.com/customization/custom.ts b/packages/mask/src/social-network-adaptor/minds.com/customization/custom.ts index 71f388a0f0d7..18b2086f0e34 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/customization/custom.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/customization/custom.ts @@ -5,7 +5,7 @@ import { useMemo } from 'react' import { useValueRef } from '@masknet/shared-base-ui' import { SubscriptionFromValueRef } from '@masknet/shared-base' import type { SocialNetworkUI } from '../../../social-network' -import { fromRGB, getBackgroundColor, getForegroundColor, shade, toRGB } from '../../../utils/theme-tools' +import { fromRGB, getBackgroundColor, getForegroundColor, shade, toRGB } from '../../../utils/theme' import { themeListItemSelector } from '../utils/selector' // TODO: get this from DOM. But currently Minds has a single primary color diff --git a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts index 9377d76923ad..e6cff6cc609a 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/customization/custom.ts @@ -5,7 +5,7 @@ import { PaletteMode, Theme, unstable_createMuiStrictModeTheme } from '@mui/mate import produce, { setAutoFreeze } from 'immer' import { useMemo } from 'react' import type { SocialNetworkUI } from '../../../social-network' -import { fromRGB, getBackgroundColor, getForegroundColor, isDark, shade, toRGB } from '../../../utils/theme-tools' +import { fromRGB, getBackgroundColor, getForegroundColor, isDark, shade, toRGB } from '../../../utils/theme' import { isMobileTwitter } from '../utils/isMobile' import { composeAnchorSelector, composeAnchorTextSelector, headingTextSelector } from '../utils/selector' import twitterColorSchema from './twitter-color-schema.json' diff --git a/packages/mask/src/utils/index.ts b/packages/mask/src/utils/index.ts index c6a009552f39..eba2a666feb7 100644 --- a/packages/mask/src/utils/index.ts +++ b/packages/mask/src/utils/index.ts @@ -11,7 +11,6 @@ export * from './i18n-next-ui' export * from './messages' export * from './permissions' export * from './createNormalReactRoot' -export * from './theme-tools' export * from './theme' export * from './utils' export * from './watcher' diff --git a/packages/mask/src/utils/theme/MaskTheme.ts b/packages/mask/src/utils/theme/MaskTheme.ts new file mode 100644 index 000000000000..3aad54159e25 --- /dev/null +++ b/packages/mask/src/utils/theme/MaskTheme.ts @@ -0,0 +1,96 @@ +// ! This file is used during SSR. DO NOT import new files that does not work in SSR + +import { unstable_createMuiStrictModeTheme, type ThemeOptions } from '@mui/material' +import { grey, orange } from '@mui/material/colors' +import { cloneDeep, merge } from 'lodash-unified' + +function getFontFamily(monospace?: boolean) { + // We want to look native. + // Windows has no CJK sans monospace. Accommodate that. + // We only use it for fingerprints anyway so CJK coverage ain't a problem... yet. + const monofont = navigator.platform.startsWith('Win') ? 'Consolas, monospace' : 'monospace' + // https://caniuse.com/font-family-system-ui + // Firefox does NOT support yet it in any form on Windows, but tests indicate that it agrees with Edge in using the UI font for sans-serif: + // Microsoft YaHei on zh-Hans-CN. + return !monospace ? '-apple-system, system-ui, sans-serif' : monofont +} +const base: ThemeOptions = { + palette: { + primary: { main: '#1c68f3' }, + secondary: orange, + text: { hint: 'rgba(0, 0, 0, 0.38)' }, + }, + typography: { + fontFamily: getFontFamily(), + }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 1112, + lg: 1280, + xl: 1920, + }, + }, + components: { + MuiLink: { defaultProps: { underline: 'hover' } }, + MuiButton: { + styleOverrides: { + root: { + textTransform: 'unset', + minWidth: '100px', + }, + }, + defaultProps: { + size: 'small', + disableElevation: true, + }, + }, + MuiTab: { + styleOverrides: { + root: { + textTransform: 'unset', + padding: '0', + // up-sm + '@media screen and (min-width: 600px)': { + minWidth: 160, + }, + }, + }, + }, + MuiDialog: { + styleOverrides: { + paper: { + borderRadius: '12px', + }, + }, + }, + }, +} +const lightThemePatch: Partial = { + palette: { + mode: 'light', + }, +} +const darkThemePatch: Partial = { + palette: { + mode: 'dark', + background: { + paper: grey[900], + }, + }, + components: { + MuiPaper: { + // https://github.com/mui-org/material-ui/pull/25522 + styleOverrides: { root: { backgroundImage: 'unset' } }, + }, + }, +} +const baseTheme = (theme: 'dark' | 'light') => { + if (theme === 'light') return merge(cloneDeep(base), lightThemePatch) + return merge(cloneDeep(base), darkThemePatch) +} +/** @deprecated Only use it from useClassicMaskSNSTheme */ +export const MaskLightTheme = unstable_createMuiStrictModeTheme(baseTheme('light')) +/** @deprecated Only use it from useClassicMaskSNSTheme */ +export const MaskDarkTheme = unstable_createMuiStrictModeTheme(baseTheme('dark')) diff --git a/packages/mask/src/utils/theme-tools.ts b/packages/mask/src/utils/theme/color-tools.ts similarity index 94% rename from packages/mask/src/utils/theme-tools.ts rename to packages/mask/src/utils/theme/color-tools.ts index 197f11140ba4..68c7c239196c 100644 --- a/packages/mask/src/utils/theme-tools.ts +++ b/packages/mask/src/utils/theme/color-tools.ts @@ -1,3 +1,5 @@ +import { clamp } from 'lodash-unified' + type RGB = [number, number, number] type RGBA = [number, number, number, number] @@ -19,12 +21,6 @@ export function fromRGB(rgb: string): RGB | undefined { return } -export function clamp(num: number, min: number, max: number) { - if (num < min) return min - if (num > max) return max - return num -} - export function shade(channels: RGB, percentage: number): RGB { return channels.map((c) => clamp(Math.floor((c * (100 + percentage)) / 100), 0, 255)) as RGB } diff --git a/packages/mask/src/utils/theme/index.ts b/packages/mask/src/utils/theme/index.ts new file mode 100644 index 000000000000..76a6527c393c --- /dev/null +++ b/packages/mask/src/utils/theme/index.ts @@ -0,0 +1,9 @@ +import './theme-global.d' + +// Do not export more files. Those files are deprecated. +export * from './color-tools' +export * from './MaskTheme' +export * from './useColorStyles' +export * from './useErrorStyles' +export * from './useThemeLanguage' +export * from './useClassicMaskSNSTheme' diff --git a/packages/mask/src/utils/theme-global.d.ts b/packages/mask/src/utils/theme/theme-global.d.ts similarity index 100% rename from packages/mask/src/utils/theme-global.d.ts rename to packages/mask/src/utils/theme/theme-global.d.ts diff --git a/packages/mask/src/utils/theme/useClassicMaskFullPageTheme.ts b/packages/mask/src/utils/theme/useClassicMaskFullPageTheme.ts new file mode 100644 index 000000000000..8a0da1724299 --- /dev/null +++ b/packages/mask/src/utils/theme/useClassicMaskFullPageTheme.ts @@ -0,0 +1,26 @@ +// ! This file is used during SSR. DO NOT import new files that does not work in SSR + +import type { LanguageOptions } from '@masknet/public-api' +import { Appearance } from '@masknet/theme' +import { PaletteMode, unstable_createMuiStrictModeTheme } from '@mui/material' +import { MaskDarkTheme, MaskLightTheme } from './MaskTheme' +import { useThemeLanguage } from './useThemeLanguage' + +/** + * @deprecated Should migrate to \@masknet/theme + */ +export function useClassicMaskFullPageTheme(userPreference: Appearance, language: LanguageOptions) { + const systemPreference: PaletteMode = + 'matchMedia' in globalThis ? (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : 'light' + const finalPalette: PaletteMode = userPreference === Appearance.default ? systemPreference : userPreference + + const baseTheme = finalPalette === 'dark' ? MaskDarkTheme : MaskLightTheme + return unstable_createMuiStrictModeTheme(baseTheme, useThemeLanguage(language)) +} + +/** + * @deprecated Should migrate to \@masknet/theme + */ +export function usePopupFullPageTheme(language: LanguageOptions) { + return useClassicMaskFullPageTheme(Appearance.light, language) +} diff --git a/packages/mask/src/utils/theme/useClassicMaskSNSTheme.ts b/packages/mask/src/utils/theme/useClassicMaskSNSTheme.ts new file mode 100644 index 000000000000..e8f23320ff84 --- /dev/null +++ b/packages/mask/src/utils/theme/useClassicMaskSNSTheme.ts @@ -0,0 +1,28 @@ +import { unstable_createMuiStrictModeTheme } from '@mui/material' +import type { Theme } from '@mui/material/styles/createTheme' +import { useRef } from 'react' +import { activatedSocialNetworkUI } from '../../social-network' +import { useSubscription } from 'use-subscription' +import { MaskDarkTheme, MaskLightTheme } from './MaskTheme' +import { useThemeLanguage } from './useThemeLanguage' +import { SubscriptionFromValueRef } from '@masknet/shared-base' +import { ValueRef } from '@dimensiondev/holoflows-kit' +import { useValueRef } from '@masknet/shared-base-ui' +import { languageSettings } from '../../settings/settings' + +const staticRef = SubscriptionFromValueRef(new ValueRef('light')) +const defaultUseTheme = (t: Theme) => t +/** + * @deprecated Should migrate to \@masknet/theme + */ +export function useClassicMaskSNSTheme() { + const provider = useRef(activatedSocialNetworkUI.customization.paletteMode?.current || staticRef).current + const usePostTheme = useRef(activatedSocialNetworkUI.customization.useTheme || defaultUseTheme).current + const palette = useSubscription(provider) + const baseTheme = palette === 'dark' ? MaskDarkTheme : MaskLightTheme + + // TODO: support RTL? + const [localization, isRTL] = useThemeLanguage(useValueRef(languageSettings)) + const theme = unstable_createMuiStrictModeTheme(baseTheme, localization) + return usePostTheme(theme) +} diff --git a/packages/mask/src/utils/theme/useColorStyles.ts b/packages/mask/src/utils/theme/useColorStyles.ts new file mode 100644 index 000000000000..1d0d1e1ea458 --- /dev/null +++ b/packages/mask/src/utils/theme/useColorStyles.ts @@ -0,0 +1,18 @@ +import { makeStyles } from '@masknet/theme' +import { blue, green, red } from '@mui/material/colors' +import type { MaskDarkTheme } from './MaskTheme' + +export const useColorStyles = makeStyles()((theme: typeof MaskDarkTheme) => { + const dark = theme.palette.mode === 'dark' + return { + error: { + color: dark ? red[500] : red[900], + }, + success: { + color: dark ? green[500] : green[800], + }, + info: { + color: dark ? blue[500] : blue[800], + }, + } +}) diff --git a/packages/mask/src/utils/theme/useErrorStyles.ts b/packages/mask/src/utils/theme/useErrorStyles.ts new file mode 100644 index 000000000000..23734f2110af --- /dev/null +++ b/packages/mask/src/utils/theme/useErrorStyles.ts @@ -0,0 +1,21 @@ +import { makeStyles } from '@masknet/theme' +import { red } from '@mui/material/colors' + +export const useErrorStyles = makeStyles()((theme) => { + const dark = theme.palette.mode === 'dark' + return { + containedPrimary: { + backgroundColor: dark ? red[500] : red[900], + '&:hover': { + backgroundColor: dark ? red[900] : red[700], + }, + }, + outlinedPrimary: { + borderColor: dark ? red[500] : red[900], + color: dark ? red[500] : red[900], + '&:hover': { + borderColor: dark ? red[900] : red[700], + }, + }, + } +}) diff --git a/packages/mask/src/utils/theme.ts b/packages/mask/src/utils/theme/useSwapPageTheme.ts similarity index 52% rename from packages/mask/src/utils/theme.ts rename to packages/mask/src/utils/theme/useSwapPageTheme.ts index 3baa14bdc2ab..f03e10a0f54a 100644 --- a/packages/mask/src/utils/theme.ts +++ b/packages/mask/src/utils/theme/useSwapPageTheme.ts @@ -1,149 +1,13 @@ -import { ValueRef } from '@dimensiondev/holoflows-kit' -import { useValueRef } from '@masknet/shared-base-ui' -import { SubscriptionFromValueRef } from '@masknet/shared-base' -import { Appearance, or, makeStyles, parseColor } from '@masknet/theme' -import { LanguageOptions, SupportedLanguages } from '@masknet/public-api' -import { PaletteMode, unstable_createMuiStrictModeTheme } from '@mui/material' -import { blue, green, grey, orange, red } from '@mui/material/colors' -import { jaJP, koKR, zhTW, zhCN, enUS, Localization } from '@mui/material/locale/index' -import type { Theme, ThemeOptions } from '@mui/material/styles/createTheme' -import { cloneDeep, merge } from 'lodash-unified' -import { useRef } from 'react' -import { appearanceSettings, languageSettings } from '../settings/settings' -import { activatedSocialNetworkUI } from '../social-network' -import './theme-global.d' -import { Subscription, useSubscription } from 'use-subscription' +import { parseColor } from '@masknet/theme' +import { unstable_createMuiStrictModeTheme } from '@mui/material' import produce, { setAutoFreeze } from 'immer' -import twitterColorSchema from '../social-network-adaptor/twitter.com/customization/twitter-color-schema.json' - -function getFontFamily(monospace?: boolean) { - // We want to look native. - - // Windows has no CJK sans monospace. Accommodate that. - // We only use it for fingerprints anyway so CJK coverage ain't a problem... yet. - const monofont = navigator.platform.startsWith('Win') ? 'Consolas, monospace' : 'monospace' - // https://caniuse.com/font-family-system-ui - // Firefox does NOT support yet it in any form on Windows, but tests indicate that it agrees with Edge in using the UI font for sans-serif: - // Microsoft YaHei on zh-Hans-CN. - return !monospace ? '-apple-system, system-ui, sans-serif' : monofont -} - -const base: ThemeOptions = { - palette: { - primary: { main: '#1c68f3' }, // blue, - secondary: orange, - text: { hint: 'rgba(0, 0, 0, 0.38)' }, - }, - typography: { - fontFamily: getFontFamily(), - }, - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 1112, - lg: 1280, - xl: 1920, - }, - }, - components: { - MuiLink: { defaultProps: { underline: 'hover' } }, - MuiButton: { - styleOverrides: { - root: { - textTransform: 'unset', - minWidth: '100px', - }, - }, - defaultProps: { - size: 'small', - disableElevation: true, - }, - }, - MuiTab: { - styleOverrides: { - root: { - textTransform: 'unset', - padding: '0', - // up-sm - '@media screen and (min-width: 600px)': { - minWidth: 160, - }, - }, - }, - }, - MuiDialog: { - styleOverrides: { - paper: { - borderRadius: '12px', - }, - }, - }, - }, -} - -const lightThemePatch: Partial = { - palette: { - mode: 'light', - }, -} - -const darkThemePatch: Partial = { - palette: { - mode: 'dark', - background: { - paper: grey[900], - }, - }, - components: { - MuiPaper: { - // https://github.com/mui-org/material-ui/pull/25522 - styleOverrides: { root: { backgroundImage: 'unset' } }, - }, - }, -} - -const baseTheme = (theme: 'dark' | 'light') => { - if (theme === 'light') return merge(cloneDeep(base), lightThemePatch) - return merge(cloneDeep(base), darkThemePatch) -} - -// Theme -const MaskLightTheme = unstable_createMuiStrictModeTheme(baseTheme('light')) -const MaskDarkTheme = unstable_createMuiStrictModeTheme(baseTheme('dark')) -const staticSubscription: Subscription = SubscriptionFromValueRef(new ValueRef('light')) -export function useClassicMaskSNSTheme() { - const { current: provider } = useRef( - activatedSocialNetworkUI.customization.paletteMode?.current || staticSubscription, - ) - const { current: usePostTheme = (t: Theme) => t } = useRef(activatedSocialNetworkUI.customization.useTheme) - const palette = useSubscription(provider) - const baseTheme = palette === 'dark' ? MaskDarkTheme : MaskLightTheme - - // TODO: support RTL? - const [localization, isRTL] = useThemeLanguage() - const theme = unstable_createMuiStrictModeTheme(baseTheme, localization) - return usePostTheme(theme) -} -/** - * @deprecated - * - Popups: migrate to \@masknet/theme package - */ -export function useClassicMaskFullPageTheme(overwrite?: ClassicMaskFullPageThemeOptions) { - const userPreference = or(overwrite?.forcePalette, useValueRef(appearanceSettings)) - const systemPreference: PaletteMode = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' - const finalPalette: PaletteMode = userPreference === Appearance.default ? systemPreference : userPreference - - const baseTheme = finalPalette === 'dark' ? MaskDarkTheme : MaskLightTheme - const [localization, isRTL] = useThemeLanguage() - // TODO: support RTL - return unstable_createMuiStrictModeTheme(baseTheme, localization) -} +import twitterColorSchema from '../../social-network-adaptor/twitter.com/customization/twitter-color-schema.json' +import { MaskLightTheme } from './MaskTheme' /** - * Only used in swap pages under popups, will replace it in the future + * @deprecated Should migrate to \@masknet/theme */ -export function usePopupsMaskFullPageTheme() { +export function useSwapPageTheme() { const baseTheme = MaskLightTheme setAutoFreeze(false) @@ -348,60 +212,3 @@ export function usePopupsMaskFullPageTheme() { }) return unstable_createMuiStrictModeTheme(PopupTheme) } - -function useThemeLanguage(): [loc: Localization, RTL: boolean] { - let language = useValueRef(languageSettings) - // TODO: support auto language - if (language === LanguageOptions.__auto__) language = LanguageOptions.enUS - - const displayLanguage = language as any as SupportedLanguages - - const langs: Record = { - [SupportedLanguages.enUS]: enUS, - [SupportedLanguages.jaJP]: jaJP, - [SupportedLanguages.koKR]: koKR, - [SupportedLanguages.zhTW]: zhTW, - [SupportedLanguages.zhCN]: zhCN, - } - return [langs[displayLanguage] || enUS, false] -} - -export interface ClassicMaskFullPageThemeOptions { - forcePalette?: Appearance -} - -export const useColorStyles = makeStyles()((theme: typeof MaskDarkTheme) => { - const dark = theme.palette.mode === 'dark' - return { - error: { - color: dark ? red[500] : red[900], - }, - success: { - color: dark ? green[500] : green[800], - }, - info: { - color: dark ? blue[500] : blue[800], - }, - } -}) -export const useErrorStyles = makeStyles()((theme) => { - const dark = theme.palette.mode === 'dark' - return { - containedPrimary: { - backgroundColor: dark ? red[500] : red[900], - '&:hover': { - backgroundColor: dark ? red[900] : red[700], - }, - }, - outlinedPrimary: { - borderColor: dark ? red[500] : red[900], - color: dark ? red[500] : red[900], - '&:hover': { - borderColor: dark ? red[900] : red[700], - }, - }, - } -}) -export function extendsTheme(extend: (theme: Theme) => ThemeOptions) { - return (theme: Theme) => merge(cloneDeep(theme), extend(theme)) -} diff --git a/packages/mask/src/utils/theme/useThemeLanguage.ts b/packages/mask/src/utils/theme/useThemeLanguage.ts new file mode 100644 index 000000000000..841c44fbcf6e --- /dev/null +++ b/packages/mask/src/utils/theme/useThemeLanguage.ts @@ -0,0 +1,28 @@ +// ! This file is used during SSR. DO NOT import new files that does not work in SSR + +import { LanguageOptions, SupportedLanguages } from '@masknet/public-api' +import { jaJP, koKR, zhTW, zhCN, enUS, Localization } from '@mui/material/locale/index' +import { updateLanguage } from '@masknet/shared-base' +import { startTransition, useEffect } from 'react' + +const langs: Record = { + [SupportedLanguages.enUS]: enUS, + [SupportedLanguages.jaJP]: jaJP, + [SupportedLanguages.koKR]: koKR, + [SupportedLanguages.zhTW]: zhTW, + [SupportedLanguages.zhCN]: zhCN, +} +export function useThemeLanguage(language: LanguageOptions): [loc: Localization, RTL: boolean] { + useEffect(() => { + if (language !== LanguageOptions.__auto__) return + startTransition(() => updateLanguage(language)) + }, [language]) + + if (language === LanguageOptions.__auto__) { + // we've scheduled an update above. + language = LanguageOptions.enUS + } + + const displayLanguage = language as any as SupportedLanguages + return [langs[displayLanguage] || enUS, false] +} diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts index 3af80710f206..2764905d6304 100644 --- a/packages/theme/src/index.ts +++ b/packages/theme/src/index.ts @@ -47,6 +47,7 @@ export * from './UIHelper/custom-ui-helper' export * from './CSSVariableInjector' export { getMaskColor, useMaskColor, MaskColorVar, applyMaskColorVars } from './constants' export type { MaskCSSVariableColor } from './constants' +export { TssCacheProvider } from 'tss-react' const query = '(prefers-color-scheme: dark)' export function useSystemPreferencePalette(): PaletteMode { From b3ef01bd0a7abd4c942dc9633c3ef4cf4706369e Mon Sep 17 00:00:00 2001 From: Jack Works Date: Sun, 3 Apr 2022 18:55:32 +0800 Subject: [PATCH 2/3] chore: always use baseline --- packages/mask/src/UIRoot.tsx | 1 - packages/theme/src/ThemeProvider.tsx | 18 +++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/mask/src/UIRoot.tsx b/packages/mask/src/UIRoot.tsx index 9a9dc2b98630..caa45b96d77f 100644 --- a/packages/mask/src/UIRoot.tsx +++ b/packages/mask/src/UIRoot.tsx @@ -57,7 +57,6 @@ export function MaskUIRoot({ children, kind, useTheme }: MaskUIRootProps) { useMaskIconPalette={useMaskIconPalette} CustomSnackbarOffsetY={isFacebook(activatedSocialNetworkUI) ? 80 : undefined} useTheme={useTheme} - baseline={kind === 'page'} children={jsx} /> ), diff --git a/packages/theme/src/ThemeProvider.tsx b/packages/theme/src/ThemeProvider.tsx index ad93110993a8..ef7664dd5744 100644 --- a/packages/theme/src/ThemeProvider.tsx +++ b/packages/theme/src/ThemeProvider.tsx @@ -5,16 +5,14 @@ import { CustomSnackbarProvider } from './Components/Snackbar' function compose(init: React.ReactNode, ...f: ((children: React.ReactNode) => JSX.Element)[]) { return f.reduceRight((prev, curr) => curr(prev), <>{init}) } -const identity = (jsx: React.ReactNode) => jsx as JSX.Element export interface MaskThemeProvider extends React.PropsWithChildren<{}> { - baseline: boolean useTheme(): Theme useMaskIconPalette(theme: Theme): MaskIconPalette CustomSnackbarOffsetY?: number } export function MaskThemeProvider(props: MaskThemeProvider) { - const { children, baseline, useTheme, useMaskIconPalette, CustomSnackbarOffsetY } = props + const { children, useTheme, useMaskIconPalette, CustomSnackbarOffsetY } = props const theme = useTheme() const MaskIconPalette = useMaskIconPalette(theme) @@ -30,13 +28,11 @@ export function MaskThemeProvider(props: MaskThemeProvider) { offsetY={CustomSnackbarOffsetY} /> ), - baseline - ? (jsx) => ( - <> - - {jsx} - - ) - : identity, + (jsx) => ( + <> + + {jsx} + + ), ) } From 908168db01547809742c5611ba0097a30dd11ec0 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Sun, 3 Apr 2022 18:57:43 +0800 Subject: [PATCH 3/3] chore: use popup theme --- packages/mask/src/extension/popups/UI.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/mask/src/extension/popups/UI.tsx b/packages/mask/src/extension/popups/UI.tsx index e5fd019066b6..9e5993fe12c9 100644 --- a/packages/mask/src/extension/popups/UI.tsx +++ b/packages/mask/src/extension/popups/UI.tsx @@ -2,18 +2,17 @@ import { lazy } from 'react' import { Navigate, Route, Routes, HashRouter } from 'react-router-dom' import { createInjectHooksRenderer, useActivatedPluginsDashboard } from '@masknet/plugin-infra' import { PopupRoutes } from '@masknet/shared-base' -import { useClassicMaskFullPageTheme } from '../../utils/theme/useClassicMaskFullPageTheme' +import { usePopupFullPageTheme } from '../../utils/theme/useClassicMaskFullPageTheme' import '../../social-network-adaptor/browser-action' import { Web3Provider } from '@masknet/web3-shared-evm' import { PopupWeb3Context } from '../../web3/context' import { PopupFrame } from './components/PopupFrame' -import { Appearance } from '@masknet/theme' import { MaskUIRoot } from '../../UIRoot' import { useValueRef } from '@masknet/shared-base-ui' import { languageSettings } from '../../settings/settings' -function useAlwaysLightTheme() { - return useClassicMaskFullPageTheme(Appearance.light, useValueRef(languageSettings)) +function usePopupTheme() { + return usePopupFullPageTheme(useValueRef(languageSettings)) } const Wallet = lazy(() => import('./pages/Wallet')) const Personas = lazy(() => import('./pages/Personas')) @@ -26,7 +25,7 @@ const PluginRender = createInjectHooksRenderer(useActivatedPluginsDashboard, (x) export default function Popups() { return ( - +