Restore guest mode
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user