diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 086f40d..e99e79f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -40,6 +40,8 @@ android { } dependencies { + + //Android Studio Auto-Gen implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) @@ -55,4 +57,7 @@ dependencies { androidTestImplementation(libs.androidx.compose.ui.test.junit4) debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.test.manifest) + + //Manually added + implementation("androidx.datastore:datastore-preferences:1.2.0") } \ No newline at end of file diff --git a/app/src/main/java/de/miaurizius/shap_planner/UserPreferences.kt b/app/src/main/java/de/miaurizius/shap_planner/UserPreferences.kt new file mode 100644 index 0000000..852816d --- /dev/null +++ b/app/src/main/java/de/miaurizius/shap_planner/UserPreferences.kt @@ -0,0 +1,39 @@ +package de.miaurizius.shap_planner + +import android.content.Context +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +val Context.dataStore by preferencesDataStore(name = "user_prefs") + +object UserPreferencesKeys { + val IS_LOGGED_IN = booleanPreferencesKey("is_logged_in") + val LAST_USER_ID = stringPreferencesKey("last_user_id") +} + +class UserPreferences(private val context: Context) { + + //Stave status + suspend fun saveLogin(userId: String) { + context.dataStore.edit { prefs -> + prefs[UserPreferencesKeys.IS_LOGGED_IN] = true + prefs[UserPreferencesKeys.LAST_USER_ID] = userId; + } + } + + //Logout + suspend fun clearLogin() { + context.dataStore.edit { prefs -> + prefs[UserPreferencesKeys.IS_LOGGED_IN] = false + prefs[UserPreferencesKeys.LAST_USER_ID] = "" + } + } + + //Get state + val isLoggedInFlow: Flow = context.dataStore.data.map { prefs -> prefs[UserPreferencesKeys.IS_LOGGED_IN] ?: false } + val lastUserLoginFlow: Flow = context.dataStore.data.map { prefs -> prefs[UserPreferencesKeys.LAST_USER_ID] } +} \ No newline at end of file diff --git a/app/src/main/java/de/miaurizius/shap_planner/activities/MainActivity.kt b/app/src/main/java/de/miaurizius/shap_planner/activities/MainActivity.kt index c288778..d2c1e4e 100644 --- a/app/src/main/java/de/miaurizius/shap_planner/activities/MainActivity.kt +++ b/app/src/main/java/de/miaurizius/shap_planner/activities/MainActivity.kt @@ -4,44 +4,68 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold +import androidx.compose.material3.Button import androidx.compose.material3.Text +import androidx.compose.material3.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import de.miaurizius.shap_planner.UserPreferences import de.miaurizius.shap_planner.ui.theme.ShapPlannerTheme +import de.miaurizius.shap_planner.viewmodels.LoginViewModel class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() +// enableEdgeToEdge() + + val prefs = UserPreferences(this) + val viewModel = LoginViewModel(prefs) + setContent { ShapPlannerTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - Greeting( - name = "Android", - modifier = Modifier.padding(innerPadding) - ) - } + val isLoggedIn by viewModel.isLoggedIn.collectAsState() + if(isLoggedIn) MainScreen() + else LoginScreen { userId -> viewModel.login(userId) } } } } } @Composable -fun Greeting(name: String, modifier: Modifier = Modifier) { - Text( - text = "Hello $name!", - modifier = modifier - ) +fun MainScreen() { + Column(modifier = Modifier.padding(16.dp)) { + Text("Willkommen zurück!") + Button(onClick = { /* TODO: Logout */ }) { + Text("Logout") + } + } } -@Preview(showBackground = true) @Composable -fun GreetingPreview() { - ShapPlannerTheme { - Greeting("Android") +fun LoginScreen(onLogin: (String) -> Unit) { + var userId by remember { mutableStateOf("") } + + Column(modifier = Modifier.padding(16.dp)) { + Text("Bitte anmelden") + Spacer(modifier = Modifier.height(8.dp)) + TextField( + value = userId, + onValueChange = { userId = it }, + label = { Text("User ID") } + ) + Spacer(modifier = Modifier.height(8.dp)) + Button(onClick = { if(userId.isNotEmpty()) onLogin(userId) }) { + Text("Login") + } } } \ No newline at end of file diff --git a/app/src/main/java/de/miaurizius/shap_planner/viewmodels/LoginViewModel.kt b/app/src/main/java/de/miaurizius/shap_planner/viewmodels/LoginViewModel.kt new file mode 100644 index 0000000..e1ed193 --- /dev/null +++ b/app/src/main/java/de/miaurizius/shap_planner/viewmodels/LoginViewModel.kt @@ -0,0 +1,23 @@ +package de.miaurizius.shap_planner.viewmodels + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import de.miaurizius.shap_planner.UserPreferences +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch + +class LoginViewModel(private val prefs: UserPreferences) : ViewModel() { + + val isLoggedIn = prefs.isLoggedInFlow.stateIn(viewModelScope, SharingStarted.Lazily, false) + val lastUserId = prefs.lastUserLoginFlow.stateIn(viewModelScope, SharingStarted.Lazily, null) + + fun login(userId: String) { + viewModelScope.launch { prefs.saveLogin(userId) } + } + + fun logout() { + viewModelScope.launch { prefs.clearLogin() } + } + +} \ No newline at end of file