Working transition auth/clip

This commit is contained in:
Romain CLEMENT 2023-04-09 20:13:52 +02:00
parent 2c1df94e27
commit 07e4984fef
9 changed files with 132 additions and 74 deletions

View File

@ -21,44 +21,63 @@ import ClipViewLocal from './clip/ClipViewLocal';
import ClipViewRemote from './clip/ClipViewRemote'; import ClipViewRemote from './clip/ClipViewRemote';
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs'; import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createNativeStackNavigator } from '@react-navigation/native-stack';
import SignUp from './auth/SignUp';
import SignIn from './auth/SignIn'; import SignIn from './auth/SignIn';
import SignUp from './auth/SignUp';
import { Provider } from 'react-redux';
import store from './redux/store';
const Stack = createNativeStackNavigator(); const Stack = createNativeStackNavigator();
const Tab = createMaterialBottomTabNavigator(); const Tab = createMaterialBottomTabNavigator();
function Clip() { class App extends React.Component<any, any> {
return (
<Tab.Navigator>
<Tab.Screen name="Local" options={{ title: 'local' }}>
{(props) => <ClipViewLocal navigation={props.navigation} type={"local"} />}
</Tab.Screen>
<Tab.Screen name="Remote" options={{ title: 'remote' }}>
{(props) => <ClipViewRemote navigation={props.navigation} type={"remote"} />}
</Tab.Screen>
</Tab.Navigator>
);
}
function Auth() { constructor(props: any) {
return <Tab.Navigator> super(props);
<Tab.Screen component={SignIn} name="Login" options={{ title: 'Sign In' }} /> this.state = {
<Tab.Screen component={SignUp} name="Register" options={{ title: 'Sign Up' }} /> token: "",
</Tab.Navigator>; username: ""
} }
store.subscribe(() => {
console.log("see a dispatch");
this.setState({ token: store.getState().userReducer.token})
});
}
function App(): JSX.Element { Auth() {
return ( return <Provider store={store}>
<NavigationContainer> <Tab.Navigator>
<Stack.Navigator> <Tab.Screen children={() => <SignIn store={store} />} name="Login" options={{ title: 'Connexion' }} />
{/*-------------------------------------------*/} <Tab.Screen children={() => <SignUp store={store} />} name="Register" options={{ title: 'Créer un compte' }} />
<Stack.Screen component={Auth} name="Authentification" options={{title: "Authentification"}} /> </Tab.Navigator>
{/*-------------------------------------------*/} </Provider>;
<Stack.Screen component={Clip} name="Clipboards" options={{title: 'Clipboard'}}/> }
{/*-------------------------------------------*/}
</Stack.Navigator> Clip() {
return (
<Tab.Navigator>
<Tab.Screen name="Local" options={{ title: 'local' }}>
{(props) => <ClipViewLocal store={store} navigation={props.navigation} type={"local"} />}
</Tab.Screen>
<Tab.Screen name="Remote" options={{ title: 'distant' }}>
{(props) => <ClipViewRemote store={store} navigation={props.navigation} type={"remote"} />}
</Tab.Screen>
</Tab.Navigator>
);
}
render(): React.ReactNode {
console.log("render app", store.getState());
console.log("app state", this.state);
return <NavigationContainer>
<Stack.Navigator>{
this.state.token === ""
?
<Stack.Screen component={this.Auth} name="Authentication" options={{ title: "Authentification" }} />
:
<Stack.Screen component={this.Clip} name="Clipboards" options={{ title: 'Presse papiers' }} />
}</Stack.Navigator>
</NavigationContainer> </NavigationContainer>
); };
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { View, Text, Button, TextInput } from 'react-native'; import { View, Text, Button, TextInput } from 'react-native';
import { setUser } from '../redux/actions';
export default class SignIn extends React.Component<any, any> { export default class SignIn extends React.Component<any, any> {
@ -16,6 +16,15 @@ export default class SignIn extends React.Component<any, any> {
} }
async signInFunction() { async signInFunction() {
const signInResponse = await fetch(
'https://notifysync.simailadjalim.fr/user?username=' + this.state.username + '&password=' + this.state.password,
{ method: 'POST' }
);
const signInJson = await signInResponse.json();
if (signInJson.status === "ok") {
console.log(this.props.store);
this.props.store.dispatch(setUser(signInJson.token, this.state.username));
} else console.log(signInJson);
} }
updateUsername(event: any) { updateUsername(event: any) {
@ -29,10 +38,10 @@ export default class SignIn extends React.Component<any, any> {
render(): React.ReactNode { render(): React.ReactNode {
return ( return (
<View> <View>
<Text>Sign In</Text> <Text>Connexion</Text>
<TextInput placeholder="Pseudo" value={this.state.username} onChange={this.updateUsername}/> <TextInput placeholder="Nom d'utilisateur" value={this.state.username} onChange={this.updateUsername}/>
<TextInput placeholder="Mot de Passe" value={this.state.password} onChange={this.updatePassword}/> <TextInput placeholder="Mot de Passe" value={this.state.password} onChange={this.updatePassword}/>
<Button title="Sign In" onPress={this.signInFunction} /> <Button title="Se connecter" onPress={this.signInFunction} />
</View> </View>
); );
} }

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { View, Text, Button, TextInput } from 'react-native'; import { View, Text, Button, TextInput } from 'react-native';
import { accessibilityProps } from 'react-native-paper/lib/typescript/src/components/MaterialCommunityIcon';
import { setUser } from '../redux/actions';
export default class SignUp extends React.Component<any, any> { export default class SignUp extends React.Component<any, any> {
@ -11,56 +12,45 @@ export default class SignUp extends React.Component<any, any> {
username: '', username: '',
password: '' password: ''
} }
this.signUpFunction = this.signUpFunction.bind(this);
this.updateUsername = this.updateUsername.bind(this); this.updateUsername = this.updateUsername.bind(this);
this.updatePassword = this.updatePassword.bind(this); this.updatePassword = this.updatePassword.bind(this);
this.signUpFunction = this.signUpFunction.bind(this);
} }
async signUpFunction() { async signUpFunction() {
const signInResponse = await fetch('https://notifysync.simailadjalim.fr/user', { const signUpResponse = await fetch(
method: 'PUT', 'https://notifysync.simailadjalim.fr/user?username=' + this.state.username + '&password=' + this.state.password,
headers: { { method: 'PUT' }
Accept: 'application/json', );
'Content-Type': 'application/json', const signUpJson = await signUpResponse.json();
}, if (signUpJson.status === "ok") {
body: JSON.stringify({ const signInResponse = await fetch(
username: this.state.username, 'https://notifysync.simailadjalim.fr/user?username=' + this.state.username + '&password=' + this.state.password,
password: this.state.password { method: 'POST' }
}), );
}); const signInJson = await signInResponse.json();
const signInJson = await signInResponse.json(); if (signInJson.status === "ok") {
if (signInJson.status == "ok"){ console.log(this.props.store);
const loginResponse = await fetch('https://notifysync.simailadjalim.fr/user', { this.props.store.dispatch(setUser(signInJson.token, this.state.username));
method: 'POST', } else console.log(signInJson);
headers: { } else console.log(signUpJson);
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
}),
});
const loginJson = await loginResponse.json();
}
} }
updateUsername(event: any) { updateUsername(username: string) {
this.setState({ username: event.target.value }); this.setState({ username: username });
} }
updatePassword(event: any) { updatePassword(password: any) {
this.setState({ password: event.target.value }); this.setState({ password: password });
} }
render(): React.ReactNode { render(): React.ReactNode {
return ( return (
<View> <View>
<Text>Sign Up</Text> <Text>Créer un compte</Text>
<TextInput placeholder="Pseudo" value={this.state.username} onChange={this.updateUsername} /> <TextInput placeholder="Nom d'utilisateur" value={this.state.username} onChangeText={this.updateUsername} />
<TextInput placeholder="Mot de Passe" value={this.state.password} onChange={this.updatePassword} /> <TextInput placeholder="Mot de Passe" value={this.state.password} onChangeText={this.updatePassword} />
<Button title="Sign Up" onPress={this.signUpFunction} /> <Button title="S'enregistrer" onPress={this.signUpFunction} />
</View> </View>
); );
} }

View File

@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { ScrollView, Text, Button } from 'react-native'; import { Button } from 'react-native';
import ClipList from './ClipList'; import { clearUser } from '../redux/actions';
export default abstract class AClipView extends React.Component<any, any> { export default abstract class AClipView extends React.Component<any, any> {
@ -12,6 +11,13 @@ export default abstract class AClipView extends React.Component<any, any> {
} }
} }
getSignOutBtn() {
return <Button title="Sign out" onPress={() => {
console.log("logout");
this.props.store.dispatch(clearUser());
}} />
}
abstract getClips(): any; abstract getClips(): any;
abstract componentDidMount(): any; abstract componentDidMount(): any;

View File

@ -27,6 +27,7 @@ export default class ClipViewLocal extends AClipView {
return <ScrollView> return <ScrollView>
<Text style={{ fontWeight: 'bold', fontSize: 30, margin: 20 }}>{title}</Text> <Text style={{ fontWeight: 'bold', fontSize: 30, margin: 20 }}>{title}</Text>
<ClipList type={this.props.type} clips={this.state.clips} /> <ClipList type={this.props.type} clips={this.state.clips} />
{this.getSignOutBtn()}
</ScrollView>; </ScrollView>;
} }
} }

View File

@ -27,6 +27,7 @@ export default class ClipViewRemote extends AClipView {
<Text style={{ fontWeight: 'bold', fontSize: 30, margin: 20 }}>{title}</Text> <Text style={{ fontWeight: 'bold', fontSize: 30, margin: 20 }}>{title}</Text>
<ClipList type={this.props.type} clips={this.state.clips} /> <ClipList type={this.props.type} clips={this.state.clips} />
<Button title="Refresh" onPress={() => this.componentDidMount()} /> <Button title="Refresh" onPress={() => this.componentDidMount()} />
{this.getSignOutBtn()}
</ScrollView>; </ScrollView>;
} }
} }

12
src/redux/actions.tsx Normal file
View File

@ -0,0 +1,12 @@
export function setUser(token: string, username: string) {
return {
type: "auth/connect",
payload: { token, username }
};
}
export function clearUser() {
return {
type: "auth/disconnect"
};
}

12
src/redux/reducers.tsx Normal file
View File

@ -0,0 +1,12 @@
const initialState = { token: "" }
export function userReducer(state = initialState, action: any) {
switch (action.type) {
case "auth/connect":
return { ...state, token: action.payload.token, username: action.payload.username };
case "auth/disconnect":
return { ...state, token: "" };
default:
return state;
}
}

8
src/redux/store.tsx Normal file
View File

@ -0,0 +1,8 @@
import { createStore, combineReducers } from "redux";
import { userReducer } from "./reducers";
export default createStore(
combineReducers({
userReducer
})
);