make it work
This commit is contained in:
parent
0ca0cbe723
commit
127a31841e
16 changed files with 234 additions and 137 deletions
|
@ -1,4 +1,3 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||||
|
|
|
@ -13,4 +13,6 @@ I'm making this to learn stuff please don't rely on this app
|
||||||
- material you supported
|
- material you supported
|
||||||
- dashboard
|
- dashboard
|
||||||
|
|
||||||
|
home and instances icons are from font awesome
|
||||||
|
|
||||||
TODO
|
TODO
|
|
@ -7,6 +7,7 @@ import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
|
@ -15,7 +16,9 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
@ -102,7 +105,8 @@ fun MyNavigationBar(items: List<Screen>, navController: NavHostController) {
|
||||||
},
|
},
|
||||||
icon = {
|
icon = {
|
||||||
Icon(
|
Icon(
|
||||||
screen.icon,
|
painterResource(screen.icon),
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
contentDescription = stringResource(screen.resourceId)
|
contentDescription = stringResource(screen.resourceId)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,7 +32,7 @@ class DashboardViewModel(private val _user: User, val vastApi: VastApi) : ViewMo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshData() {
|
fun refresh() {
|
||||||
val request = vastApi.buildRequest(
|
val request = vastApi.buildRequest(
|
||||||
ApiRoute.SHOW_USER,
|
ApiRoute.SHOW_USER,
|
||||||
UserUrlRequestCallback({ user ->
|
UserUrlRequestCallback({ user ->
|
||||||
|
@ -41,5 +41,8 @@ class DashboardViewModel(private val _user: User, val vastApi: VastApi) : ViewMo
|
||||||
_uiState.value = _uiState.value.copy(isRefreshing = false, error = apiFailure.errorMessage)
|
_uiState.value = _uiState.value.copy(isRefreshing = false, error = apiFailure.errorMessage)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_uiState.value = _uiState.value.copy(isRefreshing = true)
|
||||||
|
request.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package eu.m724.vastapp.activity.dashboard.screen
|
package eu.m724.vastapp.activity.dashboard.screen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
@ -8,15 +9,24 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||||
|
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
||||||
|
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableDoubleStateOf
|
import androidx.compose.runtime.mutableDoubleStateOf
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
@ -34,143 +44,108 @@ class Dashboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class) // for pullRefresh
|
||||||
@Composable
|
@Composable
|
||||||
fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
|
fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
|
||||||
var balance by rememberSaveable { mutableDoubleStateOf(user.credit) }
|
val uiState by dashboardViewModel.uiState.collectAsState()
|
||||||
var remainingTime by rememberSaveable { mutableIntStateOf(0) }
|
|
||||||
|
|
||||||
Column(
|
val user by remember(uiState) { derivedStateOf { uiState.user } }
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
val remainingTime by rememberSaveable { mutableIntStateOf(0) }
|
||||||
|
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
|
PullToRefreshBox(
|
||||||
|
isRefreshing = uiState.isRefreshing,
|
||||||
|
state = rememberPullToRefreshState(),
|
||||||
|
onRefresh = { dashboardViewModel.refresh() }
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(100.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center) {
|
modifier = Modifier.verticalScroll(scrollState)
|
||||||
Text("Hello ${user.username}!", fontSize = 28.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.width(340.dp)
|
|
||||||
) {
|
) {
|
||||||
Card(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp)
|
.height(100.dp),
|
||||||
.weight(1f),
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
colors = CardDefaults.cardColors(
|
verticalArrangement = Arrangement.Center) {
|
||||||
containerColor = balanceCardColor(balance)
|
Text("Hello ${user.username}!", fontSize = 28.sp)
|
||||||
)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.baseline_account_balance_wallet_24),
|
|
||||||
contentDescription = "Balance"
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.weight(1f)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "$%.2f".format(balance),
|
|
||||||
fontSize = 22.sp,
|
|
||||||
color = balanceColor(balance, user.balanceThreshold)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
Row(
|
||||||
.fillMaxWidth()
|
modifier = Modifier.width(340.dp)
|
||||||
.padding(16.dp)
|
|
||||||
.weight(1f),
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Card(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
modifier = Modifier
|
||||||
verticalAlignment = Alignment.CenterVertically
|
.fillMaxWidth()
|
||||||
) {
|
.padding(16.dp)
|
||||||
Icon(
|
.weight(1f),
|
||||||
painter = painterResource(id = R.drawable.baseline_access_time_filled_24),
|
colors = CardDefaults.cardColors(
|
||||||
contentDescription = "Remaining time"
|
containerColor = balanceCardColor(user.credit)
|
||||||
)
|
)
|
||||||
Spacer(
|
) {
|
||||||
modifier = Modifier
|
Row(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.baseline_monetization_on_24),
|
||||||
|
contentDescription = "Balance"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = formatTime(remainingTime),
|
text = "$%.2f".format(user.credit),
|
||||||
fontSize = 22.sp
|
fontSize = 22.sp,
|
||||||
)
|
color = balanceColor(user.credit, user.balanceThreshold)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Card(
|
||||||
}
|
modifier = Modifier
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.width(340.dp)
|
|
||||||
) {
|
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp)
|
|
||||||
.weight(1f),
|
|
||||||
colors = CardDefaults.cardColors(
|
|
||||||
containerColor = balanceCardColor(balance)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.baseline_account_balance_wallet_24),
|
|
||||||
contentDescription = "Balance"
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f)
|
.padding(16.dp)
|
||||||
)
|
.weight(1f),
|
||||||
Text(
|
|
||||||
text = "$%.2f".format(balance),
|
|
||||||
fontSize = 22.sp,
|
|
||||||
color = balanceColor(balance, user.balanceThreshold)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Card(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp)
|
|
||||||
.weight(1f),
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Row(
|
||||||
painter = painterResource(id = R.drawable.baseline_access_time_filled_24),
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
contentDescription = "Remaining time"
|
verticalAlignment = Alignment.CenterVertically
|
||||||
)
|
) {
|
||||||
Spacer(
|
Icon(
|
||||||
modifier = Modifier
|
painter = painterResource(id = R.drawable.baseline_access_time_filled_24),
|
||||||
.fillMaxWidth()
|
contentDescription = "Remaining time"
|
||||||
.weight(1f)
|
)
|
||||||
)
|
Spacer(
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = formatTime(remainingTime),
|
.fillMaxWidth()
|
||||||
fontSize = 22.sp
|
.weight(1f)
|
||||||
)
|
)
|
||||||
|
Text(
|
||||||
|
text = formatTime(remainingTime),
|
||||||
|
fontSize = 22.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Column(
|
val instance = JSONObject()
|
||||||
modifier = Modifier.width(340.dp)
|
instance.put("id", 234523)
|
||||||
) {
|
instance.put("machine_id", 1121323)
|
||||||
|
instance.put("host_id", 5924)
|
||||||
|
instance.put("gpu_name", "RTX 4090")
|
||||||
|
instance.put("num_gpus", 2)
|
||||||
|
instance.put("gpu_util", 70)
|
||||||
|
instance.put("gpu_ram", 24564)
|
||||||
|
instance.put("vmem_usage", 0.339843)
|
||||||
|
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.width(340.dp)
|
||||||
|
) {
|
||||||
|
InstanceCard(instance = instance, modifier = Modifier.padding(16.dp))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
package eu.m724.vastapp.activity.dashboard.screen
|
package eu.m724.vastapp.activity.dashboard.screen
|
||||||
|
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import eu.m724.vastapp.activity.dashboard.DashboardViewModel
|
import eu.m724.vastapp.activity.dashboard.DashboardViewModel
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
@ -25,11 +33,61 @@ fun InstancesScreen(dashboardViewModel: DashboardViewModel) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InstanceCard(instance: JSONObject, modifier: Modifier = Modifier) {
|
fun InstanceCard(instance: JSONObject, modifier: Modifier = Modifier) {
|
||||||
|
val gpuUsage = instance.getInt("gpu_util")
|
||||||
|
val vramGb = instance.getInt("gpu_ram") / 1000.0
|
||||||
|
val vramGbUsed = vramGb * instance.getDouble("vmem_usage")
|
||||||
|
|
||||||
Card(modifier = modifier) {
|
Card(modifier = modifier) {
|
||||||
Row(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = instance.getString("id"))
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
Text(text = instance.getString("id"), fontSize = 14.sp)
|
||||||
|
Text(text = "m:" + instance.getString("machine_id"), fontSize = 14.sp)
|
||||||
|
Text(text = "h:" + instance.getString("host_id"), fontSize = 14.sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(0.5f),
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
Text(text = instance.getString("gpu_name"), fontSize = 24.sp)
|
||||||
|
if (instance.getInt("num_gpus") > 1) {
|
||||||
|
Text(text = "x" + instance.getString("num_gpus"), modifier = Modifier.padding(start = 2.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(0.5f)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth().weight(1f)
|
||||||
|
) {
|
||||||
|
Text(text = "GPU: $gpuUsage%", fontSize = 12.sp)
|
||||||
|
LinearProgressIndicator(
|
||||||
|
progress = { gpuUsage / 100f }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth().weight(1f)
|
||||||
|
) {
|
||||||
|
Text(text = "%.1f / %.1f G".format(vramGbUsed, vramGb), fontSize = 12.sp)
|
||||||
|
LinearProgressIndicator(
|
||||||
|
progress = { instance.getDouble("vmem_usage").toFloat() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
package eu.m724.vastapp.activity.dashboard.screen
|
package eu.m724.vastapp.activity.dashboard.screen
|
||||||
|
|
||||||
|
import android.media.Image
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Home
|
import androidx.compose.material.icons.outlined.Home
|
||||||
import androidx.compose.material.icons.outlined.Menu
|
import androidx.compose.material.icons.outlined.Menu
|
||||||
import androidx.compose.material.icons.outlined.ShoppingCart
|
import androidx.compose.material.icons.outlined.ShoppingCart
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.vectorResource
|
||||||
import eu.m724.vastapp.R
|
import eu.m724.vastapp.R
|
||||||
|
|
||||||
sealed class Screen(val route: String, @StringRes val resourceId: Int, val icon: ImageVector) {
|
sealed class Screen(val route: String, @StringRes val resourceId: Int, val icon: Int) {
|
||||||
object Dashboard : Screen("dashboard", R.string.nav_dashboard, Icons.Outlined.Home)
|
data object Dashboard : Screen("dashboard", R.string.nav_dashboard, R.drawable.house_solid)
|
||||||
object Instances : Screen("instances", R.string.nav_instances, Icons.Outlined.Menu)
|
data object Instances : Screen("instances", R.string.nav_instances, R.drawable.server_solid)
|
||||||
object Billing : Screen("billing", R.string.nav_billing, Icons.Outlined.ShoppingCart)
|
data object Billing : Screen("billing", R.string.nav_billing, R.drawable.baseline_monetization_on_24)
|
||||||
|
data object Help : Screen("help", R.string.nav_help, R.drawable.baseline_help_outline_24)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,11 @@ import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.animateColor
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
|
import androidx.compose.animation.core.Spring
|
||||||
import androidx.compose.animation.core.animateFloat
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.spring
|
||||||
import androidx.compose.animation.core.updateTransition
|
import androidx.compose.animation.core.updateTransition
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -31,6 +35,7 @@ import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
|
@ -50,6 +55,9 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.Color
|
||||||
|
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
|
||||||
|
@ -60,6 +68,7 @@ import eu.m724.vastapp.ui.theme.VastappTheme
|
||||||
import eu.m724.vastapp.vastai.data.User
|
import eu.m724.vastapp.vastai.data.User
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.chromium.net.CronetEngine
|
import org.chromium.net.CronetEngine
|
||||||
|
import org.w3c.dom.Text
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@ -136,8 +145,9 @@ fun LoginApp(loginViewModel: LoginViewModel) {
|
||||||
if (state) 180f else 0f
|
if (state) 180f else 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.width(300.dp),
|
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
|
||||||
) {
|
) {
|
||||||
|
@ -149,6 +159,7 @@ fun LoginApp(loginViewModel: LoginViewModel) {
|
||||||
label = { Text(text = "API key") },
|
label = { Text(text = "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,
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
isError = loginErrorMessage != null
|
isError = loginErrorMessage != null
|
||||||
)
|
)
|
||||||
|
@ -188,7 +199,20 @@ fun LoginApp(loginViewModel: LoginViewModel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AdvancedOptions() {
|
fun rainbowTextStyle(): TextStyle {
|
||||||
|
return LocalTextStyle.current.copy(brush = Brush.linearGradient(colors = listOf(
|
||||||
|
Color.Red,
|
||||||
|
Color(255,127,0),
|
||||||
|
Color.Yellow,
|
||||||
|
Color.Green,
|
||||||
|
Color.Blue,
|
||||||
|
Color(75, 0, 130), // Indigo
|
||||||
|
Color(143, 0, 255) // Violet
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
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 { mutableStateOf("here's a checkbox for you") }
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.widget.Toast
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import eu.m724.vastapp.vastai.ApiFailure
|
import eu.m724.vastapp.vastai.ApiFailure
|
||||||
import eu.m724.vastapp.vastai.ApiRoute
|
import eu.m724.vastapp.vastai.ApiRoute
|
||||||
import eu.m724.vastapp.vastai.VastApi
|
import eu.m724.vastapp.vastai.VastApi
|
||||||
|
@ -33,7 +34,7 @@ class LoginViewModel(val cronetEngine: CronetEngine, val executor: Executor) : V
|
||||||
_uiState.value = LoginUiState.Success(user)
|
_uiState.value = LoginUiState.Success(user)
|
||||||
}, { apiFailure ->
|
}, { apiFailure ->
|
||||||
_uiState.value = LoginUiState.Idle
|
_uiState.value = LoginUiState.Idle
|
||||||
_error.value = apiFailure.errorMessage
|
_error.postValue(apiFailure.errorMessage)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M21,18v1c0,1.1 -0.9,2 -2,2L5,21c-1.11,0 -2,-0.9 -2,-2L3,5c0,-1.1 0.89,-2 2,-2h14c1.1,0 2,0.9 2,2v1h-9c-1.11,0 -2,0.9 -2,2v8c0,1.1 0.89,2 2,2h9zM12,16h10L22,8L12,8v8zM16,13.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
5
app/src/main/res/drawable/baseline_help_outline_24.xml
Normal file
5
app/src/main/res/drawable/baseline_help_outline_24.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z"/>
|
||||||
|
|
||||||
|
</vector>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13.41,18.09L13.41,20h-2.67v-1.93c-1.71,-0.36 -3.16,-1.46 -3.27,-3.4h1.96c0.1,1.05 0.82,1.87 2.65,1.87 1.96,0 2.4,-0.98 2.4,-1.59 0,-0.83 -0.44,-1.61 -2.67,-2.14 -2.48,-0.6 -4.18,-1.62 -4.18,-3.67 0,-1.72 1.39,-2.84 3.11,-3.21L10.74,4h2.67v1.95c1.86,0.45 2.79,1.86 2.85,3.39L14.3,9.34c-0.05,-1.11 -0.64,-1.87 -2.22,-1.87 -1.5,0 -2.4,0.68 -2.4,1.64 0,0.84 0.65,1.39 2.67,1.91s4.18,1.39 4.18,3.91c-0.01,1.83 -1.38,2.83 -3.12,3.16z"/>
|
||||||
|
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/house_solid.xml
Normal file
9
app/src/main/res/drawable/house_solid.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="576dp"
|
||||||
|
android:height="512dp"
|
||||||
|
android:viewportWidth="576"
|
||||||
|
android:viewportHeight="512">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M575.8,255.5c0,18 -15,32.1 -32,32.1l-32,0 0.7,160.2c0,2.7 -0.2,5.4 -0.5,8.1l0,16.2c0,22.1 -17.9,40 -40,40l-16,0c-1.1,0 -2.2,0 -3.3,-0.1c-1.4,0.1 -2.8,0.1 -4.2,0.1L416,512l-24,0c-22.1,0 -40,-17.9 -40,-40l0,-24 0,-64c0,-17.7 -14.3,-32 -32,-32l-64,0c-17.7,0 -32,14.3 -32,32l0,64 0,24c0,22.1 -17.9,40 -40,40l-24,0 -31.9,0c-1.5,0 -3,-0.1 -4.5,-0.2c-1.2,0.1 -2.4,0.2 -3.6,0.2l-16,0c-22.1,0 -40,-17.9 -40,-40l0,-112c0,-0.9 0,-1.9 0.1,-2.8l0,-69.7 -32,0c-18,0 -32,-14 -32,-32.1c0,-9 3,-17 10,-24L266.4,8c7,-7 15,-8 22,-8s15,2 21,7L564.8,231.5c8,7 12,15 11,24z"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/server_solid.xml
Normal file
9
app/src/main/res/drawable/server_solid.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="512dp"
|
||||||
|
android:height="512dp"
|
||||||
|
android:viewportWidth="512"
|
||||||
|
android:viewportHeight="512">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M64,32C28.7,32 0,60.7 0,96l0,64c0,35.3 28.7,64 64,64l384,0c35.3,0 64,-28.7 64,-64l0,-64c0,-35.3 -28.7,-64 -64,-64L64,32zM344,104a24,24 0,1 1,0 48,24 24,0 1,1 0,-48zM392,128a24,24 0,1 1,48 0,24 24,0 1,1 -48,0zM64,288c-35.3,0 -64,28.7 -64,64l0,64c0,35.3 28.7,64 64,64l384,0c35.3,0 64,-28.7 64,-64l0,-64c0,-35.3 -28.7,-64 -64,-64L64,288zM344,360a24,24 0,1 1,0 48,24 24,0 1,1 0,-48zM400,384a24,24 0,1 1,48 0,24 24,0 1,1 -48,0z"/>
|
||||||
|
</vector>
|
|
@ -6,4 +6,5 @@
|
||||||
<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>
|
||||||
</resources>
|
</resources>
|
|
@ -7,13 +7,14 @@ junitVersion = "1.2.1"
|
||||||
espressoCore = "3.6.1"
|
espressoCore = "3.6.1"
|
||||||
appcompat = "1.7.0"
|
appcompat = "1.7.0"
|
||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
lifecycleRuntimeKtx = "2.8.3"
|
lifecycleRuntimeKtx = "2.8.4"
|
||||||
activityCompose = "1.9.0"
|
activityCompose = "1.9.1"
|
||||||
composeBom = "2024.06.00"
|
composeBom = "2024.06.00"
|
||||||
playServicesCronet = "18.1.0"
|
playServicesCronet = "18.1.0"
|
||||||
navigationCompose = "2.7.7"
|
navigationCompose = "2.7.7"
|
||||||
secretsGradlePlugin = "2.0.1"
|
secretsGradlePlugin = "2.0.1"
|
||||||
runtimeLivedata = "1.6.8"
|
runtimeLivedata = "1.6.8"
|
||||||
|
material3 = "1.3.0-beta05" # for pulltorefresh
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
@ -31,7 +32,7 @@ androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||||
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||||
play-services-cronet = { module = "com.google.android.gms:play-services-cronet", version.ref = "playServicesCronet" }
|
play-services-cronet = { module = "com.google.android.gms:play-services-cronet", version.ref = "playServicesCronet" }
|
||||||
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
||||||
androidx-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata", version.ref = "runtimeLivedata" }
|
androidx-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata", version.ref = "runtimeLivedata" }
|
||||||
|
|
Loading…
Reference in a new issue