Compare commits

...

5 commits

Author SHA1 Message Date
37475c83d5
tweak cards on dashboard
to allow very short and very long text
looks fine too
2024-07-28 12:55:57 +02:00
99b7229628
so you can't put a number when formatting as float 2024-07-28 12:49:38 +02:00
115b5adb7a
forgot one 2024-07-28 12:46:37 +02:00
eeb4125336
make things translatable 2024-07-28 12:43:18 +02:00
8bdd22f783
remove unnecessary string 2024-07-28 12:19:36 +02:00
4 changed files with 63 additions and 42 deletions

View file

@ -22,6 +22,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import eu.m724.vastapp.R import eu.m724.vastapp.R
@ -45,12 +46,16 @@ fun BillingScreen(dashboardViewModel: DashboardViewModel) {
modifier = Modifier.width(160.dp) modifier = Modifier.width(160.dp)
) { ) {
Row( Row(
modifier = Modifier.padding(16.dp, 8.dp).height(IntrinsicSize.Min) modifier = Modifier
.padding(16.dp, 8.dp)
.height(IntrinsicSize.Min)
) { ) {
Icon( Icon(
modifier = Modifier.fillMaxHeight().aspectRatio(1f), modifier = Modifier
.fillMaxHeight()
.aspectRatio(1f),
painter = painterResource(id = R.drawable.baseline_monetization_on_24), painter = painterResource(id = R.drawable.baseline_monetization_on_24),
contentDescription = "Balance" contentDescription = stringResource(id = R.string.balance)
) )
Spacer(modifier = Modifier Spacer(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()

View file

@ -32,6 +32,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import eu.m724.vastapp.R import eu.m724.vastapp.R
@ -43,7 +44,7 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
val uiState by dashboardViewModel.uiState.collectAsState() val uiState by dashboardViewModel.uiState.collectAsState()
val user by remember(uiState) { derivedStateOf { uiState.user } } val user by remember(uiState) { derivedStateOf { uiState.user } }
val remainingTime by rememberSaveable { mutableIntStateOf(0) } val remainingTime by rememberSaveable { mutableIntStateOf(6000000) }
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
@ -62,14 +63,18 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
.height(100.dp), .height(100.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center) { verticalArrangement = Arrangement.Center) {
Text("Hello ${user.username}!", fontSize = 28.sp) Text(
text = stringResource(id = R.string.greeting, user.username),
fontSize = 28.sp
)
} }
FlowRow { FlowRow(
horizontalArrangement = Arrangement.Center
) {
// balance card // balance card
Card( Card(
modifier = Modifier modifier = Modifier
.width(160.dp)
.padding(16.dp), .padding(16.dp),
colors = CardDefaults.cardColors( colors = CardDefaults.cardColors(
containerColor = balanceCardColor(user.credit) containerColor = balanceCardColor(user.credit)
@ -82,12 +87,10 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
Icon( Icon(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.baseline_monetization_on_24), painter = painterResource(id = R.drawable.baseline_monetization_on_24),
contentDescription = "Balance" contentDescription = stringResource(id = R.string.balance)
) )
Spacer( Spacer(
modifier = Modifier modifier = Modifier.width(12.dp)
.fillMaxWidth()
.weight(1f)
) )
Text( Text(
text = "$%.2f".format(user.credit), text = "$%.2f".format(user.credit),
@ -100,7 +103,6 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
// time card // time card
Card( Card(
modifier = Modifier modifier = Modifier
.width(160.dp)
.padding(16.dp) .padding(16.dp)
) { ) {
Row( Row(
@ -110,12 +112,10 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
Icon( Icon(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.baseline_access_time_filled_24), painter = painterResource(id = R.drawable.baseline_access_time_filled_24),
contentDescription = "Remaining time" contentDescription = stringResource(id = R.string.time_left)
) )
Spacer( Spacer(
modifier = Modifier modifier = Modifier.width(12.dp)
.fillMaxWidth()
.weight(1f)
) )
Text( Text(
text = formatTime(remainingTime), text = formatTime(remainingTime),
@ -127,7 +127,6 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
// instances // instances
Card( Card(
modifier = Modifier modifier = Modifier
.width(160.dp)
.padding(16.dp) .padding(16.dp)
) { ) {
Row( Row(
@ -137,11 +136,10 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
Icon( Icon(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.server_solid), painter = painterResource(id = R.drawable.server_solid),
contentDescription = "Rented" contentDescription = stringResource(id = R.string.rented_instances)
) )
Spacer(modifier = Modifier Spacer(
.fillMaxWidth() modifier = Modifier.width(12.dp)
.weight(1f)
) )
Text( Text(
text = "4", text = "4",
@ -164,19 +162,19 @@ fun balanceColor(balance: Double, warningThreshold: Double): Color {
return if (balance > warningThreshold) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.error return if (balance > warningThreshold) MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.error
} }
@Composable
fun formatTime(seconds: Int): String { fun formatTime(seconds: Int): String {
if (seconds <= 0) return "0.00m" if (seconds <= 0)
return stringResource(id = R.string.time_minutes_short, 0.0)
val minutes: Double = seconds / 60.0 val minutes: Double = seconds / 60.0
if (minutes < 60) { if (minutes < 60)
return "%.2fm".format(minutes) return stringResource(id = R.string.time_minutes_short, minutes)
}
val hours: Double = minutes / 60 val hours: Double = minutes / 60
if (hours < 24) { if (hours < 24)
return "%.2fh".format(hours) return stringResource(id = R.string.time_hours_short, hours)
}
val days: Double = hours / 24 val days: Double = hours / 24
return "%.2fd".format(days) return stringResource(id = R.string.time_days_short, days)
} }

View file

@ -57,12 +57,14 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import eu.m724.vastapp.BuildConfig import eu.m724.vastapp.BuildConfig
import eu.m724.vastapp.R
import eu.m724.vastapp.activity.dashboard.DashboardActivity import eu.m724.vastapp.activity.dashboard.DashboardActivity
import eu.m724.vastapp.ui.theme.VastappTheme import eu.m724.vastapp.ui.theme.VastappTheme
import eu.m724.vastapp.vastai.data.User import eu.m724.vastapp.vastai.data.User
@ -147,7 +149,9 @@ fun LoginApp(loginViewModel: LoginViewModel) {
Column( Column(
modifier = Modifier.width(300.dp).animateContentSize(spring(stiffness = Spring.StiffnessMedium)), // TODO double animation modifier = Modifier
.width(300.dp)
.animateContentSize(spring(stiffness = Spring.StiffnessMedium)), // TODO double animation
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
@ -156,7 +160,7 @@ fun LoginApp(loginViewModel: LoginViewModel) {
enabled = isIdle, enabled = isIdle,
value = apiKey, value = apiKey,
onValueChange = { apiKey = it }, onValueChange = { apiKey = it },
label = { Text(text = "API key") }, label = { Text(text = stringResource(id = R.string.api_key)) },
visualTransformation = PasswordVisualTransformation(), visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
textStyle = if (uiState is LoginUiState.Success) rainbowTextStyle() else LocalTextStyle.current, textStyle = if (uiState is LoginUiState.Success) rainbowTextStyle() else LocalTextStyle.current,
@ -171,7 +175,7 @@ fun LoginApp(loginViewModel: LoginViewModel) {
advancedOpen = !advancedOpen advancedOpen = !advancedOpen
} }
) { ) {
Text("Advanced options") Text(text = stringResource(id = R.string.advanced_options))
Icon( Icon(
imageVector = Icons.Filled.KeyboardArrowDown, imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = null, contentDescription = null,
@ -188,7 +192,7 @@ fun LoginApp(loginViewModel: LoginViewModel) {
if (uiState is LoginUiState.Loading) { if (uiState is LoginUiState.Loading) {
CircularProgressIndicator() CircularProgressIndicator()
} else { } else {
Text("Log in") Text(text = stringResource(id = R.string.btn_login))
} }
} }
} }
@ -213,13 +217,14 @@ fun rainbowTextStyle(): TextStyle {
@Composable @Composable
fun AdvancedOptions() { // TODO put this in viewmodel fun AdvancedOptions() { // TODO put this in viewmodel
var checked by rememberSaveable { mutableStateOf(true) } var checked by rememberSaveable { mutableStateOf(true) }
var clicks by rememberSaveable { mutableIntStateOf(0) } var clicks by rememberSaveable { mutableIntStateOf(0) }
var checkboxLabel by rememberSaveable { mutableStateOf("here's a checkbox for you") } var checkboxLabel by rememberSaveable { mutableIntStateOf(R.string.login_checkbox) }
var mathPassing by rememberSaveable { mutableStateOf(true) } var mathPassing by rememberSaveable { mutableStateOf(true) }
val clickMessages = mapOf( val clickMessages = mapOf(
20 to "having fun?" 20 to R.string.login_checkbox_20
) )
Column( Column(
@ -227,7 +232,7 @@ fun AdvancedOptions() { // TODO put this in viewmodel
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 12.dp) .padding(horizontal = 12.dp)
) { ) {
Text("none yet sorry") Text(text = stringResource(id = R.string.no_options))
Row( Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
@ -240,17 +245,17 @@ fun AdvancedOptions() { // TODO put this in viewmodel
clicks++ clicks++
if (clicks in clickMessages) { if (clicks in clickMessages) {
checkboxLabel = clickMessages[clicks].toString() checkboxLabel = clickMessages[clicks]!!
} }
} }
) )
Text(checkboxLabel) Text(text = stringResource(id = checkboxLabel))
} }
AnimatedVisibility(visible = mathPassing) { AnimatedVisibility(visible = mathPassing) {
MathProblem(onFail = { MathProblem(onFail = {
mathPassing = false mathPassing = false
checkboxLabel = "checkbox is angry" checkboxLabel = R.string.login_checkbox_angry
}, onPass = { }, onPass = {
checked = !checked checked = !checked
}) })

View file

@ -1,10 +1,23 @@
<resources> <resources>
<string name="app_name">vast.app</string> <string name="app_name" translatable="false">vast.app</string>
<string name="title_activity_dashboard">Dashboard</string> <string name="title_activity_dashboard">Dashboard</string>
<string name="title_activity_login">Login</string> <string name="title_activity_login" translatable="false">vast.app</string>
<string name="dashboard">Dashboard</string>
<string name="nav_dashboard">Dashboard</string> <string name="nav_dashboard">Dashboard</string>
<string name="nav_billing">Billing</string> <string name="nav_billing">Billing</string>
<string name="nav_instances">Instances</string> <string name="nav_instances">Instances</string>
<string name="nav_help">Help</string> <string name="nav_help">Help</string>
<string name="balance">Balance</string>
<string name="greeting">Hello %1$s!</string>
<string name="time_left">Time left</string>
<string name="rented_instances">Rented</string>
<string name="time_minutes_short">%1$.2fm</string>
<string name="time_hours_short">%1$.2fh</string>
<string name="time_days_short">%1$.2fd</string>
<string name="api_key">API Key</string>
<string name="advanced_options">Advanced options</string>
<string name="btn_login">Log in</string>
<string name="login_checkbox">here\'s a checkbox for you</string>
<string name="login_checkbox_20">having fun?</string>
<string name="login_checkbox_angry">checkbox is angry</string>
<string name="no_options">none yet sorry</string>
</resources> </resources>