From 967f9fc474f2903dd2c12ef4f662ead1592ea26c Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Thu, 9 Jun 2022 21:34:43 -0500 Subject: [PATCH] Add desktop shell --- README.md | 2 - src/platform/desktop-web/left-column.tsx | 57 ++++++++++++++++++ src/platform/desktop-web/right-column.tsx | 19 ++++++ src/platform/desktop-web/shell.tsx | 35 ++++++++++++ src/platform/detection.ts | 11 ++++ src/platform/shell.tsx | 12 ++++ src/routes/index.tsx | 70 ++++++++++++----------- src/routes/types.ts | 40 ++++++++----- src/screens/Home.tsx | 15 ++--- src/screens/Login.tsx | 15 ++--- src/screens/Menu.tsx | 19 +++--- src/screens/NotFound.tsx | 32 ++++------- src/screens/Notifications.tsx | 25 +++----- src/screens/Profile.tsx | 17 ++++-- src/screens/Search.tsx | 23 +++----- src/screens/Signup.tsx | 15 ++--- 16 files changed, 269 insertions(+), 138 deletions(-) create mode 100644 src/platform/desktop-web/left-column.tsx create mode 100644 src/platform/desktop-web/right-column.tsx create mode 100644 src/platform/desktop-web/shell.tsx create mode 100644 src/platform/detection.ts create mode 100644 src/platform/shell.tsx diff --git a/README.md b/README.md index 9627e39e..1ac5ff41 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,6 @@ Uses: ## TODOs -- Web - - Desktop vs mobile styling - API - Create mock api - Tests diff --git a/src/platform/desktop-web/left-column.tsx b/src/platform/desktop-web/left-column.tsx new file mode 100644 index 00000000..082231ec --- /dev/null +++ b/src/platform/desktop-web/left-column.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import {Pressable, View, StyleSheet} from 'react-native' +import {Link} from '@react-navigation/native' +import {useRoute} from '@react-navigation/native' + +export const NavItem: React.FC<{label: string; screen: string}> = ({ + label, + screen, +}) => { + const route = useRoute() + return ( + + [ + // @ts-ignore it does exist! (react-native-web) -prf + state.hovered && styles.navItemHovered, + ]}> + + {label} + + + + ) +} + +export const DesktopLeftColumn: React.FC = () => { + return ( + + + + + + ) +} + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + left: 'calc(50vw - 500px)', + width: '200px', + height: '100%', + }, + navItemHovered: { + backgroundColor: 'gray', + }, + navItemLink: { + padding: '1rem', + }, + navItemLinkSelected: { + color: 'blue', + }, +}) diff --git a/src/platform/desktop-web/right-column.tsx b/src/platform/desktop-web/right-column.tsx new file mode 100644 index 00000000..5fe65cac --- /dev/null +++ b/src/platform/desktop-web/right-column.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import {Text, View, StyleSheet} from 'react-native' + +export const DesktopRightColumn: React.FC = () => { + return ( + + Right Column + + ) +} + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + right: 'calc(50vw - 500px)', + width: '200px', + height: '100%', + }, +}) diff --git a/src/platform/desktop-web/shell.tsx b/src/platform/desktop-web/shell.tsx new file mode 100644 index 00000000..ef880306 --- /dev/null +++ b/src/platform/desktop-web/shell.tsx @@ -0,0 +1,35 @@ +import React from 'react' +import {observer} from 'mobx-react-lite' +import {View, StyleSheet} from 'react-native' +import {DesktopLeftColumn} from './left-column' +import {DesktopRightColumn} from './right-column' +import {useStores} from '../../state' + +export const DesktopWebShell: React.FC = observer(({children}) => { + const store = useStores() + return ( + + {store.session.isAuthed ? ( + <> + + {children} + + + ) : ( + {children} + )} + + ) +}) + +const styles = StyleSheet.create({ + outerContainer: { + height: '100%', + }, + innerContainer: { + marginLeft: 'auto', + marginRight: 'auto', + width: '600px', + height: '100%', + }, +}) diff --git a/src/platform/detection.ts b/src/platform/detection.ts new file mode 100644 index 00000000..5d2ffcb2 --- /dev/null +++ b/src/platform/detection.ts @@ -0,0 +1,11 @@ +import {Platform} from 'react-native' + +export const isIOS = Platform.OS === 'ios' +export const isAndroid = Platform.OS === 'android' +export const isNative = isIOS || isAndroid +export const isWeb = !isNative +export const isMobileWeb = + isWeb && + // @ts-ignore we know window exists -prf + global.window.matchMedia('only screen and (max-width: 1000px)')?.matches +export const isDesktopWeb = isWeb && !isMobileWeb diff --git a/src/platform/shell.tsx b/src/platform/shell.tsx new file mode 100644 index 00000000..ec8d51e1 --- /dev/null +++ b/src/platform/shell.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import {SafeAreaView} from 'react-native' +import {isDesktopWeb} from './detection' +import {DesktopWebShell} from './desktop-web/shell' + +export const Shell: React.FC = ({children}) => { + return isDesktopWeb ? ( + {children} + ) : ( + {children} + ) +} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index fa035e3c..a8a92e54 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -9,8 +9,9 @@ import { import {createNativeStackNavigator} from '@react-navigation/native-stack' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs' import {observer} from 'mobx-react-lite' -import type {RootStackParamList} from './types' +import type {RootTabsParamList} from './types' import {useStores} from '../state' +import * as platform from '../platform/detection' import {Home} from '../screens/Home' import {Search} from '../screens/Search' import {Notifications} from '../screens/Notifications' @@ -20,74 +21,77 @@ import {Login} from '../screens/Login' import {Signup} from '../screens/Signup' import {NotFound} from '../screens/NotFound' -const linking: LinkingOptions = { +const linking: LinkingOptions = { prefixes: [ 'http://localhost:3000', // local dev ], config: { screens: { - Primary: { - screens: { - Home: '', - Search: 'search', - Notifications: 'notifications', - Menu: 'menu', - }, - }, + Home: '', + Profile: 'profile/:name', + Search: 'search', + Notifications: 'notifications', + Menu: 'menu', Login: 'login', Signup: 'signup', - Profile: 'profile/:name', NotFound: '*', }, }, } -export const RootStack = createNativeStackNavigator() -export const PrimaryTab = createBottomTabNavigator() +export const RootTabs = createBottomTabNavigator() +export const PrimaryStack = createNativeStackNavigator() const tabBarScreenOptions = ({ route, }: { route: RouteProp }) => ({ + headerShown: false, tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => { // TODO: icons return {route.name.at(0)} }, }) -function Primary() { - return ( - - - - - - - ) -} +const HIDE_TAB = {tabBarButton: () => null} export const Root = observer(() => { const store = useStores() + + // hide the tabbar on desktop web + const tabBar = platform.isDesktopWeb ? () => null : undefined + return ( Loading...}> - + {store.session.isAuthed ? ( <> - - - + + + + + ) : ( <> - - + + )} - + + ) }) diff --git a/src/routes/types.ts b/src/routes/types.ts index 88148fd4..d92594bb 100644 --- a/src/routes/types.ts +++ b/src/routes/types.ts @@ -1,26 +1,36 @@ -import type {NavigatorScreenParams} from '@react-navigation/native' -import type {CompositeScreenProps} from '@react-navigation/native' import type {StackScreenProps} from '@react-navigation/stack' -import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs' -export type RootStackParamList = { - Primary: undefined +export type RootTabsParamList = { + Home: undefined + Search: undefined + Notifications: undefined + Menu: undefined Profile: {name: string} Login: undefined Signup: undefined NotFound: undefined } -export type RootStackScreenProps = - StackScreenProps +export type RootTabsScreenProps = + StackScreenProps -export type PrimaryTabParamList = { - Home: NavigatorScreenParams - Search: undefined - Notifications: undefined - Menu: undefined +/* +NOTE +this is leftover from a nested nav implementation +keeping it around for future reference +-prf + +import type {NavigatorScreenParams} from '@react-navigation/native' +import type {CompositeScreenProps} from '@react-navigation/native' +import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs' + +Container: NavigatorScreenParams +export type PrimaryStacksParamList = { + Home: undefined + Profile: {name: string} } -export type PrimaryTabScreenProps = +export type PrimaryStacksScreenProps = CompositeScreenProps< - BottomTabScreenProps, - RootStackScreenProps + BottomTabScreenProps, + RootTabsScreenProps > +*/ diff --git a/src/screens/Home.tsx b/src/screens/Home.tsx index a2d013ab..90c9262f 100644 --- a/src/screens/Home.tsx +++ b/src/screens/Home.tsx @@ -1,20 +1,21 @@ import React from 'react' -import {Text, Button, View, SafeAreaView} from 'react-native' -import type {PrimaryTabScreenProps} from '../routes/types' +import {Text, Button, View} from 'react-native' +import {Shell} from '../platform/shell' +import type {RootTabsScreenProps} from '../routes/types' import {useStores} from '../state' -export function Home({navigation}: PrimaryTabScreenProps<'Home'>) { +export function Home({navigation}: RootTabsScreenProps<'Home'>) { const store = useStores() return ( - - - Hello world + + + Home