Compare commits
2 Commits
2f99cf1500
...
89c8a4b985
| Author | SHA1 | Date | |
|---|---|---|---|
|
89c8a4b985
|
|||
|
534f844196
|
@@ -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")
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.ShapPlanner">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name=".activities.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.ShapPlanner">
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package de.miaurizius.shap_planner
|
||||
|
||||
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.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import de.miaurizius.shap_planner.ui.theme.ShapPlannerTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
ShapPlannerTheme {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = "Hello $name!",
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
ShapPlannerTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
||||
@@ -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<Boolean> = context.dataStore.data.map { prefs -> prefs[UserPreferencesKeys.IS_LOGGED_IN] ?: false }
|
||||
val lastUserLoginFlow: Flow<String?> = context.dataStore.data.map { prefs -> prefs[UserPreferencesKeys.LAST_USER_ID] }
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package de.miaurizius.shap_planner.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
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.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.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()
|
||||
|
||||
val prefs = UserPreferences(this)
|
||||
val viewModel = LoginViewModel(prefs)
|
||||
|
||||
setContent {
|
||||
ShapPlannerTheme {
|
||||
val isLoggedIn by viewModel.isLoggedIn.collectAsState()
|
||||
if(isLoggedIn) MainScreen()
|
||||
else LoginScreen { userId -> viewModel.login(userId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainScreen() {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text("Willkommen zurück!")
|
||||
Button(onClick = { /* TODO: Logout */ }) {
|
||||
Text("Logout")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.miaurizius.shap_planner.entities
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
data class Expense (
|
||||
val id: UUID,
|
||||
val amt: Double,
|
||||
val desc: String,
|
||||
|
||||
val payerId: UUID,
|
||||
val debtors: List<User>
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.miaurizius.shap_planner.entities
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
data class User (
|
||||
val id: UUID,
|
||||
val name: String,
|
||||
)
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user