remove useProfileTheme in favour of nesting main provider

This commit is contained in:
Samuel Newman
2024-11-13 16:22:10 +00:00
parent 72ecc4355c
commit 28c764e6ca
10 changed files with 60 additions and 59 deletions
+1 -1
View File
@@ -122,7 +122,7 @@ function InnerApp() {
}, [_]) }, [_])
return ( return (
<Alf theme={theme}> <Alf themeName={theme}>
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<Splash isReady={isReady && hasCheckedReferrer}> <Splash isReady={isReady && hasCheckedReferrer}>
<RootSiblingParent> <RootSiblingParent>
+1 -1
View File
@@ -101,7 +101,7 @@ function InnerApp() {
if (!isReady || !hasCheckedReferrer) return null if (!isReady || !hasCheckedReferrer) return null
return ( return (
<Alf theme={theme}> <Alf themeName={theme}>
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<RootSiblingParent> <RootSiblingParent>
<VideoVolumeProvider> <VideoVolumeProvider>
+12 -3
View File
@@ -63,8 +63,12 @@ export const Context = React.createContext<Alf>({
export function ThemeProvider({ export function ThemeProvider({
children, children,
theme: themeName, themeName,
}: React.PropsWithChildren<{theme: ThemeName}>) { theme,
}: React.PropsWithChildren<{
themeName: ThemeName
theme?: ReturnType<typeof createThemes>
}>) {
const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() => const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() =>
getFontScale(), getFontScale(),
) )
@@ -74,6 +78,7 @@ export function ThemeProvider({
const setFontScaleAndPersist = React.useCallback< const setFontScaleAndPersist = React.useCallback<
Alf['fonts']['setFontScale'] Alf['fonts']['setFontScale']
>( >(
// eslint-disable-next-line @typescript-eslint/no-shadow
fontScale => { fontScale => {
setFontScale(fontScale) setFontScale(fontScale)
persistFontScale(fontScale) persistFontScale(fontScale)
@@ -87,6 +92,7 @@ export function ThemeProvider({
const setFontFamilyAndPersist = React.useCallback< const setFontFamilyAndPersist = React.useCallback<
Alf['fonts']['setFontFamily'] Alf['fonts']['setFontFamily']
>( >(
// eslint-disable-next-line @typescript-eslint/no-shadow
fontFamily => { fontFamily => {
setFontFamily(fontFamily) setFontFamily(fontFamily)
persistFontFamily(fontFamily) persistFontFamily(fontFamily)
@@ -94,6 +100,9 @@ export function ThemeProvider({
[setFontFamily], [setFontFamily],
) )
const themes = React.useMemo(() => { const themes = React.useMemo(() => {
if (theme) {
return theme
}
return createThemes({ return createThemes({
hues: { hues: {
primary: BLUE_HUE, primary: BLUE_HUE,
@@ -101,7 +110,7 @@ export function ThemeProvider({
positive: GREEN_HUE, positive: GREEN_HUE,
}, },
}) })
}, []) }, [theme])
const value = React.useMemo<Alf>( const value = React.useMemo<Alf>(
() => ({ () => ({
@@ -49,6 +49,7 @@ interface Props {
moderationOpts: ModerationOpts moderationOpts: ModerationOpts
hideBackButton?: boolean hideBackButton?: boolean
isPlaceholderProfile?: boolean isPlaceholderProfile?: boolean
backgroundColor: string
} }
let ProfileHeaderLabeler = ({ let ProfileHeaderLabeler = ({
@@ -168,7 +169,8 @@ let ProfileHeaderLabeler = ({
profile={profile} profile={profile}
moderation={moderation} moderation={moderation}
hideBackButton={hideBackButton} hideBackButton={hideBackButton}
isPlaceholderProfile={isPlaceholderProfile}> isPlaceholderProfile={isPlaceholderProfile}
backgroundColor={backgroundColor}>
<View <View
style={[a.px_lg, a.pt_md, a.pb_sm]} style={[a.px_lg, a.pt_md, a.pb_sm]}
pointerEvents={isIOS ? 'auto' : 'box-none'}> pointerEvents={isIOS ? 'auto' : 'box-none'}>
@@ -22,7 +22,6 @@ import {
import {useRequireAuth, useSession} from '#/state/session' import {useRequireAuth, useSession} from '#/state/session'
import {ProfileMenu} from '#/view/com/profile/ProfileMenu' import {ProfileMenu} from '#/view/com/profile/ProfileMenu'
import * as Toast from '#/view/com/util/Toast' import * as Toast from '#/view/com/util/Toast'
import {useProfileTheme} from '#/view/screens/Profile'
import {atoms as a} from '#/alf' import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog' import {useDialogControl} from '#/components/Dialog'
@@ -47,6 +46,7 @@ interface Props {
moderationOpts: ModerationOpts moderationOpts: ModerationOpts
hideBackButton?: boolean hideBackButton?: boolean
isPlaceholderProfile?: boolean isPlaceholderProfile?: boolean
backgroundColor: string
} }
let ProfileHeaderStandard = ({ let ProfileHeaderStandard = ({
@@ -55,6 +55,7 @@ let ProfileHeaderStandard = ({
moderationOpts, moderationOpts,
hideBackButton = false, hideBackButton = false,
isPlaceholderProfile, isPlaceholderProfile,
backgroundColor,
}: Props): React.ReactNode => { }: Props): React.ReactNode => {
const profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> = const profile: Shadow<AppBskyActorDefs.ProfileViewDetailed> =
useProfileShadow(profileUnshadowed) useProfileShadow(profileUnshadowed)
@@ -149,14 +150,13 @@ let ProfileHeaderStandard = ({
[currentAccount, profile], [currentAccount, profile],
) )
const pTheme = useProfileTheme()
return ( return (
<ProfileHeaderShell <ProfileHeaderShell
profile={profile} profile={profile}
moderation={moderation} moderation={moderation}
hideBackButton={hideBackButton} hideBackButton={hideBackButton}
isPlaceholderProfile={isPlaceholderProfile}> isPlaceholderProfile={isPlaceholderProfile}
backgroundColor={backgroundColor}>
<View <View
style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]} style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]}
pointerEvents={isIOS ? 'auto' : 'box-none'}> pointerEvents={isIOS ? 'auto' : 'box-none'}>
@@ -179,8 +179,7 @@ let ProfileHeaderStandard = ({
color="secondary" color="secondary"
variant="solid" variant="solid"
onPress={onPressEditProfile} onPress={onPressEditProfile}
label={_(msg`Edit profile`)} label={_(msg`Edit profile`)}>
style={[{backgroundColor: pTheme.lightPalette.primary_50}]}>
<ButtonText> <ButtonText>
<Trans>Edit Profile</Trans> <Trans>Edit Profile</Trans>
</ButtonText> </ButtonText>
@@ -200,10 +199,7 @@ let ProfileHeaderStandard = ({
label={_(msg`Unblock`)} label={_(msg`Unblock`)}
disabled={!hasSession} disabled={!hasSession}
onPress={() => unblockPromptControl.open()} onPress={() => unblockPromptControl.open()}
style={[ style={[a.rounded_full]}>
a.rounded_full,
{backgroundColor: pTheme.lightPalette.primary_50},
]}>
<ButtonText> <ButtonText>
<Trans context="action">Unblock</Trans> <Trans context="action">Unblock</Trans>
</ButtonText> </ButtonText>
@@ -226,10 +222,7 @@ let ProfileHeaderStandard = ({
onPress={ onPress={
profile.viewer?.following ? onPressUnfollow : onPressFollow profile.viewer?.following ? onPressUnfollow : onPressFollow
} }
style={[ style={[a.rounded_full]}>
a.rounded_full,
{backgroundColor: pTheme.lightPalette.primary_50},
]}>
<ButtonIcon <ButtonIcon
position="left" position="left"
icon={profile.viewer?.following ? Check : Plus} icon={profile.viewer?.following ? Check : Plus}
+4 -12
View File
@@ -19,7 +19,6 @@ import {useSession} from '#/state/session'
import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {UserBanner} from '#/view/com/util/UserBanner' import {UserBanner} from '#/view/com/util/UserBanner'
import {useProfileTheme} from '#/view/screens/Profile'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {LabelsOnMe} from '#/components/moderation/LabelsOnMe' import {LabelsOnMe} from '#/components/moderation/LabelsOnMe'
import {ProfileHeaderAlerts} from '#/components/moderation/ProfileHeaderAlerts' import {ProfileHeaderAlerts} from '#/components/moderation/ProfileHeaderAlerts'
@@ -31,6 +30,7 @@ interface Props {
moderation: ModerationDecision moderation: ModerationDecision
hideBackButton?: boolean hideBackButton?: boolean
isPlaceholderProfile?: boolean isPlaceholderProfile?: boolean
backgroundColor: string
} }
let ProfileHeaderShell = ({ let ProfileHeaderShell = ({
@@ -39,6 +39,7 @@ let ProfileHeaderShell = ({
moderation, moderation,
hideBackButton = false, hideBackButton = false,
isPlaceholderProfile, isPlaceholderProfile,
backgroundColor,
}: React.PropsWithChildren<Props>): React.ReactNode => { }: React.PropsWithChildren<Props>): React.ReactNode => {
const t = useTheme() const t = useTheme()
const {currentAccount} = useSession() const {currentAccount} = useSession()
@@ -97,20 +98,11 @@ let ProfileHeaderShell = ({
[currentAccount, profile], [currentAccount, profile],
) )
const pTheme = useProfileTheme()
const palette = t.name === 'light' ? pTheme.lightPalette : pTheme.darkPalette
return ( return (
<View pointerEvents={isIOS ? 'auto' : 'box-none'}> <View pointerEvents={isIOS ? 'auto' : 'box-none'}>
<LinearGradient <LinearGradient
key={t.name} key={t.name}
colors={[ colors={[t.palette.primary_200, t.palette.primary_200, backgroundColor]}
palette.primary_200,
palette.primary_200,
t.atoms.bg.backgroundColor,
]}
style={{ style={{
position: 'absolute', position: 'absolute',
top: 0, top: 0,
@@ -184,7 +176,7 @@ let ProfileHeaderShell = ({
<View <View
style={[ style={[
t.atoms.bg, t.atoms.bg,
{borderColor: t.atoms.bg.backgroundColor}, {borderColor: t.palette.primary_400},
styles.avi, styles.avi,
profile.associated?.labeler && styles.aviLabeler, profile.associated?.labeler && styles.aviLabeler,
]}> ]}>
+1
View File
@@ -43,6 +43,7 @@ interface Props {
moderationOpts: ModerationOpts moderationOpts: ModerationOpts
hideBackButton?: boolean hideBackButton?: boolean
isPlaceholderProfile?: boolean isPlaceholderProfile?: boolean
backgroundColor: string
} }
let ProfileHeader = (props: Props): React.ReactNode => { let ProfileHeader = (props: Props): React.ReactNode => {
+1 -5
View File
@@ -20,7 +20,6 @@ import {
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {EventStopper} from '#/view/com/util/EventStopper' import {EventStopper} from '#/view/com/util/EventStopper'
import * as Toast from '#/view/com/util/Toast' import * as Toast from '#/view/com/util/Toast'
import {useProfileTheme} from '#/view/screens/Profile'
import {Button, ButtonIcon} from '#/components/Button' import {Button, ButtonIcon} from '#/components/Button'
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox' import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox'
import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid' import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
@@ -168,8 +167,6 @@ let ProfileMenu = ({
reportDialogControl.open() reportDialogControl.open()
}, [reportDialogControl]) }, [reportDialogControl])
const pTheme = useProfileTheme()
return ( return (
<EventStopper onKeyDown={false}> <EventStopper onKeyDown={false}>
<Menu.Root> <Menu.Root>
@@ -184,8 +181,7 @@ let ProfileMenu = ({
variant="solid" variant="solid"
color="secondary" color="secondary"
size="small" size="small"
shape="round" shape="round">
style={{backgroundColor: pTheme.lightPalette.primary_50}}>
<ButtonIcon icon={Ellipsis} size="sm" /> <ButtonIcon icon={Ellipsis} size="sm" />
</Button> </Button>
) )
+27 -19
View File
@@ -44,7 +44,7 @@ import {CenteredView} from '#/view/com/util/Views'
import {ProfileHeader, ProfileHeaderLoading} from '#/screens/Profile/Header' import {ProfileHeader, ProfileHeaderLoading} from '#/screens/Profile/Header'
import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed' import {ProfileFeedSection} from '#/screens/Profile/Sections/Feed'
import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels' import {ProfileLabelsSection} from '#/screens/Profile/Sections/Labels'
import {Palette, Theme, web} from '#/alf' import {ThemeProvider as Alf, useTheme, web} from '#/alf'
import {createThemes} from '#/alf/themes' import {createThemes} from '#/alf/themes'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {ScreenHider} from '#/components/moderation/ScreenHider' import {ScreenHider} from '#/components/moderation/ScreenHider'
@@ -52,18 +52,6 @@ import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks'
import {navigate} from '#/Navigation' import {navigate} from '#/Navigation'
import {ExpoScrollForwarderView} from '../../../modules/expo-scroll-forwarder' import {ExpoScrollForwarderView} from '../../../modules/expo-scroll-forwarder'
type ThemeType = {
lightPalette: Palette
darkPalette: Palette
dimPalette: Palette
light: Theme
dark: Theme
dim: Theme
}
const ProfileThemeContext = React.createContext<ThemeType>({} as ThemeType)
export const useProfileTheme = () => React.useContext(ProfileThemeContext)
interface SectionRef { interface SectionRef {
scrollToTop: () => void scrollToTop: () => void
} }
@@ -354,18 +342,37 @@ function ProfileScreenLoaded({
// rendering // rendering
// = // =
const [hue, setHue] = React.useState(0)
React.useEffect(() => {
const id = setInterval(() => {
setHue(h => {
const next = h + 1
if (next >= 360) {
return 0
}
return next
})
}, 100)
return () => clearInterval(id)
}, [])
const t = useTheme()
const theme = createThemes({ const theme = createThemes({
hues: { hues: {
primary: 350, primary: hue,
negative: 0, negative: 0,
positive: 0, positive: 0,
}, },
scales: {
// graySaturation: [30, 30, 30, 30, 30, 30, 30, 30, 34, 34, 38, 38, 38, 38],
},
}) })
const renderHeader = () => { const renderHeader = () => {
return ( return (
<ExpoScrollForwarderView scrollViewTag={scrollViewTag}> <ExpoScrollForwarderView scrollViewTag={scrollViewTag}>
<ProfileThemeContext.Provider value={theme}> <Alf themeName={t.name} theme={theme}>
<ProfileHeader <ProfileHeader
profile={profile} profile={profile}
labeler={labelerInfo} labeler={labelerInfo}
@@ -373,8 +380,9 @@ function ProfileScreenLoaded({
moderationOpts={moderationOpts} moderationOpts={moderationOpts}
hideBackButton={hideBackButton} hideBackButton={hideBackButton}
isPlaceholderProfile={showPlaceholder} isPlaceholderProfile={showPlaceholder}
backgroundColor={t.atoms.bg.backgroundColor}
/> />
</ProfileThemeContext.Provider> </Alf>
</ExpoScrollForwarderView> </ExpoScrollForwarderView>
) )
} }
@@ -539,10 +547,10 @@ function useRichText(text: string): [RichTextAPI, boolean] {
let ignore = false let ignore = false
async function resolveRTFacets() { async function resolveRTFacets() {
// new each time // new each time
const resolvedRT = new RichTextAPI({text}) const newRT = new RichTextAPI({text})
await resolvedRT.detectFacets(agent) await newRT.detectFacets(agent)
if (!ignore) { if (!ignore) {
setResolvedRT(resolvedRT) setResolvedRT(newRT)
} }
} }
resolveRTFacets() resolveRTFacets()
+3 -3
View File
@@ -104,13 +104,13 @@ function StorybookInner() {
<Settings /> <Settings />
<ThemeProvider theme="light"> <ThemeProvider themeName="light">
<Theming /> <Theming />
</ThemeProvider> </ThemeProvider>
<ThemeProvider theme="dim"> <ThemeProvider themeName="dim">
<Theming /> <Theming />
</ThemeProvider> </ThemeProvider>
<ThemeProvider theme="dark"> <ThemeProvider themeName="dark">
<Theming /> <Theming />
</ThemeProvider> </ThemeProvider>