diff --git a/mobile-app/app/(tabs)/index.tsx b/mobile-app/app/(tabs)/index.tsx index e21accbaa..1432bcce5 100644 --- a/mobile-app/app/(tabs)/index.tsx +++ b/mobile-app/app/(tabs)/index.tsx @@ -11,7 +11,7 @@ import { SrpUtility } from '@/utils/SrpUtility'; import EncryptionUtility from '@/utils/EncryptionUtility'; import { ApiAuthError } from '@/utils/types/errors/ApiAuthError'; import { useWebApi } from '@/context/WebApiContext'; - +import { Credential } from '@/utils/types/Credential'; export default function HomeScreen() { const [credentials, setCredentials] = useState({ username: '', @@ -99,11 +99,15 @@ export default function HomeScreen() { throw new Error('Login failed -- no token returned'); } + console.log('validationResponse.token', validationResponse.token); + // Try to get latest vault manually providing auth token. const vaultResponseJson = await webApi.authFetch('Vault', { method: 'GET', headers: { 'Authorization': `Bearer ${validationResponse.token.token}` } }); + console.log('vaultResponseJson', vaultResponseJson); + const vaultError = webApi.validateVaultResponse(vaultResponseJson); if (vaultError) { console.error('vaultError', vaultError); @@ -112,15 +116,22 @@ export default function HomeScreen() { return; } + console.log('vaultResponseJson', vaultResponseJson); + // All is good. Store auth info which is required to make requests to the web API. await authContext.setAuthTokens(credentials.username, validationResponse.token.token, validationResponse.token.refreshToken); + console.log('auth tokens set'); // Initialize the SQLite context with the new vault data. await dbContext.initializeDatabase(vaultResponseJson, passwordHashBase64); + console.log('database initialized'); + // Set logged in status to true which refreshes the app. await authContext.login(); + console.log('logged in'); + setIsLoading(false); } catch (err) { // Show API authentication errors as-is. @@ -204,7 +215,31 @@ export default function HomeScreen() { } }; - if (!isAuthenticated) { + + const [credentialsList, setCredentialsList] = useState([]); + const [isLoadingCredentials, setIsLoadingCredentials] = useState(false); + + useEffect(() => { + if (!isAuthenticated || !isDatabaseAvailable) { + return; + } + + const loadCredentials = async () => { + setIsLoadingCredentials(true); + try { + const credentialsList = await dbContext.sqliteClient!.getAllCredentials(); + console.log('credentialsList', credentialsList); + setCredentialsList(credentialsList); + } catch (err) { + console.error('Error loading credentials:', err); + } + setIsLoadingCredentials(false); + }; + + loadCredentials(); + }, [isAuthenticated, isDatabaseAvailable]); + + if (!isAuthenticated || !isDatabaseAvailable) { return ( @@ -312,7 +347,25 @@ export default function HomeScreen() { AliasVault - Logged in + Your Credentials + {isLoadingCredentials ? ( + + ) : ( + item.Id} + renderItem={({ item }) => ( + + {item.ServiceName ?? 'Unknown Service'} + {item.Username && Username: {item.Username}} + {item.Alias?.Email && Email: {item.Alias.Email}} + + )} + ListEmptyComponent={ + No credentials found + } + /> + )} @@ -412,4 +465,38 @@ const styles = StyleSheet.create({ textAlign: 'center', marginTop: 16, }, + logoutButton: { + backgroundColor: '#f97316', + padding: 12, + borderRadius: 8, + alignItems: 'center', + }, + logoutButtonText: { + color: '#fff', + fontSize: 16, + fontWeight: '600', + }, + credentialItem: { + backgroundColor: '#fff', + padding: 16, + borderRadius: 8, + marginBottom: 8, + borderWidth: 1, + borderColor: '#d1d5db', + }, + serviceName: { + fontSize: 16, + fontWeight: '600', + marginBottom: 4, + }, + credentialText: { + fontSize: 14, + color: '#4b5563', + }, + emptyText: { + textAlign: 'center', + fontSize: 16, + color: '#6b7280', + marginTop: 24, + }, }); diff --git a/mobile-app/app/(tabs)/settings.tsx b/mobile-app/app/(tabs)/settings.tsx new file mode 100644 index 000000000..126db5549 --- /dev/null +++ b/mobile-app/app/(tabs)/settings.tsx @@ -0,0 +1,62 @@ +import { StyleSheet, Button, SafeAreaView, TouchableOpacity } from 'react-native'; +import { ThemedText } from '@/components/ThemedText'; +import { ThemedView } from '@/components/ThemedView'; +import { useWebApi } from '@/context/WebApiContext'; +import { router } from 'expo-router'; + +export default function SettingsScreen() { + const webApi = useWebApi(); + + const handleLogout = async () => { + await webApi.logout(); + router.replace('/'); + }; + + return ( + + + + Settings + + + + Logout + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + content: { + flex: 1, + padding: 16, + }, + titleContainer: { + flexDirection: 'row', + alignItems: 'center', + gap: 8, + marginBottom: 16, + }, + settingsContainer: { + flex: 1, + gap: 8, + }, + logoutButton: { + backgroundColor: '#FF3B30', + padding: 16, + borderRadius: 8, + }, + logoutButtonText: { + color: '#FFFFFF', + fontSize: 16, + fontWeight: 'bold', + }, +}); \ No newline at end of file