Add fontScale, gate it, fix some computes

This commit is contained in:
Eric Bailey
2024-09-13 17:55:15 -05:00
parent 78a531f5ff
commit d5b62f21f5
8 changed files with 148 additions and 110 deletions
+38 -43
View File
@@ -107,51 +107,46 @@ function InnerApp() {
}, [_])
return (
<Alf theme={theme}>
<ThemeProvider theme={theme}>
<Splash isReady={isReady && hasCheckedReferrer}>
<ActiveVideoProvider>
<RootSiblingParent>
<React.Fragment
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<StatsigProvider key={currentAccount?.did}>
<Alf theme={theme}>
<ThemeProvider theme={theme}>
<Splash isReady={isReady && hasCheckedReferrer}>
<ActiveVideoProvider>
<RootSiblingParent>
<QueryProvider currentDid={currentAccount?.did}>
<StatsigProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<ProgressGuideProvider>
<GestureHandlerRootView
style={s.h100pct}>
<TestCtrls />
<Shell />
<NuxDialogs />
</GestureHandlerRootView>
</ProgressGuideProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</StatsigProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<ProgressGuideProvider>
<GestureHandlerRootView style={s.h100pct}>
<TestCtrls />
<Shell />
<NuxDialogs />
</GestureHandlerRootView>
</ProgressGuideProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</QueryProvider>
</React.Fragment>
</RootSiblingParent>
</ActiveVideoProvider>
</Splash>
</ThemeProvider>
</Alf>
</RootSiblingParent>
</ActiveVideoProvider>
</Splash>
</ThemeProvider>
</Alf>
</StatsigProvider>
)
}
+36 -40
View File
@@ -92,48 +92,44 @@ function InnerApp() {
return (
<KeyboardProvider enabled={false}>
<Alf theme={theme}>
<ThemeProvider theme={theme}>
<RootSiblingParent>
<ActiveVideoProvider>
<React.Fragment
// Resets the entire tree below when it changes:
key={currentAccount?.did}>
<StatsigProvider key={currentAccount?.did}>
<Alf theme={theme}>
<ThemeProvider theme={theme}>
<RootSiblingParent>
<ActiveVideoProvider>
<QueryProvider currentDid={currentAccount?.did}>
<StatsigProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<SafeAreaProvider>
<ProgressGuideProvider>
<Shell />
<NuxDialogs />
</ProgressGuideProvider>
</SafeAreaProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</StatsigProvider>
<MessagesProvider>
{/* LabelDefsProvider MUST come before ModerationOptsProvider */}
<LabelDefsProvider>
<ModerationOptsProvider>
<LoggedOutViewProvider>
<SelectedFeedProvider>
<HiddenRepliesProvider>
<UnreadNotifsProvider>
<BackgroundNotificationPreferencesProvider>
<MutedThreadsProvider>
<SafeAreaProvider>
<ProgressGuideProvider>
<Shell />
<NuxDialogs />
</ProgressGuideProvider>
</SafeAreaProvider>
</MutedThreadsProvider>
</BackgroundNotificationPreferencesProvider>
</UnreadNotifsProvider>
</HiddenRepliesProvider>
</SelectedFeedProvider>
</LoggedOutViewProvider>
</ModerationOptsProvider>
</LabelDefsProvider>
</MessagesProvider>
</QueryProvider>
</React.Fragment>
<ToastContainer />
</ActiveVideoProvider>
</RootSiblingParent>
</ThemeProvider>
</Alf>
<ToastContainer />
</ActiveVideoProvider>
</RootSiblingParent>
</ThemeProvider>
</Alf>
</StatsigProvider>
</KeyboardProvider>
)
}
+49 -12
View File
@@ -1,9 +1,11 @@
import React from 'react'
import {useMediaQuery} from 'react-responsive'
import {useGate} from '#/lib/statsig/statsig'
import {createThemes, defaultTheme} from '#/alf/themes'
import {Theme, ThemeName} from '#/alf/types'
import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'
import * as fontScaling from '#/alf/util/fontScaling'
export {atoms} from '#/alf/atoms'
export * as tokens from '#/alf/tokens'
@@ -12,14 +14,21 @@ export * from '#/alf/util/flatten'
export * from '#/alf/util/platform'
export * from '#/alf/util/themeSelector'
/*
* Context
*/
export const Context = React.createContext<{
export type Alf = {
themeName: ThemeName
theme: Theme
themes: ReturnType<typeof createThemes>
}>({
fontScale: number
setFontScale: (fontScale: number) => void
flags: {
neue: boolean
}
}
/*
* Context
*/
export const Context = React.createContext<Alf>({
themeName: 'light',
theme: defaultTheme,
themes: createThemes({
@@ -29,12 +38,27 @@ export const Context = React.createContext<{
positive: GREEN_HUE,
},
}),
fontScale: fontScaling.get(),
setFontScale: () => {},
flags: {
neue: false,
},
})
export function ThemeProvider({
children,
theme: themeName,
}: React.PropsWithChildren<{theme: ThemeName}>) {
const gate = useGate()
const [neue] = React.useState(() => gate('typography_neue'))
const [fontScale, setFontScale] = React.useState(() => fontScaling.get())
const setFontScaleAndPersist = React.useCallback(
(fontScale: number) => {
setFontScale(fontScale)
fontScaling.set(fontScale)
},
[setFontScale],
)
const themes = React.useMemo(() => {
return createThemes({
hues: {
@@ -44,28 +68,41 @@ export function ThemeProvider({
},
})
}, [])
const theme = themes[themeName]
return (
<Context.Provider
value={React.useMemo(
value={React.useMemo<Alf>(
() => ({
themes,
themeName: themeName,
theme: theme,
theme: themes[themeName],
fontScale,
setFontScale: setFontScaleAndPersist,
flags: {
neue,
},
}),
[theme, themeName, themes],
[themeName, themes, fontScale, setFontScaleAndPersist, neue],
)}>
{children}
</Context.Provider>
)
}
export function useAlf() {
return React.useContext(Context)
}
export function useFontScale() {
const {fontScale, setFontScale} = useAlf()
return {fontScale, setFontScale}
}
export function useTheme(theme?: ThemeName) {
const ctx = React.useContext(Context)
const alf = useAlf()
return React.useMemo(() => {
return theme ? ctx.themes[theme] : ctx.theme
}, [theme, ctx])
return theme ? alf.themes[theme] : alf.theme
}, [theme, alf])
}
export function useBreakpoints() {
+10
View File
@@ -0,0 +1,10 @@
import {device} from '#/storage'
export function set(fontScale: number) {
device.set(['fontScale'], fontScale)
}
export function get() {
const fontScale = device.get(['fontScale']) || 1
return fontScale
}
+2 -10
View File
@@ -7,7 +7,6 @@ import {
PressableProps,
StyleProp,
StyleSheet,
Text,
TextProps,
TextStyle,
View,
@@ -17,7 +16,7 @@ import {LinearGradient} from 'expo-linear-gradient'
import {android, atoms as a, flatten, select, tokens, useTheme} from '#/alf'
import {Props as SVGIconProps} from '#/components/icons/common'
import {normalizeTextStyles} from '#/components/Typography'
import {Text} from '#/components/Typography'
export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'gradient'
export type ButtonColor =
@@ -635,14 +634,7 @@ export function ButtonText({children, style, ...rest}: ButtonTextProps) {
const textStyles = useSharedButtonTextStyles()
return (
<Text
{...rest}
style={normalizeTextStyles([
a.font_bold,
a.text_center,
textStyles,
style,
])}>
<Text {...rest} style={[a.font_bold, a.text_center, textStyles, style]}>
{children}
</Text>
)
+11 -5
View File
@@ -3,7 +3,7 @@ import {StyleProp, TextProps as RNTextProps, TextStyle} from 'react-native'
import {UITextView} from 'react-native-uitextview'
import {isNative} from '#/platform/detection'
import {atoms, flatten, useTheme, web} from '#/alf'
import {atoms, flatten, useAlf, useTheme, web} from '#/alf'
export type TextProps = RNTextProps & {
/**
@@ -34,14 +34,17 @@ export function leading<
* If the `lineHeight` value is > 2, we assume it's an absolute value and
* returns it as-is.
*/
export function normalizeTextStyles(styles: StyleProp<TextStyle>) {
export function normalizeTextStyles(
styles: StyleProp<TextStyle>,
{fontScale}: {fontScale: number},
) {
const s = flatten(styles)
// should always be defined on these components
const fontSize = s.fontSize || atoms.text_md.fontSize
s.fontSize = (s.fontSize || atoms.text_md.fontSize) * fontScale
if (s?.lineHeight) {
if (s.lineHeight !== 0 && s.lineHeight <= 2) {
s.lineHeight = Math.round(fontSize * s.lineHeight)
s.lineHeight = Math.round(s.fontSize * s.lineHeight)
}
} else if (!isNative) {
s.lineHeight = s.fontSize
@@ -54,8 +57,11 @@ export function normalizeTextStyles(styles: StyleProp<TextStyle>) {
* Our main text component. Use this most of the time.
*/
export function Text({style, selectable, ...rest}: TextProps) {
const {fontScale} = useAlf()
const t = useTheme()
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)])
const s = normalizeTextStyles([atoms.text_sm, t.atoms.text, flatten(style)], {
fontScale,
})
return <UITextView selectable={selectable} uiTextView style={s} {...rest} />
}
+1
View File
@@ -1,5 +1,6 @@
export type Gate =
// Keep this alphabetic please.
| 'debug_show_feedcontext'
| 'typography_neue'
| 'suggested_feeds_interstitial'
| 'ten_million_dialog'
+1
View File
@@ -2,5 +2,6 @@
* Device data that's specific to the device and does not vary based account
*/
export type Device = {
fontScale: number | undefined
lastNuxDialog: string | undefined
}