Skip to content

Instantly share code, notes, and snippets.

@harrisrobin
Created July 5, 2022 07:19
Show Gist options
  • Save harrisrobin/128ee10cf582b037987952e542ae60e7 to your computer and use it in GitHub Desktop.
Save harrisrobin/128ee10cf582b037987952e542ae60e7 to your computer and use it in GitHub Desktop.
import React from "react"
import { KeyboardAvoidingView, Platform } from "react-native"
import { StatusBar } from "expo-status-bar"
import { ScreenProps } from "./screen.props"
import { isNonScrolling, offsets, variants } from "./screen.variants"
import { useAppColorScheme } from "@zaboca/ui/hooks/use-app-color-scheme"
import { useThemeColor } from "@zaboca/ui/hooks/use-theme-color"
import { View } from "@zaboca/ui/view"
import { useSafeAreaInsets } from "@zaboca/ui/dimensions"
import { ScrollView } from "@zaboca/ui/scroll-view"
const isIos = Platform.OS === "ios"
function ScreenWithoutScrolling(props: ScreenProps) {
const insets = useSafeAreaInsets()
const preset = variants.fixed
const { colorScheme } = useAppColorScheme()
const backgroundColor = useThemeColor("background")
const backgroundStyle = props.backgroundColor
? { backgroundColor: props.backgroundColor }
: { backgroundColor: backgroundColor }
const insetStyle = { paddingTop: props.unsafe ? 0 : insets.top }
const footerComponent = props.footerComponent || null
const statusBarStyle =
props.barStyle || colorScheme === "dark" ? "light" : "dark"
return (
<KeyboardAvoidingView
style={[preset.outer, backgroundStyle]}
behavior={isIos ? "padding" : undefined}
keyboardVerticalOffset={offsets[props.keyboardOffset || "none"]}
>
<StatusBar style={statusBarStyle || "auto"} />
<View
sx={{
...props.sx,
}}
// @ts-expect-error TODO(Harirs): figure out how to avoid ThemeUICSSObject conflict with ViewStyle
style={[preset.inner, insetStyle]}
>
{props.children}
<View
sx={{
paddingBottom: insets.bottom,
}}
>
{Boolean(footerComponent) && footerComponent}
</View>
</View>
</KeyboardAvoidingView>
)
}
function ScreenWithScrolling(props: ScreenProps) {
const insets = useSafeAreaInsets()
const preset = variants.scroll
const { colorScheme } = useAppColorScheme()
const backgroundColor = useThemeColor("background")
const backgroundStyle = props.backgroundColor
? { backgroundColor: props.backgroundColor }
: { backgroundColor: backgroundColor }
const insetStyle = { paddingTop: props.unsafe ? 0 : insets.top }
const footerComponent = props.footerComponent || null
const statusBarStyle =
props.barStyle || colorScheme === "dark" ? "light" : "dark"
return (
<KeyboardAvoidingView
style={[preset.outer, backgroundStyle]}
behavior={isIos ? "padding" : undefined}
keyboardVerticalOffset={offsets[props.keyboardOffset || "none"]}
>
<StatusBar style={statusBarStyle || "auto"} />
<View
sx={{
...preset.outer,
...backgroundStyle,
...insetStyle,
}}
>
<ScrollView
ref={props.scrollRef}
sx={{
...preset.outer,
...backgroundStyle,
}}
contentContainerSx={{
...preset.inner,
...props.sx,
}}
keyboardShouldPersistTaps={
props.keyboardShouldPersistTaps || "handled"
}
refreshControl={props.refreshControl}
>
{props.children}
</ScrollView>
<View
sx={{
paddingBottom: insets.bottom,
}}
>
{Boolean(footerComponent) && footerComponent}
</View>
</View>
</KeyboardAvoidingView>
)
}
/**
* The starting component on every screen in the app.
*
* @param props The screen props
*/
export function Screen(props: ScreenProps): JSX.Element {
if (isNonScrolling(props.variant)) {
return <ScreenWithoutScrolling {...props} />
} else {
return <ScreenWithScrolling {...props} />
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment