nice and clean now
I don't know if this works
This commit is contained in:
parent
5cf1466c54
commit
3ddbe78fe8
9 changed files with 79 additions and 110 deletions
|
@ -44,17 +44,16 @@ class DashboardActivity : ComponentActivity() {
|
|||
|
||||
val dashboardViewModel = DashboardViewModel(application)
|
||||
if (intent.getBooleanExtra("direct", false).not()) {
|
||||
dashboardViewModel.refresh(this)
|
||||
dashboardViewModel.refresh()
|
||||
}
|
||||
|
||||
dashboardViewModel.checkTermux(this)
|
||||
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
dashboardViewModel.refreshError.collect {
|
||||
it.forEach { errorMsg ->
|
||||
Toast.makeText(baseContext, errorMsg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
}
|
||||
Toast.makeText(baseContext, it, Toast.LENGTH_SHORT).show()
|
||||
} // TODO any better way?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,9 +112,9 @@ fun MyNavigationBar(items: List<Screen>, navController: NavHostController) {
|
|||
saveState = true
|
||||
}
|
||||
// Avoid multiple copies of the same destination when
|
||||
// reselecting the same item
|
||||
// re-selecting the same item
|
||||
launchSingleTop = true
|
||||
// Restore state when reselecting a previously selected item
|
||||
// Restore state when re-selecting a previously selected item
|
||||
restoreState = true
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package eu.m724.vastapp.activity.dashboard
|
||||
|
||||
data class DashboardUiState(
|
||||
val refreshing: Int = 0
|
||||
val refreshing: Boolean = false
|
||||
)
|
|
@ -6,18 +6,17 @@ import android.content.Context
|
|||
import androidx.activity.ComponentActivity
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.m724.vastapp.R
|
||||
import eu.m724.vastapp.VastApplication
|
||||
import eu.m724.vastapp.activity.Opener
|
||||
import eu.m724.vastapp.activity.PermissionChecker
|
||||
import eu.m724.vastapp.vastai.ApiRoute
|
||||
import eu.m724.vastapp.vastai.api.InstancesUrlRequestCallback
|
||||
import eu.m724.vastapp.vastai.api.UserUrlRequestCallback
|
||||
import eu.m724.vastapp.vastai.data.RentedInstance
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class DashboardViewModel(
|
||||
|
@ -25,12 +24,12 @@ class DashboardViewModel(
|
|||
) : AndroidViewModel(application) { // TODO do something with the user
|
||||
|
||||
private val _uiState: MutableStateFlow<DashboardUiState> =
|
||||
MutableStateFlow(DashboardUiState(0))
|
||||
MutableStateFlow(DashboardUiState(false))
|
||||
val uiState: StateFlow<DashboardUiState> =
|
||||
_uiState.asStateFlow()
|
||||
|
||||
private val _refreshError: MutableStateFlow<List<String>> = MutableStateFlow(emptyList())
|
||||
val refreshError: StateFlow<List<String>> = _refreshError.asStateFlow()
|
||||
private val _refreshError: MutableStateFlow<String?> = MutableStateFlow(null)
|
||||
val refreshError: StateFlow<String?> = _refreshError.asStateFlow()
|
||||
|
||||
private val _termuxAvailable: MutableStateFlow<Int> = MutableStateFlow(0)
|
||||
val termuxAvailable: StateFlow<Int> = _termuxAvailable.asStateFlow()
|
||||
|
@ -39,43 +38,29 @@ class DashboardViewModel(
|
|||
private val vastApi = this.application.vastApi
|
||||
val account = this.application.account!!
|
||||
|
||||
fun refresh(activity: ComponentActivity) {
|
||||
_uiState.value = _uiState.value.copy(refreshing = 2)
|
||||
_refreshError.value = emptyList()
|
||||
fun refresh() {
|
||||
_uiState.update { it.copy(refreshing = true) }
|
||||
_refreshError.value = null
|
||||
|
||||
val userRequest = vastApi.buildRequest(
|
||||
ApiRoute.SHOW_USER,
|
||||
UserUrlRequestCallback({ newUser ->
|
||||
account.updateUser(newUser)
|
||||
_uiState.update {
|
||||
it.copy(refreshing = it.refreshing - 1) // TODO I don't like how this looks
|
||||
}
|
||||
}, { apiFailure ->
|
||||
_refreshError.update { it + apiFailure.errorMessage!! }
|
||||
_uiState.update {
|
||||
it.copy(refreshing = it.refreshing - 1)
|
||||
}
|
||||
})
|
||||
)
|
||||
val userDeferred = vastApi.getUser()
|
||||
val rentedInstancesDeferred = vastApi.getRentedInstances()
|
||||
|
||||
val instancesRequest = vastApi.buildRequest(
|
||||
ApiRoute.GET_INSTANCES,
|
||||
InstancesUrlRequestCallback({ instances ->
|
||||
account.updateRentedInstances(instances)
|
||||
_uiState.update {
|
||||
it.copy(refreshing = it.refreshing - 1)
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
account.updateUser(userDeferred.await())
|
||||
account.updateRentedInstances(rentedInstancesDeferred.await())
|
||||
} catch (e: Exception) {
|
||||
_refreshError.update {
|
||||
"Refresh failed: " + e.message.toString()
|
||||
}
|
||||
}, { apiFailure ->
|
||||
_refreshError.update { it + apiFailure.errorMessage!! }
|
||||
_uiState.update {
|
||||
it.copy(refreshing = it.refreshing - 1)
|
||||
}
|
||||
})
|
||||
) // TODO move all that refreshing to some shared place
|
||||
|
||||
userRequest.start()
|
||||
instancesRequest.start()
|
||||
}
|
||||
_uiState.update {
|
||||
it.copy(refreshing = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkTermux(activity: ComponentActivity) {
|
||||
val context = activity.applicationContext
|
||||
|
||||
_termuxAvailable.value =
|
||||
|
@ -88,8 +73,6 @@ class DashboardViewModel(
|
|||
} else -1 // not available because permission denied
|
||||
}
|
||||
} else -1 // not available
|
||||
|
||||
// TODO I don't like this function especially the last line. I think it should be moved to application
|
||||
}
|
||||
|
||||
@SuppressLint("SdCardPath")
|
||||
|
|
|
@ -32,7 +32,7 @@ class LoadingActivity : ComponentActivity() {
|
|||
.putExtra("direct", true)
|
||||
} else {
|
||||
Intent(this, LoginActivity::class.java)
|
||||
.putExtra("error", result.error!!)
|
||||
.putExtra("error", result.error)
|
||||
}
|
||||
|
||||
this.startActivity(intent)
|
||||
|
|
|
@ -2,11 +2,10 @@ package eu.m724.vastapp.activity.dashboard.loading
|
|||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.m724.vastapp.VastApplication
|
||||
import eu.m724.vastapp.vastai.Account
|
||||
import eu.m724.vastapp.vastai.ApiRoute
|
||||
import eu.m724.vastapp.vastai.api.InstancesUrlRequestCallback
|
||||
import eu.m724.vastapp.vastai.api.UserUrlRequestCallback
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class LoadingViewModel(
|
||||
application: Application,
|
||||
|
@ -15,40 +14,30 @@ class LoadingViewModel(
|
|||
private val application = application as VastApplication
|
||||
|
||||
fun init() {
|
||||
val vastApi = application.vastApi
|
||||
val apiKey = application.loadKey()
|
||||
if (apiKey == null) {
|
||||
onEnded(LoadingResult(false, null))
|
||||
return
|
||||
}
|
||||
|
||||
if (apiKey != null) {
|
||||
vastApi.apiKey = apiKey
|
||||
val vastApi = application.vastApi
|
||||
|
||||
val request = vastApi.buildRequest(
|
||||
ApiRoute.SHOW_USER,
|
||||
UserUrlRequestCallback({ user ->
|
||||
application.account = Account(user)
|
||||
loadInstances()
|
||||
}, { apiFailure ->
|
||||
onEnded(LoadingResult(false, apiFailure.errorMessage))
|
||||
})
|
||||
)
|
||||
vastApi.setApiKey(apiKey)
|
||||
val userDeferred = vastApi.getUser()
|
||||
|
||||
request.start()
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val user = userDeferred.await()
|
||||
application.account = Account(user)
|
||||
|
||||
// TODO should we do this were, or is it better to say you're logged in and handle the error from dashboard
|
||||
val rentedInstances = vastApi.getRentedInstances().await()
|
||||
application.account!!.updateRentedInstances(rentedInstances)
|
||||
|
||||
onEnded(LoadingResult(true, null))
|
||||
} catch (e: Exception) {
|
||||
onEnded(LoadingResult(false, e.message.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadInstances() {
|
||||
val vastApi = application.vastApi
|
||||
|
||||
val instancesRequest = vastApi.buildRequest(
|
||||
ApiRoute.GET_INSTANCES,
|
||||
InstancesUrlRequestCallback({ instances ->
|
||||
application.account!!.updateRentedInstances(instances)
|
||||
onEnded(LoadingResult(true, null))
|
||||
}, { apiFailure ->
|
||||
// TODO I don't know what to do yet
|
||||
onEnded(LoadingResult(true, null))
|
||||
})
|
||||
)
|
||||
|
||||
instancesRequest.start()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package eu.m724.vastapp.activity.dashboard.screen
|
||||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
|
@ -24,9 +23,7 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
|||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -47,14 +44,13 @@ fun DashboardScreen(dashboardViewModel: DashboardViewModel) {
|
|||
val user by dashboardViewModel.account.user.collectAsState()
|
||||
val rentedInstances by dashboardViewModel.account.rentedInstances.collectAsState()
|
||||
val remainingTime by dashboardViewModel.account.remainingTime.collectAsState()
|
||||
val isRefreshing by remember(uiState) { derivedStateOf { uiState.refreshing > 0 } }
|
||||
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
PullToRefreshBox(
|
||||
isRefreshing = isRefreshing,
|
||||
isRefreshing = uiState.refreshing,
|
||||
state = rememberPullToRefreshState(),
|
||||
onRefresh = { dashboardViewModel.refresh(context as ComponentActivity) }
|
||||
onRefresh = { dashboardViewModel.refresh() }
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
|
|
@ -4,13 +4,13 @@ import android.app.Application
|
|||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.m724.vastapp.VastApplication
|
||||
import eu.m724.vastapp.vastai.ApiRoute
|
||||
import eu.m724.vastapp.vastai.api.UserUrlRequestCallback
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.chromium.net.CronetEngine
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
|
@ -30,29 +30,23 @@ class LoginViewModel(
|
|||
private val _apiKey = MutableStateFlow<String>("")
|
||||
var apiKey: StateFlow<String> = _apiKey.asStateFlow()
|
||||
|
||||
private val _fullscreenLoading = MutableStateFlow<Boolean>(false)
|
||||
var fullscreenLoading: StateFlow<Boolean> = _fullscreenLoading.asStateFlow()
|
||||
|
||||
private val application = getApplication<VastApplication>()
|
||||
|
||||
fun tryLogin() {
|
||||
val vastApi = application.vastApi
|
||||
vastApi.apiKey = apiKey.value
|
||||
val userDeferred = application.vastApi.getUser()
|
||||
|
||||
val request = vastApi.buildRequest(
|
||||
ApiRoute.SHOW_USER,
|
||||
UserUrlRequestCallback({ user ->
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val user = userDeferred.await()
|
||||
application.submitKey(apiKey.value) // TODO toggle for this
|
||||
_uiState.value = LoginUiState.Success(user)
|
||||
}, { apiFailure ->
|
||||
_uiState.value = LoginUiState.Idle
|
||||
_fullscreenLoading.value = false
|
||||
_error.postValue(apiFailure.errorMessage)
|
||||
})
|
||||
)
|
||||
_uiState.update { LoginUiState.Success(user) }
|
||||
} catch (e: Exception) {
|
||||
_uiState.update { LoginUiState.Idle }
|
||||
_error.postValue(e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
_uiState.value = LoginUiState.Loading
|
||||
request.start()
|
||||
_uiState.update { LoginUiState.Loading }
|
||||
}
|
||||
|
||||
fun onApiKeyChange(apiKey: String) {
|
||||
|
|
|
@ -7,11 +7,15 @@ import org.chromium.net.UrlRequest
|
|||
import java.util.concurrent.Executor
|
||||
|
||||
class RequestMaker(
|
||||
private val apiKey: String,
|
||||
private var apiKey: String,
|
||||
private val cronetEngine: CronetEngine,
|
||||
private val executor: Executor
|
||||
) {
|
||||
|
||||
fun setApiKey(apiKey: String) {
|
||||
this.apiKey = apiKey
|
||||
}
|
||||
|
||||
/**
|
||||
* build an api request
|
||||
* don't forget to call .start() on the returned [UrlRequest]
|
||||
|
|
|
@ -18,6 +18,10 @@ class VastApi(
|
|||
) {
|
||||
private val requestMaker = RequestMaker(apiKey, cronetEngine, executor)
|
||||
|
||||
fun setApiKey(apiKey: String) {
|
||||
requestMaker.setApiKey(apiKey)
|
||||
}
|
||||
|
||||
fun getUser(): CompletableDeferred<User> {
|
||||
val deferred = CompletableDeferred<User>()
|
||||
|
||||
|
|
Loading…
Reference in a new issue