UI Feedback
This commit is contained in:
@@ -3,6 +3,9 @@ package net.helcel.cowspent.android.main
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material.CircularProgressIndicator
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -69,13 +72,43 @@ fun EmptyProjectsState(onConfigureNextcloud: () -> Unit, onAddManually: () -> Un
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A full-height, centred state that a pull to refresh can still act on.
|
||||||
|
*
|
||||||
|
* PullRefresh reads the gesture from a nested scroll source, and a plain Column offers none - so
|
||||||
|
* on an empty list, which is exactly when a refresh is wanted most, the pull never fires. A
|
||||||
|
* single-item LazyColumn has nowhere to scroll but does provide that source.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun RefreshableFullScreenState(content: @Composable ColumnScope.() -> Unit) {
|
||||||
|
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||||
|
item {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillParentMaxSize().padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoadingBillsState() {
|
||||||
|
RefreshableFullScreenState {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.error_loading),
|
||||||
|
style = MaterialTheme.typography.subtitle1,
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EmptyMembersState() {
|
fun EmptyMembersState() {
|
||||||
Column(
|
RefreshableFullScreenState {
|
||||||
modifier = Modifier.fillMaxSize().padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.error_no_members).uppercase(),
|
text = stringResource(R.string.error_no_members).uppercase(),
|
||||||
style = MaterialTheme.typography.subtitle1,
|
style = MaterialTheme.typography.subtitle1,
|
||||||
@@ -94,11 +127,7 @@ fun EmptyMembersState() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EmptyBillsState() {
|
fun EmptyBillsState() {
|
||||||
Column(
|
RefreshableFullScreenState {
|
||||||
modifier = Modifier.fillMaxSize().padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.error_no_bills).uppercase(),
|
text = stringResource(R.string.error_no_bills).uppercase(),
|
||||||
style = MaterialTheme.typography.subtitle1,
|
style = MaterialTheme.typography.subtitle1,
|
||||||
@@ -203,11 +232,7 @@ fun SectionHeader(title: String) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EmptyState() {
|
fun EmptyState() {
|
||||||
Column(
|
RefreshableFullScreenState {
|
||||||
modifier = Modifier.fillMaxSize(),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.error_no_bills).uppercase(),
|
text = stringResource(R.string.error_no_bills).uppercase(),
|
||||||
style = MaterialTheme.typography.subtitle1,
|
style = MaterialTheme.typography.subtitle1,
|
||||||
|
|||||||
@@ -409,6 +409,10 @@ fun BillsListScreen(
|
|||||||
when {
|
when {
|
||||||
viewModel.showNoProjects -> EmptyProjectsState(onAccountSwitcherClick, onAddProjectClick)
|
viewModel.showNoProjects -> EmptyProjectsState(onAccountSwitcherClick, onAddProjectClick)
|
||||||
viewModel.showNoMembers -> EmptyMembersState()
|
viewModel.showNoMembers -> EmptyMembersState()
|
||||||
|
// A large project takes a long time on its first sync. Until that finishes there
|
||||||
|
// is nothing stored for it yet, and reporting that as "no bills" tells the user
|
||||||
|
// the project is empty when it is still downloading.
|
||||||
|
viewModel.isRefreshing && viewModel.bills.isEmpty() -> LoadingBillsState()
|
||||||
viewModel.showNoBills -> EmptyBillsState()
|
viewModel.showNoBills -> EmptyBillsState()
|
||||||
viewModel.bills.isEmpty() -> EmptyState()
|
viewModel.bills.isEmpty() -> EmptyState()
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -94,14 +94,16 @@ class BillsListViewActivity :
|
|||||||
private val syncCallBack = object : ICallback {
|
private val syncCallBack = object : ICallback {
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
mActionMode?.finish()
|
mActionMode?.finish()
|
||||||
refreshLists()
|
|
||||||
viewModel.isRefreshing = false
|
viewModel.isRefreshing = false
|
||||||
|
refreshLists()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFinish(result: String, message: String) {}
|
override fun onFinish(result: String, message: String) {}
|
||||||
|
|
||||||
override fun onScheduled() {
|
override fun onScheduled() {
|
||||||
viewModel.isRefreshing = false
|
// Being queued is not being done. Clearing the indicator here stops the spinner while a
|
||||||
|
// large project is still downloading; synchronize() already releases it when nothing
|
||||||
|
// actually started.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user