Restore guest mode

This commit is contained in:
mathysPaul
2023-10-08 19:47:03 +02:00
parent 1228eb603e
commit f610de3045
28 changed files with 855 additions and 1062 deletions
+4 -2
View File
@@ -4,6 +4,8 @@ import InteractiveBase from './InteractiveBase';
import { Text, useTheme } from 'native-base';
import { Icon } from 'iconsax-react-native';
export type ButtonType = 'filled' | 'outlined' | 'menu';
interface ButtonProps {
title?: string;
style?: StyleProp<ViewStyle>;
@@ -12,7 +14,7 @@ interface ButtonProps {
icon?: Icon;
iconVariant?: 'Bold' | 'Outline';
iconImage?: string;
type?: 'filled' | 'outlined' | 'menu';
type?: ButtonType;
}
const ButtonBase: React.FC<ButtonProps> = ({
@@ -128,7 +130,7 @@ const ButtonBase: React.FC<ButtonProps> = ({
/>
)}
{iconImage && <Image source={{ uri: iconImage }} style={styles.icon} />}
{title && <Text style={styles.text}>{title}</Text>}
{title && <Text style={styles.text} selectable={false}>{title}</Text>}
</View>
)}
</InteractiveBase>
+27
View File
@@ -0,0 +1,27 @@
import { BlurView } from 'expo-blur';
import { ReactNode } from 'react';
import React from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import useColorScheme from '../../hooks/colorScheme';
type GlassmorphismCCProps = {
children?: ReactNode,
style?: StyleProp<ViewStyle>;
};
const GlassmorphismCC = ({ children, style }: GlassmorphismCCProps) => {
const colorScheme = useColorScheme();
console.log(colorScheme);
return (
<BlurView
style={[{borderRadius: 12}, style]}
intensity={70}
tint={colorScheme === 'light' ? 'light' : 'dark'}
>
{children}
</BlurView>
);
};
export default GlassmorphismCC;
+64
View File
@@ -0,0 +1,64 @@
import { Text, Row, Heading, Column, Center } from 'native-base';
import ButtonBase, { ButtonType } from './ButtonBase';
import { CloseSquare, LoginCurve, LogoutCurve } from 'iconsax-react-native';
import { useDispatch } from 'react-redux';
import { translate } from '../../i18n/i18n';
import { unsetAccessToken } from '../../state/UserSlice';
import { BlurView } from 'expo-blur';
import { useState } from 'react';
import Modal from "react-native-modal";
import React from 'react';
import SignUpForm from '../../components/forms/signupform';
import API, { APIError } from '../../API';
import PopupCC from './PopupCC';
const handleSubmit = async (username: string, password: string, email: string) => {
try {
await API.transformGuestToUser({ username, password, email });
} catch (error) {
if (error instanceof APIError) return translate(error.userMessage);
if (error instanceof Error) return error.message;
return translate('unknownError');
}
return translate('loggedIn');
};
type LogoutButtonCCProps = {
isGuest?: boolean;
style: any;
buttonType: ButtonType
};
const LogoutButtonCC = ({isGuest = false, buttonType = 'menu', style}: LogoutButtonCCProps) => {
const dispatch = useDispatch();
const [isVisible, setIsVisible] = useState(false);
return (
<>
<ButtonBase
style={style}
icon={LogoutCurve}
title={translate('signOutBtn')}
type={buttonType}
onPress={async () => {isGuest ? setIsVisible(true) : dispatch(unsetAccessToken());}}
/>
<PopupCC
title={translate('Attention')}
description={translate('transformGuestToUserExplanations')}
isVisible={isVisible}
setIsVisible={setIsVisible}
>
<SignUpForm onSubmit={handleSubmit} />
<ButtonBase
style={{width: '100%'}}
type="outlined"
icon={LogoutCurve}
title={translate('signOutBtn')}
onPress={async () => { dispatch(unsetAccessToken()) }}
/>
</PopupCC>
</>
);
};
export default LogoutButtonCC;
+62
View File
@@ -0,0 +1,62 @@
import { Text, Row, Heading, Column } from 'native-base';
import ButtonBase from './ButtonBase';
import { CloseSquare } from 'iconsax-react-native';
import { BlurView } from 'expo-blur';
import { ReactNode } from 'react';
import Modal from "react-native-modal";
import React from 'react';
import GlassmorphismCC from './Glassmorphism';
type PopupCCProps = {
title: string,
description?: string,
children?: ReactNode,
isVisible: boolean,
setIsVisible: (isVisible: boolean) => void,
};
const PopupCC = ({ title, description, children, isVisible, setIsVisible }: PopupCCProps) => {
return (
<Modal
backdropOpacity={0.3}
isVisible={isVisible}
style={{
display: 'flex',
alignContent: 'center',
alignSelf: 'center',
alignItems: 'center'
}}
>
<GlassmorphismCC>
<Column
style={{
maxWidth: '800px',
maxHeight: 'fit-content',
padding: '20px',
}}
space={4}
>
<Heading size="md" mb={2} alignItems={'flex-end'}>
<Row style={{flex: 1, width: '100%', alignItems: 'flex-end'}}>
<Text style={{flex: 1,width: '100%'}}>
{title}
</Text>
<ButtonBase
type='menu'
style={{width: 'fit-content'}}
icon={CloseSquare}
onPress={async () => setIsVisible(false)}
/>
</Row>
</Heading>
{description &&
<Text>{description}</Text>
}
{children}
</Column>
</GlassmorphismCC>
</Modal>
);
};
export default PopupCC;
+92 -42
View File
@@ -1,13 +1,22 @@
import { LinearGradient } from 'expo-linear-gradient';
import { Center, Flex, Stack, View, Text, Wrap, Image } from 'native-base';
import { Flex, Stack, View, Text, Wrap, Image, Row, Column, ScrollView, useToast } from 'native-base';
import { FunctionComponent } from 'react';
import { Linking, useWindowDimensions } from 'react-native';
import ButtonBase from './ButtonBase';
import { translate } from '../../i18n/i18n';
import API from '../../API';
import API, { APIError } from '../../API';
import SeparatorBase from './SeparatorBase';
import LinkBase from './LinkBase';
import ImageBanner from '../../assets/banner.jpg';
import { useDispatch } from '../../state/Store';
import { setAccessToken } from '../../state/UserSlice';
import useColorScheme from '../../hooks/colorScheme';
const handleGuestLogin = async (apiSetter: (accessToken: string) => void): Promise<string> => {
const apiAccess = await API.createAndGetGuestAccount();
apiSetter(apiAccess);
return translate('loggedIn');
};
interface ScaffoldAuthProps {
title: string;
@@ -25,6 +34,12 @@ const ScaffoldAuth: FunctionComponent<ScaffoldAuthProps> = ({
link,
}) => {
const layout = useWindowDimensions();
const dispatch = useDispatch();
const toast = useToast();
const colorScheme = useColorScheme();
const logo = colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png');
return (
<Flex
@@ -32,54 +47,89 @@ const ScaffoldAuth: FunctionComponent<ScaffoldAuthProps> = ({
justifyContent="space-between"
style={{ flex: 1, backgroundColor: '#101014' }}
>
<Center style={{ flex: 1 }}>
<View style={{ width: '100%', maxWidth: 420, padding: 16 }}>
<Stack
space={8}
justifyContent="center"
alignContent="center"
alignItems="center"
style={{ width: '100%', paddingBottom: 40 }}
>
<Text fontSize="4xl" textAlign="center">
{title}
</Text>
<Text fontSize="lg" textAlign="center">
{description}
</Text>
</Stack>
<Stack
space={5}
justifyContent="center"
alignContent="center"
alignItems="center"
style={{ width: '100%' }}
>
<ButtonBase
style={{ width: '100%' }}
type="outlined"
iconImage="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/2008px-Google_%22G%22_Logo.svg.png"
title={translate('continuewithgoogle')}
onPress={() => Linking.openURL(`${API.baseUrl}/auth/login/google`)}
<Column style={{ flex: 1 }}>
<Wrap space={4} direction='row' style={{padding: 16, paddingBottom: 0}}>
<Row space={2} flex={1}>
<Image
source={{ uri: logo }}
style={{
aspectRatio: 1,
width: '32px',
height: '32px',
}}
/>
<SeparatorBase>or</SeparatorBase>
{layout.width > 650 &&
<Text fontSize={'xl'} selectable={false}>
Chromacase
</Text>
}
</Row>
<ButtonBase
title='guest mode'
onPress={async () => {
try {
handleGuestLogin((accessToken: string) => {
dispatch(setAccessToken(accessToken));
});
} catch (error) {
if (error instanceof APIError) {
toast.show({ description: translate(error.userMessage) });
return;
}
toast.show({ description: error as string });
}
}}
/>
</Wrap>
<ScrollView contentContainerStyle={{ padding: 16, flexGrow: 1, justifyContent: 'center', alignSelf: 'center' }}>
<View style={{ width: '100%', maxWidth: 420 }}>
<Stack
space={3}
space={8}
justifyContent="center"
alignContent="center"
alignItems="center"
style={{ width: '100%', paddingBottom: 40 }}
>
<Text fontSize="4xl" textAlign="center">
{title}
</Text>
<Text fontSize="lg" textAlign="center">
{description}
</Text>
</Stack>
<Stack
space={5}
justifyContent="center"
alignContent="center"
alignItems="center"
style={{ width: '100%' }}
>
{form}
<ButtonBase
style={{ width: '100%' }}
type="outlined"
iconImage="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/2008px-Google_%22G%22_Logo.svg.png"
title={translate('continuewithgoogle')}
onPress={() => Linking.openURL(`${API.baseUrl}/auth/login/google`)}
/>
<SeparatorBase>or</SeparatorBase>
<Stack
space={3}
justifyContent="center"
alignContent="center"
alignItems="center"
style={{ width: '100%' }}
>
{form}
</Stack>
{submitButton}
<Wrap style={{ flexDirection: 'row', justifyContent: 'center' }}>
<Text>{link.description}</Text>
<LinkBase onPress={link.onPress}>{link.text}</LinkBase>
</Wrap>
</Stack>
{submitButton}
<Wrap style={{ flexDirection: 'row', justifyContent: 'center' }}>
<Text>{link.description}</Text>
<LinkBase onPress={link.onPress}>{link.text}</LinkBase>
</Wrap>
</Stack>
</View>
</Center>
</View>
</ScrollView>
</Column>
{layout.width > 650 ? (
<View style={{ width: '50%', height: '100%', padding: 16 }}>
<Image
+12 -12
View File
@@ -10,7 +10,6 @@ import {
Cup,
Discover,
Icon,
LogoutCurve,
Music,
SearchNormal1,
Setting2,
@@ -42,9 +41,10 @@ const menu: {
type ScaffoldCCProps = {
children?: React.ReactNode;
routeName: string;
withPadding?: boolean;
};
const ScaffoldCC = (props: ScaffoldCCProps) => {
const ScaffoldCC = ({children, routeName, withPadding = true}: ScaffoldCCProps) => {
const screenSize = useBreakpointValue({ base: 'small', md: 'big' });
const userQuery = useQuery(API.getUserInfo);
@@ -53,19 +53,20 @@ const ScaffoldCC = (props: ScaffoldCCProps) => {
return <LoadingView />;
}
const colorScheme = useColorScheme();
const logo = colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png');
if (screenSize === 'small') {
return (
<ScaffoldMobileCC
user={userQuery.data}
logo={colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png')}
routeName={props.routeName}
logo={logo}
routeName={routeName}
menu={menu}
>
{props.children}
{children}
</ScaffoldMobileCC>
);
}
@@ -73,13 +74,12 @@ const ScaffoldCC = (props: ScaffoldCCProps) => {
return (
<ScaffoldDesktopCC
user={userQuery.data}
logo={colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png')}
routeName={props.routeName}
logo={logo}
routeName={routeName}
menu={menu}
widthPadding={withPadding}
>
{props.children}
{children}
</ScaffoldDesktopCC>
);
};
+9 -59
View File
@@ -1,20 +1,21 @@
import { View, Image } from 'react-native';
import { Divider, Text, ScrollView, Flex, Row, Popover, Heading, Button } from 'native-base';
import { Divider, Text, ScrollView, Flex, Row } from 'native-base';
import { useQuery, useQueries } from '../../Queries';
import API from '../../API';
import Song from '../../models/Song';
import { LinearGradient } from 'expo-linear-gradient';
import ButtonBase from './ButtonBase';
import { Icon, LogoutCurve } from 'iconsax-react-native';
import { useDispatch } from 'react-redux';
import { Icon } from 'iconsax-react-native';
import { LoadingView } from '../Loading';
import { translate } from '../../i18n/i18n';
import { unsetAccessToken } from '../../state/UserSlice';
import { useNavigation } from '../../Navigation';
import Spacer from './Spacer';
import User from '../../models/User';
import LogoutButtonCC from './LogoutButtonCC';
import GlassmorphismCC from './Glassmorphism';
type ScaffoldDesktopCCProps = {
widthPadding: boolean,
children?: React.ReactNode;
user: User;
logo: string;
@@ -30,7 +31,6 @@ type ScaffoldDesktopCCProps = {
const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
const navigation = useNavigation();
const userQuery = useQuery(API.getUserInfo);
const dispatch = useDispatch();
if (!userQuery.data || userQuery.isLoading) {
return <LoadingView />;
@@ -160,75 +160,25 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
/>
))}
<Spacer />
{!props.user.isGuest && (
<ButtonBase
style={{ width: '100%' }}
icon={LogoutCurve}
title={translate('signOutBtn')}
type="menu"
onPress={async () => {
dispatch(unsetAccessToken());
}}
/>
)}
{props.user.isGuest && (
<Popover
trigger={(triggerProps) => (
<ButtonBase {...triggerProps}>
{translate('signOutBtn')}
</ButtonBase>
)}
>
<Popover.Content>
<Popover.Arrow />
<Popover.Body>
<Heading size="md" mb={2}>
{translate('Attention')}
</Heading>
<Text>
{translate(
'YouAreCurrentlyConnectedWithAGuestAccountWarning'
)}
</Text>
<Button.Group variant="ghost" space={2}>
<Button
onPress={() => dispatch(unsetAccessToken())}
colorScheme="red"
>
{translate('signOutBtn')}
</Button>
<Button
onPress={() => {
navigation.navigate('Login');
}}
colorScheme="green"
>
{translate('signUpBtn')}
</Button>
</Button.Group>
</Popover.Body>
</Popover.Content>
</Popover>
)}
<LogoutButtonCC isGuest={props.user.isGuest} style={{with: '100%'}} buttonType={'menu'}/>
</View>
</View>
<ScrollView
style={{ flex: 1, maxHeight: '100vh' }}
contentContainerStyle={{ flex: 1 }}
>
<View
<GlassmorphismCC
style={{
backgroundColor: 'rgba(16,16,20,0.5)',
flex: 1,
margin: 8,
padding: 20,
padding: props.widthPadding ? 20 : 0,
borderRadius: 12,
minHeight: 'fit-content',
}}
>
{props.children}
</View>
</GlassmorphismCC>
<Spacer/>
</ScrollView>
</View>