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