* add ThemeProvider to App.web.tsx * make FlatNavigator use themed color * fix extra padding on top in web * add observer to App.web.tsx to make it react to theme changes * fix TS for useColorSchemeStyle * add dark mode toggle button to web LeftNav * fix index.web.tsx border colors for web * Move the darkmode desktop web toggle to the right nav column --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>zio/stable
parent
05e4e4ff93
commit
f50f07f562
|
@ -6,8 +6,10 @@ import * as analytics from 'lib/analytics'
|
||||||
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
||||||
import {Shell} from './view/shell/index'
|
import {Shell} from './view/shell/index'
|
||||||
import {ToastContainer} from './view/com/util/Toast.web'
|
import {ToastContainer} from './view/com/util/Toast.web'
|
||||||
|
import {ThemeProvider} from 'lib/ThemeContext'
|
||||||
|
import {observer} from 'mobx-react-lite'
|
||||||
|
|
||||||
function App() {
|
const App = observer(() => {
|
||||||
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
|
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
)
|
)
|
||||||
|
@ -27,17 +29,19 @@ function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RootSiblingParent>
|
<ThemeProvider theme={rootStore.shell.darkMode ? 'dark' : 'light'}>
|
||||||
<analytics.Provider>
|
<RootSiblingParent>
|
||||||
<RootStoreProvider value={rootStore}>
|
<analytics.Provider>
|
||||||
<SafeAreaProvider>
|
<RootStoreProvider value={rootStore}>
|
||||||
<Shell />
|
<SafeAreaProvider>
|
||||||
</SafeAreaProvider>
|
<Shell />
|
||||||
<ToastContainer />
|
</SafeAreaProvider>
|
||||||
</RootStoreProvider>
|
<ToastContainer />
|
||||||
</analytics.Provider>
|
</RootStoreProvider>
|
||||||
</RootSiblingParent>
|
</analytics.Provider>
|
||||||
|
</RootSiblingParent>
|
||||||
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
|
|
@ -40,6 +40,7 @@ import {PrivacyPolicyScreen} from './view/screens/PrivacyPolicy'
|
||||||
import {TermsOfServiceScreen} from './view/screens/TermsOfService'
|
import {TermsOfServiceScreen} from './view/screens/TermsOfService'
|
||||||
import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
|
import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
|
||||||
import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy'
|
import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy'
|
||||||
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
|
||||||
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
||||||
|
|
||||||
|
@ -162,6 +163,7 @@ function NotificationsTabNavigator() {
|
||||||
* in a single ("flat") stack.
|
* in a single ("flat") stack.
|
||||||
*/
|
*/
|
||||||
function FlatNavigator() {
|
function FlatNavigator() {
|
||||||
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<Flat.Navigator
|
<Flat.Navigator
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
|
@ -169,7 +171,7 @@ function FlatNavigator() {
|
||||||
fullScreenGestureEnabled: true,
|
fullScreenGestureEnabled: true,
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
animationDuration: 250,
|
animationDuration: 250,
|
||||||
contentStyle: {backgroundColor: 'white'},
|
contentStyle: [pal.view],
|
||||||
}}>
|
}}>
|
||||||
<Flat.Screen name="Home" component={HomeScreen} />
|
<Flat.Screen name="Home" component={HomeScreen} />
|
||||||
<Flat.Screen name="Search" component={SearchScreen} />
|
<Flat.Screen name="Search" component={SearchScreen} />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
|
|
||||||
export function useColorSchemeStyle(lightStyle: any, darkStyle: any) {
|
export function useColorSchemeStyle<T>(lightStyle: T, darkStyle: T) {
|
||||||
const colorScheme = useTheme().colorScheme
|
const colorScheme = useTheme().colorScheme
|
||||||
return colorScheme === 'dark' ? darkStyle : lightStyle
|
return colorScheme === 'dark' ? darkStyle : lightStyle
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {FlatList, View} from 'react-native'
|
import {FlatList, View, Platform} from 'react-native'
|
||||||
import {useFocusEffect, useIsFocused} from '@react-navigation/native'
|
import {useFocusEffect, useIsFocused} from '@react-navigation/native'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import useAppState from 'react-native-appstate-hook'
|
import useAppState from 'react-native-appstate-hook'
|
||||||
|
@ -187,12 +187,11 @@ const FeedPage = observer(
|
||||||
key="default"
|
key="default"
|
||||||
feed={feed}
|
feed={feed}
|
||||||
scrollElRef={scrollElRef}
|
scrollElRef={scrollElRef}
|
||||||
style={s.hContentRegion}
|
|
||||||
showPostFollowBtn
|
showPostFollowBtn
|
||||||
onPressTryAgain={onPressTryAgain}
|
onPressTryAgain={onPressTryAgain}
|
||||||
onScroll={onMainScroll}
|
onScroll={onMainScroll}
|
||||||
renderEmptyState={renderEmptyState}
|
renderEmptyState={renderEmptyState}
|
||||||
headerOffset={HEADER_OFFSET}
|
headerOffset={Platform.OS === 'web' ? 0 : HEADER_OFFSET} // only offset on mobile
|
||||||
/>
|
/>
|
||||||
{feed.hasNewLatest && !feed.isRefreshing && (
|
{feed.hasNewLatest && !feed.isRefreshing && (
|
||||||
<LoadLatestBtn onPress={onPressLoadLatest} label="posts" />
|
<LoadLatestBtn onPress={onPressLoadLatest} label="posts" />
|
||||||
|
|
|
@ -130,7 +130,7 @@ export const DesktopLeftNav = observer(function DesktopLeftNav() {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.leftNav}>
|
<View style={[styles.leftNav, pal.view]}>
|
||||||
{store.session.hasSession && <ProfileCard />}
|
{store.session.hasSession && <ProfileCard />}
|
||||||
<BackBtn />
|
<BackBtn />
|
||||||
<NavItem
|
<NavItem
|
||||||
|
@ -246,6 +246,7 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
backgroundColor: colors.blue3,
|
backgroundColor: colors.blue3,
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
newPostBtnIconWrapper: {
|
newPostBtnIconWrapper: {
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
|
|
|
@ -10,10 +10,18 @@ import {FEEDBACK_FORM_URL} from 'lib/constants'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {pluralize} from 'lib/strings/helpers'
|
import {pluralize} from 'lib/strings/helpers'
|
||||||
|
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||||
|
import {MoonIcon} from 'lib/icons'
|
||||||
|
|
||||||
export const DesktopRightNav = observer(function DesktopRightNav() {
|
export const DesktopRightNav = observer(function DesktopRightNav() {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const mode = useColorSchemeStyle('Light', 'Dark')
|
||||||
|
|
||||||
|
const onDarkmodePress = React.useCallback(() => {
|
||||||
|
store.shell.setDarkMode(!store.shell.darkMode)
|
||||||
|
}, [store])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.rightNav, pal.view]}>
|
<View style={[styles.rightNav, pal.view]}>
|
||||||
{store.session.hasSession && <DesktopSearch />}
|
{store.session.hasSession && <DesktopSearch />}
|
||||||
|
@ -50,6 +58,18 @@ export const DesktopRightNav = observer(function DesktopRightNav() {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<InviteCodes />
|
<InviteCodes />
|
||||||
|
<View>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.darkModeToggle]}
|
||||||
|
onPress={onDarkmodePress}>
|
||||||
|
<View style={[pal.viewLight, styles.darkModeToggleIcon]}>
|
||||||
|
<MoonIcon size={18} style={pal.textLight} />
|
||||||
|
</View>
|
||||||
|
<Text type="sm" style={pal.textLight}>
|
||||||
|
{mode} mode
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -110,4 +130,19 @@ const styles = StyleSheet.create({
|
||||||
inviteCodesIcon: {
|
inviteCodesIcon: {
|
||||||
marginRight: 6,
|
marginRight: 6,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
darkModeToggle: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
marginHorizontal: 12,
|
||||||
|
},
|
||||||
|
darkModeToggleIcon: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: 26,
|
||||||
|
height: 26,
|
||||||
|
borderRadius: 15,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,9 +14,11 @@ import {RoutesContainer, FlatNavigator} from '../../Navigation'
|
||||||
import {DrawerContent} from './Drawer'
|
import {DrawerContent} from './Drawer'
|
||||||
import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries'
|
||||||
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
|
import {BottomBarWeb} from './bottom-bar/BottomBarWeb'
|
||||||
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
|
||||||
const ShellInner = observer(() => {
|
const ShellInner = observer(() => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
|
const pal = usePalette('default')
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isDesktop} = useWebMediaQueries()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -30,8 +32,20 @@ const ShellInner = observer(() => {
|
||||||
<>
|
<>
|
||||||
<DesktopLeftNav />
|
<DesktopLeftNav />
|
||||||
<DesktopRightNav />
|
<DesktopRightNav />
|
||||||
<View style={[styles.viewBorder, styles.viewBorderLeft]} />
|
<View
|
||||||
<View style={[styles.viewBorder, styles.viewBorderRight]} />
|
style={[
|
||||||
|
styles.viewBorder,
|
||||||
|
{borderLeftColor: pal.colors.border},
|
||||||
|
styles.viewBorderLeft,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.viewBorder,
|
||||||
|
{borderLeftColor: pal.colors.border},
|
||||||
|
styles.viewBorderRight,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Composer
|
<Composer
|
||||||
|
@ -81,7 +95,6 @@ const styles = StyleSheet.create({
|
||||||
width: 1,
|
width: 1,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
borderLeftColor: colors.gray2,
|
|
||||||
},
|
},
|
||||||
viewBorderLeft: {
|
viewBorderLeft: {
|
||||||
left: 'calc(50vw - 300px)',
|
left: 'calc(50vw - 300px)',
|
||||||
|
|
Loading…
Reference in New Issue