Extended Login and UI</div>
The login process has been expanded to include fields for Server URL, Username, and Password, replacing the previous User ID-only login. The UI now utilizes `navigationBarsPadding` to prevent overlap with system navigation elements on the Login, Account Selection, and generic screens. The `Account` entity has been updated to include a `serverUrl`.
This commit is contained in:
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Spacer
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
@@ -65,11 +66,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
!isLoggedIn || accountList.isEmpty() -> {
|
!isLoggedIn || accountList.isEmpty() -> {
|
||||||
LoginScreen { userId ->
|
LoginScreen { serverUrl, username, password -> loginViewModel.login(serverUrl, username, password, mainViewModel) }
|
||||||
val acc = Account(userId, "MiauRizius", "Pfadi-WG") //TODO: get data from backend
|
|
||||||
mainViewModel.addAccount(acc)
|
|
||||||
loginViewModel.login(acc.id.toString())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedAccount != null -> {
|
selectedAccount != null -> {
|
||||||
@@ -99,7 +96,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
@Composable
|
@Composable
|
||||||
fun AccountSelectionScreen(accounts: List<Account>, onAccountClick: (Account) -> Unit, onAddAccountClick: () -> Unit) {
|
fun AccountSelectionScreen(accounts: List<Account>, onAccountClick: (Account) -> Unit, onAddAccountClick: () -> Unit) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.fillMaxSize().padding(16.dp).statusBarsPadding(),
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(16.dp)
|
||||||
|
.statusBarsPadding()
|
||||||
|
.navigationBarsPadding(),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
@@ -131,19 +132,44 @@ fun AccountSelectionScreen(accounts: List<Account>, onAccountClick: (Account) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LoginScreen(onLogin: (UUID) -> Unit) {
|
fun LoginScreen(onLogin: (String, String, String) -> Unit) {
|
||||||
var userId by remember { mutableStateOf("") }
|
var serverUrl by remember { mutableStateOf("") }
|
||||||
|
var username by remember { mutableStateOf("") }
|
||||||
|
var password by remember { mutableStateOf("") }
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(16.dp).statusBarsPadding()) {
|
Column(modifier = Modifier.padding(16.dp).statusBarsPadding().navigationBarsPadding()) {
|
||||||
Text("Bitte anmelden")
|
Text("Bitte anmelden")
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
//Home-Server
|
||||||
TextField(
|
TextField(
|
||||||
value = userId,
|
value = serverUrl,
|
||||||
onValueChange = { userId = it },
|
onValueChange = { serverUrl = it },
|
||||||
label = { Text("User ID") }
|
label = { Text("Server-URL") }
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Button(onClick = { if(userId.isNotEmpty()) onLogin(UUID.fromString(userId)) }) {
|
|
||||||
|
//Username
|
||||||
|
TextField(
|
||||||
|
value = username,
|
||||||
|
onValueChange = { username = it },
|
||||||
|
label = { Text("Nutzername") }
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
//Password
|
||||||
|
TextField(
|
||||||
|
value = password,
|
||||||
|
onValueChange = { password = it },
|
||||||
|
label = { Text("Passwort") }
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Button(onClick = { if(serverUrl.isNotEmpty() && username.isNotEmpty() && password.isNotEmpty()) onLogin(
|
||||||
|
serverUrl,
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
) }) {
|
||||||
Text("Login")
|
Text("Login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,6 +182,7 @@ fun DashboardScreen(account: Account, onBack: () -> Unit) {
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(16.dp)
|
.padding(16.dp)
|
||||||
.statusBarsPadding()
|
.statusBarsPadding()
|
||||||
|
.navigationBarsPadding()
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ data class Account (
|
|||||||
@PrimaryKey val id: UUID,
|
@PrimaryKey val id: UUID,
|
||||||
val name: String,
|
val name: String,
|
||||||
val wgName: String,
|
val wgName: String,
|
||||||
val avatarUrl: String? = null
|
val avatarUrl: String? = null,
|
||||||
|
val serverUrl: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
|||||||
@@ -3,17 +3,23 @@ package de.miaurizius.shap_planner.viewmodels
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import de.miaurizius.shap_planner.UserPreferences
|
import de.miaurizius.shap_planner.UserPreferences
|
||||||
|
import de.miaurizius.shap_planner.entities.Account
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
class LoginViewModel(private val prefs: UserPreferences) : ViewModel() {
|
class LoginViewModel(private val prefs: UserPreferences) : ViewModel() {
|
||||||
|
|
||||||
val isLoggedIn = prefs.isLoggedInFlow.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
val isLoggedIn = prefs.isLoggedInFlow.stateIn(viewModelScope, SharingStarted.Lazily, false)
|
||||||
val lastUserId = prefs.lastUserLoginFlow.stateIn(viewModelScope, SharingStarted.Lazily, null)
|
val lastUserId = prefs.lastUserLoginFlow.stateIn(viewModelScope, SharingStarted.Lazily, null)
|
||||||
|
|
||||||
fun login(userId: String) {
|
fun login(serverUrl: String, username: String, password: String, viewModel: MainViewModel) {
|
||||||
viewModelScope.launch { prefs.saveLogin(userId) }
|
val uuid = UUID.randomUUID();
|
||||||
|
val acc = Account(uuid, username, "Pfadi-WG", null, serverUrl) //TODO: get data from backend
|
||||||
|
viewModel.addAccount(acc)
|
||||||
|
println("Logged in as ${username} in ${serverUrl}")
|
||||||
|
viewModelScope.launch { prefs.saveLogin(uuid.toString()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logout() {
|
fun logout() {
|
||||||
|
|||||||
Reference in New Issue
Block a user