Prettier Refactor

This commit is contained in:
Djalim Simaila 2024-04-05 00:53:05 +02:00
parent 94df141d06
commit c89cfcf4fa
25 changed files with 1122 additions and 869 deletions

68
App.tsx
View File

@ -1,60 +1,68 @@
import 'react-native-gesture-handler'; import 'react-native-gesture-handler';
// ^ le bouge pas ca casse tout ^ // ^ le bouge pas ca casse tout ^
import { AppRegistry, Platform } from 'react-native' import {AppRegistry, Platform} from 'react-native';
import {useState} from 'react';
import { useState } from "react"; import {NavigationContainer, DefaultTheme} from '@react-navigation/native';
import { NavigationContainer, DefaultTheme } from '@react-navigation/native'; import {createNativeStackNavigator} from '@react-navigation/native-stack';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import {Provider} from 'react-redux';
import { Provider } from 'react-redux'; import {store, persistor} from './src/redux/store';
import { store,persistor } from './src/redux/store'; import {PaperProvider} from 'react-native-paper';
import { PaperProvider } from 'react-native-paper'; import {ToastProvider} from 'react-native-toast-notifications';
import { ToastProvider } from 'react-native-toast-notifications'
import AuthPage from './src/pages/Auth'; import AuthPage from './src/pages/Auth';
import ClipPage from './src/pages/Clips'; import ClipPage from './src/pages/Clips';
import IntroPage from './src/pages/Intro'; import IntroPage from './src/pages/Intro';
import { StatusBar } from 'expo-status-bar'; import {StatusBar} from 'expo-status-bar';
import { Material3Dracula, ReactNavigationDracula } from './src/themes'; import {Material3Dracula, ReactNavigationDracula} from './src/themes';
import { PixelRatio, useWindowDimensions } from 'react-native'; import {PixelRatio, useWindowDimensions} from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import {SafeAreaProvider} from 'react-native-safe-area-context';
const Stack = createNativeStackNavigator(); const Stack = createNativeStackNavigator();
import { PersistGate } from 'redux-persist/integration/react'; import {PersistGate} from 'redux-persist/integration/react';
function App() {
const [token, setToken] = useState(store.getState().user.token);
const [username, setUsername] = useState('');
function App(){ const {height, width} = useWindowDimensions();
const [token,setToken] = useState(store.getState().user.token);
const [username,setUsername] = useState("");
const {height,width} = useWindowDimensions();
console.log(width); console.log(width);
console.log(PixelRatio.get()) console.log(PixelRatio.get());
store.subscribe(()=>{ store.subscribe(() => {
let newToken = store.getState().user.token; let newToken = store.getState().user.token;
setToken(newToken); setToken(newToken);
}) });
return ( return (
<PaperProvider theme={Material3Dracula}> <PaperProvider theme={Material3Dracula}>
<ToastProvider> <ToastProvider>
<Provider store={store}> <Provider store={store}>
<PersistGate loading={null} persistor={persistor}> <PersistGate loading={null} persistor={persistor}>
<StatusBar style="light"/> <StatusBar style="light" />
<SafeAreaProvider> <SafeAreaProvider>
<NavigationContainer theme={ReactNavigationDracula}> <NavigationContainer theme={ReactNavigationDracula}>
<Stack.Navigator> <Stack.Navigator>
{ {token !== '' ? (
token !== "" ? (
<> <>
<Stack.Screen name="Home" component={ClipPage} options={{ headerShown: false }}/> <Stack.Screen
name="Home"
component={ClipPage}
options={{headerShown: false}}
/>
</> </>
) : ( ) : (
<> <>
<Stack.Screen name="Intro" component={IntroPage} options={{ headerShown: false }} /> <Stack.Screen
<Stack.Screen name="SignIn" component={AuthPage} options={{ headerShown: false }} /> name="Intro"
component={IntroPage}
options={{headerShown: false}}
/>
<Stack.Screen
name="SignIn"
component={AuthPage}
options={{headerShown: false}}
/>
</> </>
) )}
}
</Stack.Navigator> </Stack.Navigator>
</NavigationContainer> </NavigationContainer>
</SafeAreaProvider> </SafeAreaProvider>

View File

@ -1,83 +1,88 @@
import axios from 'axios'; import axios from 'axios';
import React from 'react'; import React from 'react';
import { View, Text, Platform, useWindowDimensions } from 'react-native'; import {View, Text, Platform, useWindowDimensions} from 'react-native';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import { Button, TextInput } from 'react-native-paper'; import {Button, TextInput} from 'react-native-paper';
import { login } from '../../redux/reducers'; import {login} from '../../redux/reducers';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { ReactNavigationDracula as t } from '../../themes'; import {ReactNavigationDracula as t} from '../../themes';
import { ps } from '../../utils'; import {ps} from '../../utils';
export default function SignIn(){ export default function SignIn() {
const [username, setUsername] = React.useState(""); const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState(""); const [password, setPassword] = React.useState('');
const [token,setToken] = React.useState(""); const [token, setToken] = React.useState('');
const toast = useToast(); const toast = useToast();
const dispatch = useDispatch(); const dispatch = useDispatch();
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
async function signInFunction(dispatch) { async function signInFunction(dispatch) {
axios.post("https://notifysync.simailadjalim.fr/user",{ axios
username:username, .post(
password:password 'https://notifysync.simailadjalim.fr/user',
},{ {
headers: {'Content-Type': 'multipart/form-data'}}) username: username,
password: password,
},
{
headers: {'Content-Type': 'multipart/form-data'},
},
)
.then((response, status) => { .then((response, status) => {
let token = response.data.token; let token = response.data.token;
dispatch(login({username:username,token:token})); dispatch(login({username: username, token: token}));
toast.show("login successful .w.",{ toast.show('login successful .w.', {
type:"success" type: 'success',
}); });
}) })
.catch(response =>{ .catch(response => {
toast.show(response.response.data.status); toast.show(response.response.data.status);
}); });
} }
return <View style={[{ return (
borderRadius:12, <View
height:"100%" style={[
},{ {
flex:1, borderRadius: 12,
margin:ps(8), height: '100%',
padding:ps(8), },
paddingTop:ps(8), {
gap:10, flex: 1,
flexDirection:'column', margin: ps(8),
justifyContent:"center", padding: ps(8),
alignItems:"center", paddingTop: ps(8),
gap: 10,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: width > 600 ? t.colors.card : t.colors.background, backgroundColor: width > 600 ? t.colors.card : t.colors.background,
}]}> },
]}>
<Text style={{ fontWeight: 'bold', fontSize: 30, color:t.colors.text }}> <Text style={{fontWeight: 'bold', fontSize: 30, color: t.colors.text}}>
Connexion Connexion
</Text> </Text>
<TextInput <TextInput
label="Nom d'utilisateur" label="Nom d'utilisateur"
mode='outlined' mode="outlined"
value={username} value={username}
onChangeText={setUsername} onChangeText={setUsername}
style={{ style={{
width: 300 width: 300,
}} }}
/> />
<TextInput <TextInput
label="Mot de Passe" label="Mot de Passe"
mode='outlined' mode="outlined"
value={password} value={password}
onChangeText={setPassword} onChangeText={setPassword}
style={{ style={{
width: 300 width: 300,
}} }}
/> />
<Button <Button mode="contained" onPress={() => dispatch(signInFunction)}>
mode="contained"
onPress={()=>dispatch(signInFunction)}
>
Se connecter Se connecter
</Button> </Button>
</View> </View>
);
} }

View File

@ -1,106 +1,124 @@
import React from 'react'; import React from 'react';
import {View, Text, Platform, useWindowDimensions } from 'react-native'; import {View, Text, Platform, useWindowDimensions} from 'react-native';
import axios from 'axios'; import axios from 'axios';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import { Button, TextInput } from 'react-native-paper'; import {Button, TextInput} from 'react-native-paper';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { login } from '../../redux/reducers'; import {login} from '../../redux/reducers';
import { ReactNavigationDracula as t } from '../../themes'; import {ReactNavigationDracula as t} from '../../themes';
import { ps } from '../../utils'; import {ps} from '../../utils';
export default function SignUp(){ export default function SignUp() {
const [username, setUsername] = React.useState(""); const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState(""); const [password, setPassword] = React.useState('');
const [confirm, setConfirm] = React.useState(""); const [confirm, setConfirm] = React.useState('');
const toast = useToast(); const toast = useToast();
const dispatch = useDispatch(); const dispatch = useDispatch();
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
function signUpFunction(dispatch) { function signUpFunction(dispatch) {
if (confirm != password) {
if (confirm != password){ toast.show('The password and its confirmation are not the same', {
toast.show("The password and its confirmation are not the same",{ type: 'warning',
type:"warning"
}); });
return; return;
} }
axios.put("https://notifysync.simailadjalim.fr/user",{ axios
username:username, .put(
password:password 'https://notifysync.simailadjalim.fr/user',
},{ {
headers: {'Content-Type': 'multipart/form-data'}}) username: username,
password: password,
},
{
headers: {'Content-Type': 'multipart/form-data'},
},
)
.then((response, status) => { .then((response, status) => {
toast.show("Account created, logging in !",{type:"success"}); toast.show('Account created, logging in !', {type: 'success'});
axios.post("https://notifysync.simailadjalim.fr/user",{ axios
username:username, .post(
password:password 'https://notifysync.simailadjalim.fr/user',
},{ {
headers: {'Content-Type': 'multipart/form-data'}}) username: username,
password: password,
},
{
headers: {'Content-Type': 'multipart/form-data'},
},
)
.then((response, status) => { .then((response, status) => {
let token = response.data.token; let token = response.data.token;
dispatch(login({username:username,token:token})); dispatch(login({username: username, token: token}));
toast.show("login successful .w.",{type:"success"}); toast.show('login successful .w.', {type: 'success'});
}) })
.catch(response =>{ .catch(response => {
toast.show(response.response.data.status); toast.show(response.response.data.status);
}); });
// //
}) })
.catch(response =>{ .catch(response => {
toast.show(response.response.data.status); toast.show(response.response.data.status);
}); });
} }
return ( return (
<View style={[{ <View
borderRadius:12, style={[
height:"100%" {
},{ borderRadius: 12,
flex:1, height: '100%',
margin:ps(8), },
padding:ps(8), {
paddingTop:ps(8), flex: 1,
gap:10, margin: ps(8),
flexDirection:'column', padding: ps(8),
justifyContent:"center", paddingTop: ps(8),
alignItems:"center", gap: 10,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: width > 600 ? t.colors.card : t.colors.background, backgroundColor: width > 600 ? t.colors.card : t.colors.background,
}]}> },
<Text style={{fontWeight: 'bold', fontSize: 30 ,color:t.colors.text}}> ]}>
<Text style={{fontWeight: 'bold', fontSize: 30, color: t.colors.text}}>
Créer un compte Créer un compte
</Text> </Text>
<TextInput <TextInput
label="Nom d'utilisateur" label="Nom d'utilisateur"
mode='outlined' mode="outlined"
value={username} value={username}
onChangeText={setUsername} onChangeText={setUsername}
style={{ style={{
width:300 width: 300,
}} }}
/> />
<TextInput <TextInput
label="Mot de passe" label="Mot de passe"
mode='outlined' mode="outlined"
value={password} value={password}
onChangeText={setPassword} onChangeText={setPassword}
style={{ style={{
width:300 width: 300,
}} }}
/> />
<TextInput <TextInput
label="Confirmer le mot de passe" label="Confirmer le mot de passe"
mode='outlined' mode="outlined"
value={confirm} value={confirm}
onChangeText={setConfirm} onChangeText={setConfirm}
style={{ style={{
width:300 width: 300,
}} }}
/> />
<Button mode="contained" onPress={()=>{dispatch(signUpFunction)}}> <Button
mode="contained"
onPress={() => {
dispatch(signUpFunction);
}}>
S'enregistrer S'enregistrer
</Button> </Button>
</View> </View>
); );
} }

View File

@ -1,34 +1,43 @@
import axios from 'axios'; import axios from 'axios';
import {View} from 'react-native'; import {View} from 'react-native';
import IconVector from 'react-native-vector-icons/FontAwesome5'; import IconVector from 'react-native-vector-icons/FontAwesome5';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { Avatar, Card, Text } from 'react-native-paper'; import {Avatar, Card, Text} from 'react-native-paper';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
import { Button } from 'react-native-paper'; import {Button, Menu} from 'react-native-paper';
import {useState} from 'react';
export default function ClipElementLocal({content}:{content: string}){
export default function ClipElementLocal({content}: {content: string}) {
const [visible, setVisible] = useState(false);
const [coords, setCoords] = useState({x: 0, y: 0});
const toast = useToast(); const toast = useToast();
function onCopy() { function onCopy() {
Clipboard.setStringAsync(content) Clipboard.setStringAsync(content).then(() => {
.then(()=>{ toast.show('copied "' + content + '" into the clipboard');
toast.show('copied "'+content+'" into the clipboard');
}); });
} }
function sendToRemote() { function sendToRemote() {
axios.put("https://notifysync.simailadjalim.fr/clipboard",{ axios
content:content, .put(
deviceName:"TestNative", 'https://notifysync.simailadjalim.fr/clipboard',
token: store.getState().user.token {
},{ content: content,
headers: {'Content-Type': 'multipart/form-data'}} deviceName: 'TestNative',
).then((response,status)=>{ token: store.getState().user.token,
toast.show('"'+content+'" was sent to the server'); },
}).catch(response => { {
toast.show('error'); headers: {'Content-Type': 'multipart/form-data'},
},
)
.then((response, status) => {
toast.show('"' + content + '" was sent to the server');
}) })
.catch(response => {
toast.show('error');
});
} }
return ( return (
<View <View
@ -39,12 +48,28 @@ export default function ClipElementLocal({content}:{content: string}){
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
}}> }}>
<Card style={{width:"100%"}} onPress={onCopy}> <Menu
<Card.Title title={content} right={() => visible={visible}
<Button mode="contained" onPress={() => sendToRemote()} > onDismiss={() => setVisible(false)}
anchor={coords}>
<Menu.Item onPress={() => {}} title="View" />
<Menu.Item onPress={() => {}} title="Share" />
<Menu.Item onPress={() => {}} title="Delete" />
</Menu>
<Card
style={{width: '100%'}}
onPressIn={evt =>
setCoords({x: evt.nativeEvent.pageX, y: evt.nativeEvent.pageY})
}
onPress={onCopy}
onLongPress={() => setVisible(true)}>
<Card.Title
title={content}
right={() => (
<Button mode="contained" onPress={() => sendToRemote()}>
<IconVector name="paper-plane" size={20} color="black" /> <IconVector name="paper-plane" size={20} color="black" />
</Button> </Button>
} )}
/> />
<Card.Content> <Card.Content>
<Text></Text> <Text></Text>
@ -53,5 +78,3 @@ export default function ClipElementLocal({content}:{content: string}){
</View> </View>
); );
} }

View File

@ -1,33 +1,67 @@
import { View } from 'react-native'; import {View} from 'react-native';
import IconVector from 'react-native-vector-icons/FontAwesome5'; import IconVector from 'react-native-vector-icons/FontAwesome5';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import { Card, Text, Button } from 'react-native-paper'; import {Card, Text, Menu} from 'react-native-paper';
import {useState} from 'react';
export default function ClipElementRemote({content,timestamp,deviceName}:{content:string;timestamp:number,deviceName:string}){ export default function ClipElementRemote({
content,
timestamp,
deviceName,
}: {
content: string;
timestamp: number;
deviceName: string;
}) {
const [visible, setVisible] = useState(false);
const [coords, setCoords] = useState({x: 0, y: 0});
const toast = useToast(); const toast = useToast();
function onCopy() { function onCopy() {
Clipboard.setStringAsync(content) Clipboard.setStringAsync(content).then(() => {
.then(()=>{ toast.show('copied "' + content + '" into the clipboard');
toast.show('copied "'+content+'" into the clipboard');
}); });
} }
const date= new Date(timestamp*1000); const date = new Date(timestamp * 1000);
return( return (
<View style={{flex:1, <View
padding:10, style={{
width:"100%", flex: 1,
flexDirection:'row', padding: 10,
justifyContent:'center', width: '100%',
alignItems:'center'}}> flexDirection: 'row',
<Card style={{width:"100%"}} onPress={onCopy} > justifyContent: 'center',
<Card.Title title={content}/> alignItems: 'center',
}}>
<Menu
visible={visible}
onDismiss={() => setVisible(false)}
anchor={coords}>
<Menu.Item onPress={() => {}} title="View" />
<Menu.Item onPress={() => {}} title="Share" />
<Menu.Item onPress={() => {}} title="Delete" />
</Menu>
<Card
style={{width: '100%'}}
onPressIn={evt =>
setCoords({x: evt.nativeEvent.pageX, y: evt.nativeEvent.pageY})
}
onPress={onCopy}
onLongPress={() => setVisible(true)}>
<Card.Title title={content} />
<Card.Content> <Card.Content>
<Text variant="bodyMedium">{date.getHours() + ":" + date.getMinutes() + ", "+ date.toDateString()}</Text> <Text variant="bodyMedium">
{date.getHours() +
':' +
date.getMinutes() +
', ' +
date.toDateString()}
</Text>
<Text variant="bodyMedium">{deviceName}</Text> <Text variant="bodyMedium">{deviceName}</Text>
</Card.Content> </Card.Content>
</Card> </Card>
</View>); </View>
);
} }

View File

@ -2,7 +2,7 @@ import React from 'react';
import {FlatList, ScrollView} from 'react-native'; import {FlatList, ScrollView} from 'react-native';
import ClipElementLocal from './ClipElementLocal'; import ClipElementLocal from './ClipElementLocal';
import ClipElementRemote from './ClipElementRemote'; import ClipElementRemote from './ClipElementRemote';
import { nanoid } from '@reduxjs/toolkit'; import {nanoid} from '@reduxjs/toolkit';
export default class ClipList extends React.Component<any, any> { export default class ClipList extends React.Component<any, any> {
constructor(props: any) { constructor(props: any) {
@ -11,21 +11,29 @@ export default class ClipList extends React.Component<any, any> {
render(): JSX.Element { render(): JSX.Element {
if (this.props.type === 'local') { if (this.props.type === 'local') {
return <FlatList return (
<FlatList
data={this.props.clips} data={this.props.clips}
renderItem={({item}) => <ClipElementLocal content={item.content} />} renderItem={({item}) => <ClipElementLocal content={item.content} />}
keyExtractor={item => nanoid()} keyExtractor={item => nanoid()}
inverted={true} inverted={true}
/> />
);
} else { } else {
return <FlatList return (
<FlatList
data={this.props.clips} data={this.props.clips}
renderItem={({item}) => <ClipElementRemote content={item.content} deviceName={item.device_name} timestamp={item.timestamp}/>} renderItem={({item}) => (
<ClipElementRemote
content={item.content}
deviceName={item.device_name}
timestamp={item.timestamp}
/>
)}
keyExtractor={item => nanoid()} keyExtractor={item => nanoid()}
inverted={true} inverted={true}
/> />
; );
} }
} }
} }

View File

@ -1,58 +1,72 @@
import React from "react"; import React from 'react';
import { useWindowDimensions, ScrollView, View } from "react-native"; import {useWindowDimensions, ScrollView, View} from 'react-native';
import { Searchbar, Button } from "react-native-paper" import {Searchbar, Button} from 'react-native-paper';
import ClipViewLocal from "./ClipViewLocal"; import ClipViewLocal from './ClipViewLocal';
import ClipViewRemote from "./ClipViewRemote"; import ClipViewRemote from './ClipViewRemote';
import { ps } from "../../utils"; import {ps} from '../../utils';
import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs"; import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
export default function ClipView(){
export default function ClipView() {
const [searchQuery, setSearchQuery] = React.useState(''); const [searchQuery, setSearchQuery] = React.useState('');
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
const Tab = createMaterialTopTabNavigator(); const Tab = createMaterialTopTabNavigator();
let layout = "" let layout = '';
if (width < 600) layout = "compact"; if (width < 600) layout = 'compact';
else if (width < 1200 ) layout = "medium"; else if (width < 1200) layout = 'medium';
else layout = "expanded"; else layout = 'expanded';
return ( <> return (
<View style={{flexDirection:"row",justifyContent:"center",alignItems:"center", gap:5, margin:ps(4)}}> <>
{layout == "compact" ? <View
<Button children={<></>} icon="dots-vertical" mode="contained" style={{width:"auto"}} onPress={() => console.log('Pressed')}/> style={{
: <></>} flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
gap: 5,
margin: ps(4),
}}>
{layout == 'compact' ? (
<Button
children={<></>}
icon="dots-vertical"
mode="contained"
style={{width: 'auto'}}
onPress={() => console.log('Pressed')}
/>
) : (
<></>
)}
<Searchbar <Searchbar
placeholder="Clipboards" placeholder="Clipboards"
onChangeText={setSearchQuery} onChangeText={setSearchQuery}
value={searchQuery} value={searchQuery}
style={{ style={{
flex:1 flex: 1,
}} }}
/> />
</View> </View>
{ {layout == 'compact' ? (
layout == "compact"? (
<Tab.Navigator tabBarPosition="bottom"> <Tab.Navigator tabBarPosition="bottom">
<Tab.Screen name="Local" options={{title: 'local'}}> <Tab.Screen name="Local" options={{title: 'local'}}>
{() => ( {() => <ClipViewLocal />}
<ClipViewLocal/>
)}
</Tab.Screen> </Tab.Screen>
<Tab.Screen name="Remote" options={{title: 'distant'}}> <Tab.Screen name="Remote" options={{title: 'distant'}}>
{()=> ( {() => <ClipViewRemote />}
<ClipViewRemote/>
)}
</Tab.Screen> </Tab.Screen>
</Tab.Navigator> </Tab.Navigator>
):( ) : (
<ScrollView contentContainerStyle={{flexDirection:"row",justifyContent:"center",height:"100%",padding:ps(30)}}> <ScrollView
<ClipViewLocal/> contentContainerStyle={{
<ClipViewRemote/> flexDirection: 'row',
justifyContent: 'center',
height: '100%',
padding: ps(30),
}}>
<ClipViewLocal />
<ClipViewRemote />
</ScrollView> </ScrollView>
) )}
}
</> </>
);
)
} }

View File

@ -1,57 +1,55 @@
import React from 'react'; import React from 'react';
import {ScrollView, View, Text, useWindowDimensions} from 'react-native'; import {ScrollView, View, Text, useWindowDimensions} from 'react-native';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import ClipList from './ClipList'; import ClipList from './ClipList';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { localClipAddToList } from '../../redux/reducers'; import {localClipAddToList} from '../../redux/reducers';
import { useToast } from 'react-native-toast-notifications'; import {useToast} from 'react-native-toast-notifications';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { ps } from '../../utils'; import {ps} from '../../utils';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
export default function ClipViewLocal({}){ export default function ClipViewLocal({}) {
const [clips, setClips] = React.useState([...store.getState().localClip.localClip]); const [clips, setClips] = React.useState([
...store.getState().localClip.localClip,
]);
const dispatch = useDispatch(); const dispatch = useDispatch();
const toast = useToast(); const toast = useToast();
const {height,width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
async function addToLocal(dispatch) { async function addToLocal(dispatch) {
Clipboard.getStringAsync() Clipboard.getStringAsync()
.then(value =>{ .then(value => {
let newClip = {"content":value}; let newClip = {content: value};
console.log(value); console.log(value);
dispatch(localClipAddToList(newClip)); dispatch(localClipAddToList(newClip));
setClips([...clips,newClip]); setClips([...clips, newClip]);
toast.show('copied "'+value+'" into history'); toast.show('copied "' + value + '" into history');
}) })
.catch((error)=>{ .catch(error => {
console.log(error); console.log(error);
toast.show("could not retreive last copied element :(") toast.show('could not retreive last copied element :(');
}) });
} }
return ( return (
<View style={{ <View
width:"100%", style={{
height:"100%", width: '100%',
flex:1, height: '100%',
margin: width > 600 ? ps(10) : 0 flex: 1,
margin: width > 600 ? ps(10) : 0,
}}> }}>
<Button <Button
mode="elevated" mode="elevated"
onPress={() => { onPress={() => {
dispatch(addToLocal); dispatch(addToLocal);
}} }}>
>
Coller depuis le presse papier Coller depuis le presse papier
</Button> </Button>
<ScrollView> <ScrollView>
<ClipList <ClipList type={'local'} clips={clips} />
type={"local"}
clips={clips}
/>
</ScrollView> </ScrollView>
</View> </View>
); );
} }

View File

@ -1,45 +1,57 @@
import React from 'react'; import React from 'react';
import axios from 'axios'; import axios from 'axios';
import { ScrollView,View, Text, useWindowDimensions } from 'react-native'; import {ScrollView, View, Text, useWindowDimensions} from 'react-native';
import ClipList from './ClipList'; import ClipList from './ClipList';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
import { useToast } from 'react-native-toast-notifications'; import {useToast} from 'react-native-toast-notifications';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import { ps } from '../../utils'; import {ps} from '../../utils';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { remoteClipAddToList } from '../../redux/reducers'; import {remoteClipAddToList} from '../../redux/reducers';
export default function ClipViewRemote(){ export default function ClipViewRemote() {
const [clips,setClips] = React.useState(store.getState().remoteClip.remoteClip); const [clips, setClips] = React.useState(
store.getState().remoteClip.remoteClip,
);
const toast = useToast(); const toast = useToast();
const dispatch = useDispatch(); const dispatch = useDispatch();
const {height,width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
async function getClips(dispatch) { async function getClips(dispatch) {
axios.get("http://notifysync.simailadjalim.fr/clipboard?token="+store.getState().user.token) axios
.then((response,status) => { .get(
let remoteclips = Object.values(response["data"]['clipboard']); 'http://notifysync.simailadjalim.fr/clipboard?token=' +
store.getState().user.token,
)
.then((response, status) => {
let remoteclips = Object.values(response['data']['clipboard']);
setClips(remoteclips); setClips(remoteclips);
dispatch(remoteClipAddToList(remoteclips)) dispatch(remoteClipAddToList(remoteclips));
toast.show("fetched latest clips from remote"); toast.show('fetched latest clips from remote');
}) })
.catch(response =>{ .catch(response => {
console.log(response); console.log(response);
toast.show("failed to fetch latest clips"); toast.show('failed to fetch latest clips');
}); });
} }
function getSignOutBtn() { function getSignOutBtn() {
return <Button mode="elevated" onPress={() => {}}>Sign out</Button> return (
<Button mode="elevated" onPress={() => {}}>
Sign out
</Button>
);
} }
let title = "Remote Clipboard"; let title = 'Remote Clipboard';
return <View style={{ return (
width:"100%", <View
height:"100%", style={{
flex:1, width: '100%',
margin: width > 600 ? ps(10) : 0 height: '100%',
flex: 1,
margin: width > 600 ? ps(10) : 0,
}}> }}>
<Button mode="elevated" onPress={() => dispatch(getClips)}> <Button mode="elevated" onPress={() => dispatch(getClips)}>
Refresh Refresh
@ -47,6 +59,6 @@ export default function ClipViewRemote(){
<ScrollView> <ScrollView>
<ClipList type="remote" clips={clips} /> <ClipList type="remote" clips={clips} />
</ScrollView> </ScrollView>
</View>; </View>
);
} }

View File

@ -1,35 +1,50 @@
import axios from 'axios'; import axios from 'axios';
import {View} from 'react-native'; import {View} from 'react-native';
import IconVector from 'react-native-vector-icons/FontAwesome5'; import IconVector from 'react-native-vector-icons/FontAwesome5';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { Avatar, Card, Text } from 'react-native-paper'; import {Avatar, Card, Text} from 'react-native-paper';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
import { Button } from 'react-native-paper'; import {Button, Menu} from 'react-native-paper';
import {useState} from 'react';
export default function NotifElementLocal({title,content}:{title:string;content: string}){ export default function NotifElementLocal({
title,
content,
}: {
title: string;
content: string;
}) {
const [visible, setVisible] = useState(false);
const [coords, setCoords] = useState({x: 0, y: 0});
const toast = useToast(); const toast = useToast();
function onCopy() { function onCopy() {
Clipboard.setStringAsync(content) Clipboard.setStringAsync(content).then(() => {
.then(()=>{ toast.show('copied "' + content + '" into the clipboard');
toast.show('copied "'+content+'" into the clipboard');
}); });
} }
function sendToRemote() { function sendToRemote() {
axios.put("https://notifysync.simailadjalim.fr/notification",{ axios
title:title, .put(
content:content, 'https://notifysync.simailadjalim.fr/notification',
deviceName:"TestNative", {
token: store.getState().user.token title: title,
},{ content: content,
headers: {'Content-Type': 'multipart/form-data'}} deviceName: 'TestNative',
).then((response,status)=>{ token: store.getState().user.token,
},
{
headers: {'Content-Type': 'multipart/form-data'},
},
)
.then((response, status) => {
toast.show('the notification was sent to the server'); toast.show('the notification was sent to the server');
}).catch(response => {
toast.show('error');
}) })
.catch(response => {
toast.show('error');
});
} }
return ( return (
<View <View
@ -40,12 +55,28 @@ export default function NotifElementLocal({title,content}:{title:string;content:
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
}}> }}>
<Card style={{width:"100%"}} onPress={onCopy}> <Menu
<Card.Title title={title} right={() => visible={visible}
<Button mode="contained" onPress={() => sendToRemote()} > onDismiss={() => setVisible(false)}
anchor={coords}>
<Menu.Item onPress={() => {}} title="View" />
<Menu.Item onPress={() => {}} title="Share" />
<Menu.Item onPress={() => {}} title="Delete" />
</Menu>
<Card
style={{width: '100%'}}
onPressIn={evt =>
setCoords({x: evt.nativeEvent.pageX, y: evt.nativeEvent.pageY})
}
onPress={onCopy}
onLongPress={() => setVisible(true)}>
<Card.Title
title={title}
right={() => (
<Button mode="contained" onPress={() => sendToRemote()}>
<IconVector name="paper-plane" size={20} color="black" /> <IconVector name="paper-plane" size={20} color="black" />
</Button> </Button>
} )}
/> />
<Card.Content> <Card.Content>
<Text variant="bodyMedium">{content}</Text> <Text variant="bodyMedium">{content}</Text>
@ -54,5 +85,3 @@ export default function NotifElementLocal({title,content}:{title:string;content:
</View> </View>
); );
} }

View File

@ -1,34 +1,69 @@
import { View } from 'react-native'; import {View} from 'react-native';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { useToast } from "react-native-toast-notifications"; import {useToast} from 'react-native-toast-notifications';
import { Card, Text, Button } from 'react-native-paper'; import {Card, Text, Menu} from 'react-native-paper';
import {useState} from 'react';
export default function NotifElementRemote({title,content,timestamp,deviceName}:{title:string;content:string;timestamp:number;deviceName:string}){
export default function NotifElementRemote({
title,
content,
timestamp,
deviceName,
}: {
title: string;
content: string;
timestamp: number;
deviceName: string;
}) {
const [visible, setVisible] = useState(false);
const [coords, setCoords] = useState({x: 0, y: 0});
const toast = useToast(); const toast = useToast();
function onCopy() { function onCopy() {
Clipboard.setStringAsync(content) Clipboard.setStringAsync(content).then(() => {
.then(()=>{ toast.show('copied "' + content + '" into the clipboard');
toast.show('copied "'+content+'" into the clipboard');
}); });
} }
const date= new Date(timestamp*1000); const date = new Date(timestamp * 1000);
return( return (
<View style={{flex:1, <View
padding:10, style={{
width:"100%", flex: 1,
flexDirection:'row', padding: 10,
justifyContent:'center', width: '100%',
alignItems:'center'}}> flexDirection: 'row',
<Card style={{width:"100%"}} onPress={onCopy} > justifyContent: 'center',
<Card.Title title={title}/> alignItems: 'center',
}}>
<Menu
visible={visible}
onDismiss={() => setVisible(false)}
anchor={coords}>
<Menu.Item onPress={() => {}} title="View" />
<Menu.Item onPress={() => {}} title="Share" />
<Menu.Item onPress={() => {}} title="Delete" />
</Menu>
<Card
style={{width: '100%'}}
onPressIn={evt =>
setCoords({x: evt.nativeEvent.pageX, y: evt.nativeEvent.pageY})
}
onPress={onCopy}
onLongPress={() => setVisible(true)}>
<Card.Title title={title} />
<Card.Content> <Card.Content>
<Text variant="bodyMedium">{content}</Text> <Text variant="bodyMedium">{content}</Text>
<Text variant="bodyMedium">{date.getHours() + ":" + date.getMinutes() + ", "+ date.toDateString()}</Text> <Text variant="bodyMedium">
{date.getHours() +
':' +
date.getMinutes() +
', ' +
date.toDateString()}
</Text>
<Text variant="bodyMedium">{deviceName}</Text> <Text variant="bodyMedium">{deviceName}</Text>
</Card.Content> </Card.Content>
</Card> </Card>
</View>); </View>
);
} }

View File

@ -1,23 +1,40 @@
import React from 'react'; import React from 'react';
import {FlatList, ScrollView} from 'react-native'; import {FlatList, ScrollView} from 'react-native';
import { nanoid } from '@reduxjs/toolkit'; import {nanoid} from '@reduxjs/toolkit';
import NotifElementLocal from './NotifElementLocal'; import NotifElementLocal from './NotifElementLocal';
import NotifElementRemote from './NotifElementRemote'; import NotifElementRemote from './NotifElementRemote';
export default function NotifList({type,notifs}:{type:string,notifs:Array<object>}) { export default function NotifList({
type,
notifs,
}: {
type: string;
notifs: Array<object>;
}) {
if (type === 'local') { if (type === 'local') {
return <FlatList return (
<FlatList
data={notifs} data={notifs}
renderItem={({item}) => <NotifElementLocal title={item.title} content={item.content} />} renderItem={({item}) => (
<NotifElementLocal title={item.title} content={item.content} />
)}
keyExtractor={item => nanoid()} keyExtractor={item => nanoid()}
/> />
);
} else { } else {
return <FlatList return (
<FlatList
data={notifs} data={notifs}
renderItem={({item}) => <NotifElementRemote title={item.title} content={item.content} deviceName={item.device_name} timestamp={item.timestamp}/>} renderItem={({item}) => (
<NotifElementRemote
title={item.title}
content={item.content}
deviceName={item.device_name}
timestamp={item.timestamp}
/>
)}
keyExtractor={item => nanoid()} keyExtractor={item => nanoid()}
/> />
; );
} }
} }

View File

@ -1,58 +1,72 @@
import React from "react"; import React from 'react';
import { useWindowDimensions, ScrollView, View } from "react-native"; import {useWindowDimensions, ScrollView, View} from 'react-native';
import { Searchbar, Button } from "react-native-paper" import {Searchbar, Button} from 'react-native-paper';
import NotifViewLocal from "./NotifViewLocal"; import NotifViewLocal from './NotifViewLocal';
import NotifViewRemote from "./NotifViewRemote"; import NotifViewRemote from './NotifViewRemote';
import { ps } from "../../utils"; import {ps} from '../../utils';
import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs"; import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
export default function NotifView(){
export default function NotifView() {
const [searchQuery, setSearchQuery] = React.useState(''); const [searchQuery, setSearchQuery] = React.useState('');
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
const Tab = createMaterialTopTabNavigator(); const Tab = createMaterialTopTabNavigator();
let layout = "" let layout = '';
if (width < 600) layout = "compact"; if (width < 600) layout = 'compact';
else if (width < 1200 ) layout = "medium"; else if (width < 1200) layout = 'medium';
else layout = "expanded"; else layout = 'expanded';
return ( <> return (
<View style={{flexDirection:"row",justifyContent:"center",alignItems:"center", gap:5, margin:ps(4)}}> <>
{layout == "compact" ? <View
<Button children={<></>} icon="dots-vertical" mode="contained" style={{width:"auto"}} onPress={() => console.log('Pressed')}/> style={{
: <></>} flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
gap: 5,
margin: ps(4),
}}>
{layout == 'compact' ? (
<Button
children={<></>}
icon="dots-vertical"
mode="contained"
style={{width: 'auto'}}
onPress={() => console.log('Pressed')}
/>
) : (
<></>
)}
<Searchbar <Searchbar
placeholder="Notifications" placeholder="Notifications"
onChangeText={setSearchQuery} onChangeText={setSearchQuery}
value={searchQuery} value={searchQuery}
style={{ style={{
flex:1 flex: 1,
}} }}
/> />
</View> </View>
{ {layout == 'compact' ? (
layout == "compact"? (
<Tab.Navigator tabBarPosition="bottom"> <Tab.Navigator tabBarPosition="bottom">
<Tab.Screen name="Local" options={{title: 'local'}}> <Tab.Screen name="Local" options={{title: 'local'}}>
{() => ( {() => <NotifViewLocal />}
<NotifViewLocal/>
)}
</Tab.Screen> </Tab.Screen>
<Tab.Screen name="Remote" options={{title: 'distant'}}> <Tab.Screen name="Remote" options={{title: 'distant'}}>
{()=> ( {() => <NotifViewRemote />}
<NotifViewRemote/>
)}
</Tab.Screen> </Tab.Screen>
</Tab.Navigator> </Tab.Navigator>
):( ) : (
<ScrollView contentContainerStyle={{flexDirection:"row",justifyContent:"center",height:"100%",padding:ps(30)}}> <ScrollView
<NotifViewLocal/> contentContainerStyle={{
<NotifViewRemote/> flexDirection: 'row',
justifyContent: 'center',
height: '100%',
padding: ps(30),
}}>
<NotifViewLocal />
<NotifViewRemote />
</ScrollView> </ScrollView>
) )}
}
</> </>
);
)
} }

View File

@ -1,62 +1,67 @@
import React from 'react'; import React from 'react';
import {ScrollView, View, Text, useWindowDimensions} from 'react-native'; import {ScrollView, View, Text, useWindowDimensions} from 'react-native';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import NotifList from './NotifList'; import NotifList from './NotifList';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { localClipAddToList, localNotifAddToList } from '../../redux/reducers'; import {localClipAddToList, localNotifAddToList} from '../../redux/reducers';
import { useToast } from 'react-native-toast-notifications'; import {useToast} from 'react-native-toast-notifications';
import * as Clipboard from 'expo-clipboard'; import * as Clipboard from 'expo-clipboard';
import { ps } from '../../utils'; import {ps} from '../../utils';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
export default function NotifViewLocal({}){ export default function NotifViewLocal({}) {
const [notifs, setNotifs] = React.useState(store.getState().localNotif.localNotif); const [notifs, setNotifs] = React.useState(
store.getState().localNotif.localNotif,
);
const dispatch = useDispatch(); const dispatch = useDispatch();
const toast = useToast(); const toast = useToast();
const {height,width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
function getSignOutBtn() { function getSignOutBtn() {
return <Button mode="elevated" onPress={() => {}}>Sign out</Button> return (
<Button mode="elevated" onPress={() => {}}>
Sign out
</Button>
);
} }
async function addToLocal(dispatch) { async function addToLocal(dispatch) {
Clipboard.getStringAsync() Clipboard.getStringAsync()
.then(value =>{ .then(value => {
let newNotif = {"title":"placeholder title","content":"placeholder content"}; let newNotif = {
title: 'placeholder title',
content: 'placeholder content',
};
console.log(value); console.log(value);
dispatch(localNotifAddToList(newNotif)); dispatch(localNotifAddToList(newNotif));
setNotifs([...notifs,newNotif]); setNotifs([...notifs, newNotif]);
toast.show('added "'+value+'" into history'); toast.show('added "' + value + '" into history');
}) })
.catch((error)=>{ .catch(error => {
console.log(error); console.log(error);
toast.show("could not retreive last notification :(") toast.show('could not retreive last notification :(');
}) });
} }
return ( return (
<View style={{ <View
width:"100%", style={{
height:"100%", width: '100%',
flex:1, height: '100%',
margin: width > 600 ? ps(10) : 0 flex: 1,
margin: width > 600 ? ps(10) : 0,
}}> }}>
<Button <Button
mode="elevated" mode="elevated"
onPress={() => { onPress={() => {
console.log("TODO"); console.log('TODO');
dispatch(addToLocal); dispatch(addToLocal);
}} }}>
>
importer la derniere notification importer la derniere notification
</Button> </Button>
<ScrollView> <ScrollView>
<NotifList <NotifList type={'local'} notifs={notifs} />
type={"local"}
notifs={notifs}
/>
</ScrollView> </ScrollView>
</View> </View>
); );
} }

View File

@ -1,41 +1,49 @@
import React from 'react'; import React from 'react';
import axios from 'axios'; import axios from 'axios';
import { ScrollView,View, Text, useWindowDimensions } from 'react-native'; import {ScrollView, View, Text, useWindowDimensions} from 'react-native';
import NotifListfrom from './NotifList'; import NotifListfrom from './NotifList';
import { store } from '../../redux/store'; import {store} from '../../redux/store';
import { useToast } from 'react-native-toast-notifications'; import {useToast} from 'react-native-toast-notifications';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import { ps } from '../../utils'; import {ps} from '../../utils';
import NotifList from './NotifList'; import NotifList from './NotifList';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { remoteNotifAddToList } from '../../redux/reducers'; import {remoteNotifAddToList} from '../../redux/reducers';
export default function NotifViewRemote(){ export default function NotifViewRemote() {
const [clips,setClips] = React.useState(store.getState().remoteNotif.remoteNotif); const [clips, setClips] = React.useState(
store.getState().remoteNotif.remoteNotif,
);
const toast = useToast(); const toast = useToast();
const dispatch = useDispatch(); const dispatch = useDispatch();
const {height,width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
async function getNotif(dispatch) { async function getNotif(dispatch) {
axios.get("http://notifysync.simailadjalim.fr/notification?token="+store.getState().user.token) axios
.then((response,status) => { .get(
let remoteNotif = Object.values(response["data"]['notifications']); 'http://notifysync.simailadjalim.fr/notification?token=' +
store.getState().user.token,
)
.then((response, status) => {
let remoteNotif = Object.values(response['data']['notifications']);
setClips(remoteNotif); setClips(remoteNotif);
dispatch(remoteNotifAddToList(remoteNotif)); dispatch(remoteNotifAddToList(remoteNotif));
toast.show("fetched latest notifications from remote"); toast.show('fetched latest notifications from remote');
}) })
.catch(response =>{ .catch(response => {
console.log(response); console.log(response);
toast.show("failed to fetch latest notifications"); toast.show('failed to fetch latest notifications');
}); });
} }
return <View style={{ return (
width:"100%", <View
height:"100%", style={{
flex:1, width: '100%',
margin: width > 600 ? ps(10) : 0 height: '100%',
flex: 1,
margin: width > 600 ? ps(10) : 0,
}}> }}>
<Button mode="elevated" onPress={() => dispatch(getNotif)}> <Button mode="elevated" onPress={() => dispatch(getNotif)}>
Refresh Refresh
@ -43,6 +51,6 @@ export default function NotifViewRemote(){
<ScrollView> <ScrollView>
<NotifList type="remote" notifs={clips} /> <NotifList type="remote" notifs={clips} />
</ScrollView> </ScrollView>
</View>; </View>
);
} }

View File

@ -1,31 +1,38 @@
import { Platform, View, useWindowDimensions } from "react-native"; import {Platform, View, useWindowDimensions} from 'react-native';
import SignIn from "../components/auth/SignIn"; import SignIn from '../components/auth/SignIn';
import SignUp from "../components/auth/SignUp"; import SignUp from '../components/auth/SignUp';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'; import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs';
import { ps } from "../utils"; import {ps} from '../utils';
export default function AuthPage(){ export default function AuthPage() {
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
const Tab = createMaterialTopTabNavigator(); const Tab = createMaterialTopTabNavigator();
if (width > 700){ if (width > 700) {
return ( return (
<View style={{flexDirection:"row",justifyContent:"center",alignItems:"center",height:"100%",padding:ps(30)}}> <View
<SignIn/> style={{
<SignUp/> flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
padding: ps(30),
}}>
<SignIn />
<SignUp />
</View> </View>
);} );
else{ } else {
return( return (
<Tab.Navigator> <Tab.Navigator>
<Tab.Screen <Tab.Screen
children={() => <SignIn/>} children={() => <SignIn />}
name="Login" name="Login"
options={{title: 'Connexion'}} options={{title: 'Connexion'}}
/> />
<Tab.Screen <Tab.Screen
children={() => <SignUp/>} children={() => <SignUp />}
name="Register" name="Register"
options={{title: 'Créer un compte'}} options={{title: 'Créer un compte'}}
/> />

View File

@ -1,19 +1,25 @@
import React from "react"; import React from 'react';
import { Drawer as DrawerLayout } from 'react-native-drawer-layout'; import {Drawer as DrawerLayout} from 'react-native-drawer-layout';
import { Button, Drawer} from 'react-native-paper'; import {Button, Drawer} from 'react-native-paper';
import { Platform, View,StyleSheet, useWindowDimensions } from "react-native"; import {Platform, View, StyleSheet, useWindowDimensions} from 'react-native';
import { Modal, Text, Portal } from 'react-native-paper'; import {Modal, Text, Portal} from 'react-native-paper';
import { useDispatch } from 'react-redux'; import {useDispatch} from 'react-redux';
import { disconnect, localClipClear, localNotifClear, remoteClipClear, remoteNotifClear } from "../redux/reducers"; import {
import { ReactNavigationDracula as t } from "../themes"; disconnect,
import ClipView from "../components/clip/ClipView"; localClipClear,
import Settings from "./Settings"; localNotifClear,
import NotifView from "../components/notif/NotifView"; remoteClipClear,
remoteNotifClear,
} from '../redux/reducers';
import {ReactNavigationDracula as t} from '../themes';
import ClipView from '../components/clip/ClipView';
import Settings from './Settings';
import NotifView from '../components/notif/NotifView';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
modal: { modal: {
display:"flex", display: 'flex',
flexDirection:"column", flexDirection: 'column',
padding: 10, padding: 10,
gap: 10, gap: 10,
alignItems: 'center', alignItems: 'center',
@ -21,82 +27,83 @@ const styles = StyleSheet.create({
}, },
}); });
export default function ClipPage(){ export default function ClipPage() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [visible, setVisible] = React.useState(false); const [visible, setVisible] = React.useState(false);
const [active, setActive] = React.useState('clips'); const [active, setActive] = React.useState('clips');
const dispatch = useDispatch() const dispatch = useDispatch();
const hideModal = () => setVisible(false); const hideModal = () => setVisible(false);
const containerStyle = {backgroundColor: 'white', padding: 20}; const containerStyle = {backgroundColor: 'white', padding: 20};
const {height, width} = useWindowDimensions(); const {height, width} = useWindowDimensions();
function signout() {
function signout(){ dispatch(localClipClear());
dispatch(localClipClear()) dispatch(remoteClipClear());
dispatch(remoteClipClear()) dispatch(localNotifClear());
dispatch(localNotifClear()) dispatch(remoteNotifClear());
dispatch(remoteNotifClear()) dispatch(disconnect());
dispatch(disconnect())
} }
let layout = "" let layout = '';
if (width < 600) layout = "compact";
else if (width < 1200 ) layout = "medium";
else layout = "expanded";
if (width < 600) layout = 'compact';
else if (width < 1200) layout = 'medium';
else layout = 'expanded';
let style = {}; let style = {};
if (layout == "medium"){ if (layout == 'medium') {
style = StyleSheet.create({ style = StyleSheet.create({
drawer: { drawer: {
backgroundColor: t.colors.background, backgroundColor: t.colors.background,
width : 100 width: 100,
} },
}) });
} else { } else {
style = StyleSheet.create({ style = StyleSheet.create({
drawer : { drawer: {
backgroundColor: t.colors.background backgroundColor: t.colors.background,
} },
}) });
} }
let page; let page;
if (active == "clips") page = <ClipView/>; if (active == 'clips') page = <ClipView />;
if (active == "notif") page = <NotifView/>; if (active == 'notif') page = <NotifView />;
if (active == "settings") page = <Settings/>; if (active == 'settings') page = <Settings />;
return (<View style={{ return (
width:"100%", <View
height:"100%", style={{
paddingTop: Platform.OS == "android" ? 30 : 0 }}> width: '100%',
height: '100%',
paddingTop: Platform.OS == 'android' ? 30 : 0,
}}>
<Portal> <Portal>
<Modal <Modal
visible={visible} visible={visible}
onDismiss={hideModal} onDismiss={hideModal}
contentContainerStyle={containerStyle} contentContainerStyle={containerStyle}
style={styles.modal} style={styles.modal}>
>
<Text>Do you really want to sign out?</Text> <Text>Do you really want to sign out?</Text>
<Button mode="contained" onPress={hideModal}> <Button mode="contained" onPress={hideModal}>
no no
</Button> </Button>
<Button mode="contained-tonal" onPress={()=> signout()}> <Button mode="contained-tonal" onPress={() => signout()}>
yes yes
</Button> </Button>
</Modal> </Modal>
</Portal> </Portal>
<DrawerLayout <DrawerLayout
swipeEdgeWidth={70} swipeEdgeWidth={70}
drawerType={layout == "compact" ? "slide":"permanent"} drawerType={layout == 'compact' ? 'slide' : 'permanent'}
open={open} open={open}
onOpen={() => setOpen(true)} onOpen={() => setOpen(true)}
onClose={() => setOpen(false)} onClose={() => setOpen(false)}
drawerStyle={style.drawer} drawerStyle={style.drawer}
renderDrawerContent={() => { renderDrawerContent={() => {
if (layout != "medium"){ if (layout != 'medium') {
return <> return (
<>
<Drawer.Section title=" "> <Drawer.Section title=" ">
<Drawer.Item <Drawer.Item
icon="clipboard-arrow-down" icon="clipboard-arrow-down"
@ -104,7 +111,7 @@ export default function ClipPage(){
active={active === 'clips'} active={active === 'clips'}
onPress={() => { onPress={() => {
setActive('clips'); setActive('clips');
setOpen(false) setOpen(false);
}} }}
/> />
<Drawer.Item <Drawer.Item
@ -113,7 +120,7 @@ export default function ClipPage(){
active={active === 'notif'} active={active === 'notif'}
onPress={() => { onPress={() => {
setActive('notif'); setActive('notif');
setOpen(false) setOpen(false);
}} }}
/> />
<Drawer.Item <Drawer.Item
@ -122,7 +129,7 @@ export default function ClipPage(){
active={active === 'settings'} active={active === 'settings'}
onPress={() => { onPress={() => {
setActive('settings'); setActive('settings');
setOpen(false) setOpen(false);
}} }}
/> />
</Drawer.Section> </Drawer.Section>
@ -135,8 +142,10 @@ export default function ClipPage(){
/> />
</Drawer.Section> </Drawer.Section>
</> </>
}else{ );
return <View style={{alignItems:"center", height:"100%"}}> } else {
return (
<View style={{alignItems: 'center', height: '100%'}}>
<Drawer.Section title=" "> <Drawer.Section title=" ">
<Drawer.CollapsedItem <Drawer.CollapsedItem
focusedIcon="clipboard-arrow-down" focusedIcon="clipboard-arrow-down"
@ -145,7 +154,7 @@ export default function ClipPage(){
active={active === 'clips'} active={active === 'clips'}
onPress={() => { onPress={() => {
setActive('clips'); setActive('clips');
setOpen(false) setOpen(false);
}} }}
/> />
<Drawer.CollapsedItem <Drawer.CollapsedItem
@ -155,7 +164,7 @@ export default function ClipPage(){
active={active === 'notif'} active={active === 'notif'}
onPress={() => { onPress={() => {
setActive('notif'); setActive('notif');
setOpen(false) setOpen(false);
}} }}
/> />
<Drawer.CollapsedItem <Drawer.CollapsedItem
@ -165,7 +174,7 @@ export default function ClipPage(){
active={active === 'settings'} active={active === 'settings'}
onPress={() => { onPress={() => {
setActive('settings'); setActive('settings');
setOpen(false) setOpen(false);
}} }}
/> />
</Drawer.Section> </Drawer.Section>
@ -178,9 +187,9 @@ export default function ClipPage(){
/> />
</Drawer.Section> </Drawer.Section>
</View> </View>
);
} }
}} }}>
>
{page} {page}
</DrawerLayout> </DrawerLayout>
</View> </View>

View File

@ -1,21 +1,24 @@
import { View, Text } from "react-native"; import {View, Text} from 'react-native';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import { ps } from "../utils"; import {ps} from '../utils';
import { ReactNavigationDracula as t } from "../themes"; import {ReactNavigationDracula as t} from '../themes';
export default function IntroPage({navigation}){ export default function IntroPage({navigation}) {
return( return (
<View style={{ <View
alignItems:"center", style={{
justifyContent:"center", alignItems: 'center',
gap:ps(6), justifyContent: 'center',
flex:1, gap: ps(6),
margin:ps(16), flex: 1,
flexDirection:'column'}}> margin: ps(16),
<Text style={{ flexDirection: 'column',
fontSize:20, }}>
textAlign:"center", <Text
color: t.colors.text style={{
fontSize: 20,
textAlign: 'center',
color: t.colors.text,
}}> }}>
Salut, bienvenue dans ClipSync :) connecte toi pour commencer Salut, bienvenue dans ClipSync :) connecte toi pour commencer
</Text> </Text>

View File

@ -1,26 +1,29 @@
import { ScrollView } from "react-native"; import {ScrollView} from 'react-native';
import { View, Text } from "react-native"; import {View, Text} from 'react-native';
import { Button } from 'react-native-paper'; import {Button} from 'react-native-paper';
import { ps } from "../utils"; import {ps} from '../utils';
import { ReactNavigationDracula as t } from "../themes"; import {ReactNavigationDracula as t} from '../themes';
export default function Settings(){ export default function Settings() {
return (
return( <View
<View style={{ style={{
width: "100%", width: '100%',
height: "100%", height: '100%',
alignItems:"center", alignItems: 'center',
justifyContent:"center", justifyContent: 'center',
gap:ps(6), gap: ps(6),
flex:1, flex: 1,
flexDirection:'column'}}> flexDirection: 'column',
<Text style={{ }}>
fontSize:20, <Text
textAlign:"center", style={{
color: t.colors.text fontSize: 20,
textAlign: 'center',
color: t.colors.text,
}}> }}>
Pas encore pret mais on y travaille .w. Pas encore pret mais on y travaille .w.
</Text> </Text>
</View>) </View>
);
} }

View File

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { Button, Text } from 'react-native'; import {Button, Text} from 'react-native';
import { Drawer } from 'react-native-drawer-layout'; import {Drawer} from 'react-native-drawer-layout';
export default function DrawerExample() { export default function DrawerExample() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
@ -12,10 +12,9 @@ export default function DrawerExample() {
onClose={() => setOpen(false)} onClose={() => setOpen(false)}
renderDrawerContent={() => { renderDrawerContent={() => {
return <Text>Drawer content</Text>; return <Text>Drawer content</Text>;
}} }}>
>
<Button <Button
onPress={() => setOpen((prevOpen) => !prevOpen)} onPress={() => setOpen(prevOpen => !prevOpen)}
title={`${open ? 'Close' : 'Open'} drawer`} title={`${open ? 'Close' : 'Open'} drawer`}
/> />
</Drawer> </Drawer>

View File

@ -1 +0,0 @@

View File

@ -1,12 +1,12 @@
import { applyMiddleware,createSlice } from "@reduxjs/toolkit"; import {applyMiddleware, createSlice} from '@reduxjs/toolkit';
console.log(applyMiddleware); console.log(applyMiddleware);
export const userSlice = createSlice({ export const userSlice = createSlice({
name: 'user', name: 'user',
initialState: { initialState: {
token: "", token: '',
username:"", username: '',
}, },
reducers: { reducers: {
login: (state, action) => { login: (state, action) => {
@ -14,12 +14,11 @@ export const userSlice = createSlice({
state.username = action.payload.username; state.username = action.payload.username;
}, },
disconnect: state => { disconnect: state => {
state.token = ""; state.token = '';
state.username = ""; state.username = '';
}
}, },
},
}) });
export const {login, disconnect} = userSlice.actions; export const {login, disconnect} = userSlice.actions;
@ -31,22 +30,23 @@ export const {login, disconnect} = userSlice.actions;
export const localClipsSlice = createSlice({ export const localClipsSlice = createSlice({
name: 'localClips', name: 'localClips',
initialState: { initialState: {
localClip:[], localClip: [],
}, },
reducers: { reducers: {
localClipAddToList: (state,action) => { localClipAddToList: (state, action) => {
state.localClip = [...state.localClip,action.payload] state.localClip = [...state.localClip, action.payload];
}, },
localClipRemoveFromList: (state,action) => { localClipRemoveFromList: (state, action) => {
state.localClip = state.localClip.filter(e => e !== action.payload) state.localClip = state.localClip.filter(e => e !== action.payload);
}, },
localClipClear : (state,action) =>{ localClipClear: (state, action) => {
state.localClip = [] state.localClip = [];
} },
} },
}) });
export const {localClipAddToList, localClipRemoveFromList, localClipClear} = localClipsSlice.actions; export const {localClipAddToList, localClipRemoveFromList, localClipClear} =
localClipsSlice.actions;
// Remote clip structure // Remote clip structure
// [ // [
@ -56,62 +56,66 @@ export const {localClipAddToList, localClipRemoveFromList, localClipClear} = loc
export const remoteClipsSlice = createSlice({ export const remoteClipsSlice = createSlice({
name: 'remoteClips', name: 'remoteClips',
initialState: { initialState: {
remoteClip:[], remoteClip: [],
}, },
reducers: { reducers: {
remoteClipAddToList: (state,action) => { remoteClipAddToList: (state, action) => {
console.log(action.payload); console.log(action.payload);
state.remoteClip = action.payload state.remoteClip = action.payload;
}, },
remoteClipRemoveFromList: (state,action) => { remoteClipRemoveFromList: (state, action) => {
state.remoteClip = state.remoteClip.filter(e => e !== action.payload); state.remoteClip = state.remoteClip.filter(e => e !== action.payload);
}, },
remoteClipClear : (state,action) =>{ remoteClipClear: (state, action) => {
state.remoteClip = [] state.remoteClip = [];
}, },
},
});
} export const {remoteClipAddToList, remoteClipRemoveFromList, remoteClipClear} =
}) remoteClipsSlice.actions;
export const {remoteClipAddToList, remoteClipRemoveFromList, remoteClipClear} = remoteClipsSlice.actions;
export const localNotifsSlice = createSlice({ export const localNotifsSlice = createSlice({
name: 'localNotifs', name: 'localNotifs',
initialState: { initialState: {
localNotif:[], localNotif: [],
}, },
reducers: { reducers: {
localNotifAddToList: (state,action) => { localNotifAddToList: (state, action) => {
state.localNotif = [...state.localNotif,action.payload] state.localNotif = [...state.localNotif, action.payload];
}, },
localNotifRemoveFromList: (state,action) => { localNotifRemoveFromList: (state, action) => {
state.localNotif = state.localNotif.filter(e => e !== action.payload) state.localNotif = state.localNotif.filter(e => e !== action.payload);
}, },
localNotifClear : (state,action) =>{ localNotifClear: (state, action) => {
state.localNotif = [] state.localNotif = [];
} },
} },
}) });
export const {localNotifAddToList, localNotifRemoveFromList, localNotifClear} = localNotifsSlice.actions; export const {localNotifAddToList, localNotifRemoveFromList, localNotifClear} =
localNotifsSlice.actions;
export const remoteNotifsSlice = createSlice({ export const remoteNotifsSlice = createSlice({
name: 'remoteNotifs', name: 'remoteNotifs',
initialState: { initialState: {
remoteNotif:[], remoteNotif: [],
}, },
reducers: { reducers: {
remoteNotifAddToList: (state,action) => { remoteNotifAddToList: (state, action) => {
state.remoteNotif = [...action.payload] state.remoteNotif = [...action.payload];
}, },
remoteNotifRemoveFromList: (state,action) => { remoteNotifRemoveFromList: (state, action) => {
state.remoteNotif = state.remoteNotif.filter(e => e !== action.payload); state.remoteNotif = state.remoteNotif.filter(e => e !== action.payload);
}, },
remoteNotifClear : (state,action) =>{ remoteNotifClear: (state, action) => {
state.remoteNotif = [] state.remoteNotif = [];
} },
} },
}) });
export const {remoteNotifAddToList, remoteNotifRemoveFromList, remoteNotifClear} = remoteNotifsSlice.actions; export const {
remoteNotifAddToList,
remoteNotifRemoveFromList,
remoteNotifClear,
} = remoteNotifsSlice.actions;

View File

@ -1,29 +1,29 @@
import { applyMiddleware,configureStore } from '@reduxjs/toolkit' import {applyMiddleware, configureStore} from '@reduxjs/toolkit';
import { combineReducers } from '@reduxjs/toolkit'; import {combineReducers} from '@reduxjs/toolkit';
import { userSlice, localClipsSlice ,remoteClipsSlice } from './reducers'; import {userSlice, localClipsSlice, remoteClipsSlice} from './reducers';
import { localNotifsSlice,remoteNotifsSlice } from './reducers'; import {localNotifsSlice, remoteNotifsSlice} from './reducers';
import { persistStore, persistReducer } from 'redux-persist' import {persistStore, persistReducer} from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
const persistConfig = { const persistConfig = {
key: "root", key: 'root',
storage: AsyncStorage, storage: AsyncStorage,
}; };
const rootReducer = combineReducers({ const rootReducer = combineReducers({
user:userSlice.reducer, user: userSlice.reducer,
localClip:localClipsSlice.reducer, localClip: localClipsSlice.reducer,
remoteClip:remoteClipsSlice.reducer, remoteClip: remoteClipsSlice.reducer,
localNotif:localNotifsSlice.reducer, localNotif: localNotifsSlice.reducer,
remoteNotif:remoteNotifsSlice.reducer remoteNotif: remoteNotifsSlice.reducer,
}); });
const persistedReducer = persistReducer(persistConfig, rootReducer) const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({ const store = configureStore({
reducer: persistedReducer reducer: persistedReducer,
}) });
const persistor = persistStore(store) const persistor = persistStore(store);
export {store, persistor}; export {store, persistor};

View File

@ -1,4 +1,4 @@
import { MD3DarkTheme, Surface } from 'react-native-paper'; import {MD3DarkTheme, Surface} from 'react-native-paper';
export const Material3Dracula = { export const Material3Dracula = {
...MD3DarkTheme, ...MD3DarkTheme,
@ -10,8 +10,8 @@ export const Material3Dracula = {
surface: '#44475a', surface: '#44475a',
elevation: { elevation: {
...MD3DarkTheme.colors.elevation, ...MD3DarkTheme.colors.elevation,
level1: "#44475A" level1: '#44475A',
} },
}, },
}; };

View File

@ -1,11 +1,12 @@
import { PixelRatio,StyleSheet } from "react-native"; import {PixelRatio, StyleSheet} from 'react-native';
export const ps = (lp:number) => PixelRatio.getPixelSizeForLayoutSize(PixelRatio.roundToNearestPixel(lp)); export const ps = (lp: number) =>
PixelRatio.getPixelSizeForLayoutSize(PixelRatio.roundToNearestPixel(lp));
export const style = StyleSheet.create({ export const style = StyleSheet.create({
default : { default: {
margin: PixelRatio.getPixelSizeForLayoutSize(8), margin: PixelRatio.getPixelSizeForLayoutSize(8),
marginTop : PixelRatio.getPixelSizeForLayoutSize(8), marginTop: PixelRatio.getPixelSizeForLayoutSize(8),
marginLeft : PixelRatio.getPixelSizeForLayoutSize(8) marginLeft: PixelRatio.getPixelSizeForLayoutSize(8),
} },
}) });