import React, { useState } from "react";
import { BoxProps } from "../box/box";
import { StatusBar, RefreshControl, RefreshControlProps } from "react-native";
import {
KeyboardAwareScrollView,
KeyboardAwareScrollViewProps,
} from "react-native-keyboard-aware-scroll-view";
import { pearl } from "../../../pearl";
import { AtomComponentProps } from "../../../theme/src/types";
import { SafeAreaView, View as MotiView } from "moti";
import { MOTI_PROPS } from "../../../hooks/utils/utils";
import { useTheme } from "../../../hooks/useTheme";
import _ from "lodash";
export type BaseScreenProps = Omit<
BoxProps,
keyof KeyboardAwareScrollViewProps
> &
Omit<
KeyboardAwareScrollViewProps,
| "refresh"
| "scrollEnabled"
| "showsHorizontalScrollIndicator"
| "showsVerticalScrollIndicator"
> & {
/**
* Whether the screen is scrollable
*
* @default true
*/
scrollable?: boolean;
/**
* Whether to show the vertical scrollbar if the Screen is scrollable
*
* @default false
*/
showScrollBar?: boolean;
/** Method to execute when a pull-to-refresh action is performed. Note: `scrollable` should be set as `true` to support pull-to-refresh. */
onPullToRefresh?: Function;
/** The colors (at least one) that will be used to draw the refresh indicator (Android only) */
refreshIndicatorColors?: string[];
/** Progress view top offset */
refreshProgressBackgroundColor?: string;
/** The background color of the refresh indicator */
refreshProgressViewOffset?: number;
/** Size of the refresh indicator (Android only) */
refreshIndicatorSize?: RefreshControlProps["size"];
/** The color of the refresh indicator (iOS only) */
refreshTintColor?: string;
/** The title displayed under the refresh indicator (iOS only) */
refreshTitle?: string;
/** The color of the refresh indicator title (iOS only) */
refreshTitleColor?: string;
};
// TODO: Add Custom Pull-to-Refresh components and animations
/**
* CustomScreen is a functional component that returns a SafeAreaView component with specific styles based on the props.
* It uses the forwardRef function from React to pass the ref to the KeyboardAwareScrollView component.
* @param children The children to render inside the KeyboardAwareScrollView
* @param size The size of the Screen component
* @param variant The variant of the Screen component
* @param scrollable Whether the screen is scrollable
* @param showScrollBar Whether to show the vertical scrollbar if the Screen is scrollable
* @param onPullToRefresh Method to execute when a pull-to-refresh action is performed
* @param refreshIndicatorColors The colors (at least one) that will be used to draw the refresh indicator (Android only)
* @param refreshProgressBackgroundColor Progress view top offset
* @param refreshProgressViewOffset The background color of the refresh indicator
* @param refreshIndicatorSize Size of the refresh indicator (Android only)
* @param refreshTintColor The color of the refresh indicator (iOS only)
* @param refreshTitle The title displayed under the refresh indicator (iOS only)
* @param refreshTitleColor The color of the refresh indicator title (iOS only)
* @returns A SafeAreaView component with a KeyboardAwareScrollView component inside
*/
const CustomScreen = React.memo(
React.forwardRef(
(
{
children,
size,
variant,
scrollable,
showScrollBar,
onPullToRefresh,
refreshIndicatorColors,
refreshProgressBackgroundColor,
refreshProgressViewOffset,
refreshIndicatorSize,
refreshTintColor,
refreshTitle,
refreshTitleColor,
...props
}: AtomComponentProps<"Screen", BaseScreenProps>,
ref: any
) => {
const { colorMode } = useTheme();
const [refreshing, setRefreshing] = useState(false);
const animationProps = _.pick(props, MOTI_PROPS);
const nativeProps = _.omit(props, [...MOTI_PROPS, "style"]);
/**
* Function to execute when a pull-to-refresh action is performed
*/
const onRefresh = React.useCallback(async () => {
if (onPullToRefresh) {
setRefreshing(true);
try {
await onPullToRefresh();
} catch (error) {
console.error(error);
} finally {
setRefreshing(false);
}
}
}, [onPullToRefresh]);
const mainView = scrollable ? (
) : undefined
}
>
{children}
) : (
{children}
);
return (
<>
{mainView}
>
);
}
)
);
/** A layout component that you can use to wrap all the views in your app. */
const Screen = pearl(CustomScreen, {
componentName: "Screen",
type: "atom",
animatable: true,
});
export type ScreenProps = React.ComponentProps;
Screen.displayName = "Screen";
export default Screen;