add simple buttons for settings
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import {Slot} from "expo-router";
|
||||
|
||||
export default function App() {
|
||||
return <Slot/>;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,5 @@ export default function TabLayout() {
|
||||
/>
|
||||
</Tabs>
|
||||
</AuthenticatedWrapper>
|
||||
|
||||
)
|
||||
;
|
||||
);
|
||||
}
|
||||
|
||||
+23
-1
@@ -1,13 +1,35 @@
|
||||
import ThemedHeader from "@/src/components/themed/ThemedHeader";
|
||||
import React from "react";
|
||||
import React, {useState} from "react";
|
||||
import ThemedBackground from "@/src/components/themed/ThemedBackground";
|
||||
import ChangePasswordModal from "@/src/components/ChangePasswordModal";
|
||||
import ThemeToggleButton from "@/src/components/ThemeToggleButton";
|
||||
import SpotifyAuthButton from "@/src/components/SpotifyAuthButton";
|
||||
import {Token} from "@/src/services/RestService";
|
||||
import {Text} from 'react-native-paper';
|
||||
|
||||
import * as WebBrowser from "expo-web-browser";
|
||||
import {useAuth} from "@/src/context/AuthProvider";
|
||||
|
||||
WebBrowser.maybeCompleteAuthSession();
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const {token: jwtToken} = useAuth();
|
||||
const [token, setToken] = useState<Token | null>(null);
|
||||
|
||||
const handleAuthSuccess = (token: Token) => {
|
||||
setToken(token);
|
||||
console.log('Erhaltener Authentifizierungscode:', token);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemedBackground>
|
||||
<ThemedHeader>
|
||||
Settings
|
||||
</ThemedHeader>
|
||||
<ChangePasswordModal/>
|
||||
<ThemeToggleButton/>
|
||||
<SpotifyAuthButton onAuthSuccess={handleAuthSuccess} jwtToken={jwtToken!}/>
|
||||
{token && <Text>Erhaltener Code: {token.access_token}</Text>}
|
||||
</ThemedBackground>
|
||||
);
|
||||
}
|
||||
|
||||
Generated
+24
@@ -30,6 +30,7 @@
|
||||
"react-dom": "18.3.1",
|
||||
"react-native": "0.76.3",
|
||||
"react-native-gesture-handler": "~2.21.2",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-paper": "^5.12.5",
|
||||
"react-native-reanimated": "~3.16.3",
|
||||
"react-native-status-bar-height": "^2.6.0",
|
||||
@@ -15320,6 +15321,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-animatable": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz",
|
||||
"integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-gesture-handler": {
|
||||
"version": "2.21.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.21.2.tgz",
|
||||
@@ -15360,6 +15370,20 @@
|
||||
"react-native": ">=0.73.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-modal": {
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz",
|
||||
"integrity": "sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.6.2",
|
||||
"react-native-animatable": "1.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": ">=0.65.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-paper": {
|
||||
"version": "5.12.5",
|
||||
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.12.5.tgz",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"react-dom": "18.3.1",
|
||||
"react-native": "0.76.3",
|
||||
"react-native-gesture-handler": "~2.21.2",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-paper": "^5.12.5",
|
||||
"react-native-reanimated": "~3.16.3",
|
||||
"react-native-status-bar-height": "^2.6.0",
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import React, {useState} from "react";
|
||||
import {Paragraph, Button} from "react-native-paper";
|
||||
import ThemedTextInput from "@/src/components/themed/ThemedTextInput";
|
||||
import {useTheme} from "@/src/context/ThemeProvider";
|
||||
import Modal from "react-native-modal";
|
||||
import {View, StyleSheet} from "react-native";
|
||||
|
||||
export default function ChangePasswordModal() {
|
||||
const {theme} = useTheme();
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirmPassword, setConfirmPassword] = useState("");
|
||||
const [error, setError] = useState<{ message: string } | null>(null);
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (password !== confirmPassword) {
|
||||
setError({message: "Passwörter stimmen nicht überein!"});
|
||||
return;
|
||||
}
|
||||
console.log("Passwort erfolgreich geändert!");
|
||||
|
||||
};
|
||||
const resetModal = () => {
|
||||
setIsVisible(false);
|
||||
setError(null);
|
||||
setPassword("");
|
||||
setConfirmPassword("");
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button mode="outlined" onPress={() => setIsVisible(true)}>
|
||||
Passwort ändern
|
||||
</Button>
|
||||
<Modal isVisible={isVisible} onBackdropPress={resetModal}>
|
||||
<View style={styles.modalContent}>
|
||||
<Paragraph>Passwort ändern</Paragraph>
|
||||
{error && (
|
||||
<View style={[styles.errorBox, {backgroundColor: theme.colors.error}]}>
|
||||
<Paragraph style={{color: theme.colors.onError}}>{error.message}</Paragraph>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<ThemedTextInput
|
||||
label="Passwort"
|
||||
returnKeyType="next"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
/>
|
||||
<ThemedTextInput
|
||||
label="Passwort bestätigen"
|
||||
returnKeyType="done"
|
||||
value={confirmPassword}
|
||||
onChangeText={setConfirmPassword}
|
||||
secureTextEntry
|
||||
/>
|
||||
|
||||
<View style={styles.buttonGroup}>
|
||||
<Button mode="contained" onPress={handleConfirm}>
|
||||
Bestätigen
|
||||
</Button>
|
||||
<Button mode="elevated" onPress={resetModal}>
|
||||
Abbrechen
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContent: {
|
||||
padding: 16,
|
||||
borderRadius: 8,
|
||||
},
|
||||
errorBox: {
|
||||
marginBottom: 8,
|
||||
marginTop: 8,
|
||||
padding: 8,
|
||||
},
|
||||
buttonGroup: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
marginTop: 16,
|
||||
},
|
||||
});
|
||||
@@ -5,10 +5,11 @@ import ThemedButton from "@/src/components/themed/ThemedButton";
|
||||
|
||||
interface SpotifyAuthButtonProps {
|
||||
onAuthSuccess: (token: Token) => void;
|
||||
jwtToken: string;
|
||||
}
|
||||
|
||||
const SpotifyAuthButton = ({onAuthSuccess}: SpotifyAuthButtonProps) => {
|
||||
const {promptAuth, isReady, error} = useSpotifyAuth(onAuthSuccess);
|
||||
const SpotifyAuthButton = ({onAuthSuccess, jwtToken}: SpotifyAuthButtonProps) => {
|
||||
const {promptAuth, isReady, error} = useSpotifyAuth(onAuthSuccess, jwtToken);
|
||||
|
||||
if (error) {
|
||||
console.error('Spotify Auth Error:', error);
|
||||
|
||||
@@ -14,7 +14,8 @@ interface UseSpotifyAuthResult {
|
||||
}
|
||||
|
||||
export const useSpotifyAuth = (
|
||||
onAuthSuccess: (token: Token) => void
|
||||
onAuthSuccess: (token: Token) => void,
|
||||
jwtToken: string,
|
||||
): UseSpotifyAuthResult => {
|
||||
const [request, response, promptAsync] = useAuthRequest(
|
||||
{
|
||||
@@ -34,7 +35,7 @@ export const useSpotifyAuth = (
|
||||
if (response?.type === 'success') {
|
||||
try {
|
||||
const {code} = response.params;
|
||||
const token = (await RestService.exchangeSpotifyCodeForToken(code,"TODO")).token;
|
||||
const token = (await RestService.exchangeSpotifyCodeForToken(code,jwtToken)).token;
|
||||
console.log('Token:', token);
|
||||
onAuthSuccess(token);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user