src/components/loader.tsx (79 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import React, {useMemo} from 'react';
import {View, ActivityIndicator, ViewStyle, ScaledSize} from 'react-native';
import {Text} from './typography';
import {Theme} from '@react-navigation/native';
import {Button, Overlay} from '@rneui/themed';
import {useScreenDimensions, useTheme} from 'hooks';
import {StyleDefinition} from 'types';
type ILoaderButton = {
text: string;
onPress: () => void | Promise<void>;
};
interface ILoaderProps {
message: string;
buttons?: ILoaderButton[];
visible: boolean;
modal?: boolean;
style?: ViewStyle;
}
export function Loader(props: ILoaderProps) {
const {colors, dark} = useTheme();
const {screen} = useScreenDimensions();
const {visible, modal, style} = props;
const overlayStyle = [
...[style],
{
padding: 0,
borderRadius: 20,
backgroundColor: colors.card,
width: screen.width / 1.5,
},
];
const backdropStyle = {backgroundColor: colors.background};
if (!visible) {
return null;
}
if (modal) {
return (
<Overlay
isVisible={visible}
overlayStyle={overlayStyle}
backdropStyle={backdropStyle}>
<InnerLoader colors={colors} dark={dark} {...props} {...screen} />
</Overlay>
);
}
return <InnerLoader colors={colors} dark={dark} {...props} {...screen} />;
}
const InnerLoader = React.memo<ILoaderProps & Theme & ScaledSize>(
({message, buttons, height, colors, style}) => {
const styles = useMemo<StyleDefinition>(
() => ({
body: {height: height / 4, padding: 0, backgroundColor: colors.card},
box: {flex: 2, justifyContent: 'center', alignItems: 'center'},
message: {marginTop: 20},
buttonsBox: {flex: 1, justifyContent: 'flex-end', margin: 0},
button: {paddingVertical: 10},
}),
[height, colors.card],
);
return (
<View style={[...[style], styles.body]}>
<View style={styles.box}>
<ActivityIndicator animating={true} size={40} color={colors.text} />
<Text style={styles.message}>{message}</Text>
</View>
{buttons && buttons.length > 0 && (
<View style={styles.buttonsBox}>
{buttons.map(b => (
<Button
key={b.text}
type="clear"
title={b.text}
onPress={b.onPress}
style={styles.button}
/>
))}
</View>
)}
</View>
);
},
);