mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-11 13:46:37 +01:00
Refactor FollowSetsManagementDialog UI to correctly adapt to follow set state. Small adjustment in the NostrUserListFeedViewModel.
This commit is contained in:
@@ -57,7 +57,7 @@ class NostrUserListFeedViewModel(
|
|||||||
private val _feedContent = MutableStateFlow<FollowSetState>(FollowSetState.Loading)
|
private val _feedContent = MutableStateFlow<FollowSetState>(FollowSetState.Loading)
|
||||||
val feedContent = _feedContent.asStateFlow()
|
val feedContent = _feedContent.asStateFlow()
|
||||||
|
|
||||||
private fun refresh() {
|
fun refresh() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
refreshSuspended()
|
refreshSuspended()
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ class NostrUserListFeedViewModel(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(
|
Log.e(
|
||||||
"NostrUserListFeedViewModel",
|
this.javaClass.simpleName,
|
||||||
"refreshSuspended: Error loading or refreshing feed -> ${e.message}",
|
"refreshSuspended: Error loading or refreshing feed -> ${e.message}",
|
||||||
)
|
)
|
||||||
_feedContent.update { FollowSetState.FeedError(e.message.toString()) }
|
_feedContent.update { FollowSetState.FeedError(e.message.toString()) }
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
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.imePadding
|
import androidx.compose.foundation.layout.imePadding
|
||||||
@@ -43,6 +44,7 @@ import androidx.compose.material.icons.filled.Add
|
|||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material3.AlertDialogDefaults
|
import androidx.compose.material3.AlertDialogDefaults
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilterChip
|
import androidx.compose.material3.FilterChip
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
@@ -80,6 +82,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.FollowSetState
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListVisibility
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.ListVisibility
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NewListCreationDialog
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NewListCreationDialog
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.NostrUserListFeedViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
@@ -95,66 +98,66 @@ fun FollowSetsManagementDialog(
|
|||||||
val followSetsState by followSetsViewModel.feedContent.collectAsState()
|
val followSetsState by followSetsViewModel.feedContent.collectAsState()
|
||||||
val userInfo by remember { derivedStateOf { LocalCache.getOrCreateUser(userHex) } }
|
val userInfo by remember { derivedStateOf { LocalCache.getOrCreateUser(userHex) } }
|
||||||
|
|
||||||
when (followSetsState) {
|
Scaffold(
|
||||||
is FollowSetState.Loaded -> {
|
modifier =
|
||||||
val lists = (followSetsState as FollowSetState.Loaded).feed
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
Scaffold(
|
.recalculateWindowInsets(),
|
||||||
modifier =
|
containerColor = AlertDialogDefaults.containerColor,
|
||||||
Modifier
|
topBar = {
|
||||||
.fillMaxSize()
|
TopAppBar(
|
||||||
.recalculateWindowInsets(),
|
title = {
|
||||||
containerColor = AlertDialogDefaults.containerColor,
|
Column {
|
||||||
topBar = {
|
Text(
|
||||||
TopAppBar(
|
text = "Your Lists",
|
||||||
title = {
|
fontWeight = FontWeight.SemiBold,
|
||||||
Column {
|
)
|
||||||
Text(
|
|
||||||
text = "Your Lists",
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
|
||||||
)
|
|
||||||
// HorizontalDivider()
|
// HorizontalDivider()
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(
|
|
||||||
onClick = { navigator.popBack() },
|
|
||||||
) {
|
|
||||||
ArrowBackIcon()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors =
|
|
||||||
TopAppBarDefaults
|
|
||||||
.topAppBarColors(
|
|
||||||
containerColor = AlertDialogDefaults.containerColor,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
floatingActionButton = {
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = {
|
|
||||||
navigator.popBack()
|
|
||||||
},
|
|
||||||
shape = ButtonBorder,
|
|
||||||
colors = ButtonDefaults.filledTonalButtonColors(),
|
|
||||||
elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 6.0.dp),
|
|
||||||
) {
|
|
||||||
Text(text = "Cancel", fontWeight = FontWeight.SemiBold)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) { contentPadding ->
|
navigationIcon = {
|
||||||
Column(
|
IconButton(
|
||||||
modifier =
|
onClick = { navigator.popBack() },
|
||||||
Modifier
|
) {
|
||||||
.verticalScroll(rememberScrollState())
|
ArrowBackIcon()
|
||||||
.padding(
|
}
|
||||||
start = 10.dp,
|
},
|
||||||
end = 10.dp,
|
colors =
|
||||||
top = contentPadding.calculateTopPadding(),
|
TopAppBarDefaults
|
||||||
bottom = contentPadding.calculateBottomPadding(),
|
.topAppBarColors(
|
||||||
).consumeWindowInsets(contentPadding)
|
containerColor = AlertDialogDefaults.containerColor,
|
||||||
.imePadding(),
|
),
|
||||||
) {
|
)
|
||||||
|
},
|
||||||
|
floatingActionButton = {
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = {
|
||||||
|
navigator.popBack()
|
||||||
|
},
|
||||||
|
shape = ButtonBorder,
|
||||||
|
colors = ButtonDefaults.filledTonalButtonColors(),
|
||||||
|
elevation = ButtonDefaults.elevatedButtonElevation(defaultElevation = 6.0.dp),
|
||||||
|
) {
|
||||||
|
Text(text = "Cancel", fontWeight = FontWeight.SemiBold)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) { contentPadding ->
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(
|
||||||
|
start = 10.dp,
|
||||||
|
end = 10.dp,
|
||||||
|
top = contentPadding.calculateTopPadding(),
|
||||||
|
bottom = contentPadding.calculateBottomPadding(),
|
||||||
|
).consumeWindowInsets(contentPadding)
|
||||||
|
.imePadding(),
|
||||||
|
) {
|
||||||
|
when (followSetsState) {
|
||||||
|
is FollowSetState.Loaded -> {
|
||||||
|
val lists = (followSetsState as FollowSetState.Loaded).feed
|
||||||
|
|
||||||
lists.forEachIndexed { index, list ->
|
lists.forEachIndexed { index, list ->
|
||||||
Spacer(StdVertSpacer)
|
Spacer(StdVertSpacer)
|
||||||
FollowSetItem(
|
FollowSetItem(
|
||||||
@@ -191,22 +194,78 @@ fun FollowSetsManagementDialog(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
FollowSetsCreationMenu(
|
}
|
||||||
userName = userInfo.toBestDisplayName(),
|
|
||||||
onSetCreate = { setName, setIsPrivate, description ->
|
FollowSetState.Empty -> {
|
||||||
followSetsViewModel.addFollowSet(
|
EmptyOrNoneFound { followSetsViewModel.refresh() }
|
||||||
setName = setName,
|
}
|
||||||
setDescription = description,
|
|
||||||
isListPrivate = setIsPrivate,
|
is FollowSetState.FeedError -> {
|
||||||
optionalFirstMemberHex = userHex,
|
val errorMsg = (followSetsState as FollowSetState.FeedError).errorMessage
|
||||||
account = account,
|
ErrorMessage(errorMsg) { followSetsViewModel.refresh() }
|
||||||
)
|
}
|
||||||
},
|
|
||||||
)
|
FollowSetState.Loading -> {
|
||||||
|
Loading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (followSetsState != FollowSetState.Loading) {
|
||||||
|
FollowSetsCreationMenu(
|
||||||
|
userName = userInfo.toBestDisplayName(),
|
||||||
|
onSetCreate = { setName, setIsPrivate, description ->
|
||||||
|
followSetsViewModel.addFollowSet(
|
||||||
|
setName = setName,
|
||||||
|
setDescription = description,
|
||||||
|
isListPrivate = setIsPrivate,
|
||||||
|
optionalFirstMemberHex = userHex,
|
||||||
|
account = account,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Loading() {
|
||||||
|
Column(
|
||||||
|
Modifier.fillMaxWidth().fillMaxHeight(0.5f),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
Text(stringRes(R.string.loading_feed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun EmptyOrNoneFound(onRefresh: () -> Unit) {
|
||||||
|
Column(
|
||||||
|
Modifier.fillMaxWidth().fillMaxHeight(0.5f),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
) {
|
||||||
|
Text("No follow sets were found, or you don't have any follow sets. Tap below to refresh, or use the menu to create one.")
|
||||||
|
Spacer(modifier = StdVertSpacer)
|
||||||
|
OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ErrorMessage(
|
||||||
|
errorMsg: String,
|
||||||
|
onRefresh: () -> Unit,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
Modifier.fillMaxWidth().fillMaxHeight(0.5f),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
) {
|
||||||
|
Text("There was a problem while fetching: $errorMsg")
|
||||||
|
Spacer(modifier = StdVertSpacer)
|
||||||
|
OutlinedButton(onClick = onRefresh) { Text(text = stringRes(R.string.refresh)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user