Speeds the composition of the Topbar

This commit is contained in:
Vitor Pamplona
2023-09-30 17:23:27 -04:00
parent ff9e1556d5
commit bac50668e8
3 changed files with 80 additions and 80 deletions
@@ -6,7 +6,6 @@ import androidx.compose.foundation.background
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.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
@@ -24,7 +23,6 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment 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
@@ -60,8 +58,6 @@ fun keyboardAsState(): State<Keyboard> {
val keyboardState = remember { mutableStateOf(Keyboard.Closed) } val keyboardState = remember { mutableStateOf(Keyboard.Closed) }
val view = LocalView.current val view = LocalView.current
println("AAA - KeyboardState")
DisposableEffect(view) { DisposableEffect(view) {
val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener { val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
val rect = Rect() val rect = Rect()
@@ -128,8 +124,6 @@ private fun RowScope.HasNewItemsIcon(
} }
} }
println("AAA HasNewItemsIcon")
val size = remember { val size = remember {
if ("Home" == route.base) 25.dp else 23.dp if ("Home" == route.base) 25.dp else 23.dp
} }
@@ -108,6 +108,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.RoomNameOnlyDisplay
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ShortChannelHeader import com.vitorpamplona.amethyst.ui.screen.loggedIn.ShortChannelHeader
import com.vitorpamplona.amethyst.ui.screen.loggedIn.SpinnerSelectionDialog import com.vitorpamplona.amethyst.ui.screen.loggedIn.SpinnerSelectionDialog
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.HalfVertSpacer import com.vitorpamplona.amethyst.ui.theme.HalfVertSpacer
import com.vitorpamplona.amethyst.ui.theme.HeaderPictureModifier import com.vitorpamplona.amethyst.ui.theme.HeaderPictureModifier
@@ -376,11 +377,9 @@ fun StoriesTopBar(followLists: FollowListViewModel, drawerState: DrawerState, ac
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel -> GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.storiesListLiveData.observeAsState(GLOBAL_FOLLOWS) val list by accountViewModel.storiesListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList( FollowListWithRoutes(
followListsModel = followLists, followListsModel = followLists,
listName = list, listName = list
withGlobal = true,
withRoutes = false
) { listName -> ) { listName ->
accountViewModel.account.changeDefaultStoriesFollowList(listName.code) accountViewModel.account.changeDefaultStoriesFollowList(listName.code)
} }
@@ -392,11 +391,9 @@ fun HomeTopBar(followLists: FollowListViewModel, drawerState: DrawerState, accou
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel -> GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.homeListLiveData.observeAsState(KIND3_FOLLOWS) val list by accountViewModel.homeListLiveData.observeAsState(KIND3_FOLLOWS)
FollowList( FollowListWithRoutes(
followListsModel = followLists, followListsModel = followLists,
listName = list, listName = list
withGlobal = true,
withRoutes = true
) { listName -> ) { listName ->
if (listName.type == CodeNameType.ROUTE) { if (listName.type == CodeNameType.ROUTE) {
nav(listName.code) nav(listName.code)
@@ -412,11 +409,9 @@ fun NotificationTopBar(followLists: FollowListViewModel, drawerState: DrawerStat
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel -> GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.notificationListLiveData.observeAsState(GLOBAL_FOLLOWS) val list by accountViewModel.notificationListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList( FollowListWithoutRoutes(
followListsModel = followLists, followListsModel = followLists,
listName = list, listName = list
withGlobal = true,
withRoutes = false
) { listName -> ) { listName ->
accountViewModel.account.changeDefaultNotificationFollowList(listName.code) accountViewModel.account.changeDefaultNotificationFollowList(listName.code)
} }
@@ -428,11 +423,9 @@ fun DiscoveryTopBar(followLists: FollowListViewModel, drawerState: DrawerState,
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel -> GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.discoveryListLiveData.observeAsState(GLOBAL_FOLLOWS) val list by accountViewModel.discoveryListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList( FollowListWithoutRoutes(
followListsModel = followLists, followListsModel = followLists,
listName = list, listName = list
withGlobal = true,
withRoutes = false
) { listName -> ) { listName ->
accountViewModel.account.changeDefaultDiscoveryFollowList(listName.code) accountViewModel.account.changeDefaultDiscoveryFollowList(listName.code)
} }
@@ -491,7 +484,7 @@ fun GenericMainTopBar(
} }
} }
) )
Divider(thickness = 0.25.dp) Divider(thickness = DividerThickness)
} }
} }
@@ -510,7 +503,6 @@ private fun LoggedInUserPictureDrawer(
onClick: () -> Unit onClick: () -> Unit
) { ) {
val profilePicture by accountViewModel.account.userProfile().live().profilePictureChanges.observeAsState() val profilePicture by accountViewModel.account.userProfile().live().profilePictureChanges.observeAsState()
val pubkeyHex = remember { accountViewModel.userProfile().pubkeyHex } val pubkeyHex = remember { accountViewModel.userProfile().pubkeyHex }
val automaticallyShowProfilePicture = remember { val automaticallyShowProfilePicture = remember {
@@ -536,42 +528,35 @@ private fun LoggedInUserPictureDrawer(
} }
@Composable @Composable
fun FollowList( fun FollowListWithRoutes(
followListsModel: FollowListViewModel, followListsModel: FollowListViewModel,
listName: String, listName: String,
withGlobal: Boolean,
withRoutes: Boolean,
onChange: (CodeName) -> Unit onChange: (CodeName) -> Unit
) { ) {
val context = LocalContext.current val allLists by followListsModel.kind3GlobalPeopleRoutes.collectAsState()
val kind3Follow = CodeName(KIND3_FOLLOWS, ResourceName(R.string.follow_list_kind3follows, context), CodeNameType.HARDCODED)
val globalFollow = CodeName(GLOBAL_FOLLOWS, ResourceName(R.string.follow_list_global, context), CodeNameType.HARDCODED)
val defaultOptions = if (withGlobal) listOf(kind3Follow, globalFollow) else listOf(kind3Follow)
val followLists by followListsModel.peopleLists.collectAsState()
val routeList by followListsModel.routes.collectAsState()
val allLists = remember(followLists) {
if (withRoutes) {
(defaultOptions + followLists + routeList)
} else {
(defaultOptions + followLists)
}
}
val followNames by remember(followLists) {
derivedStateOf {
allLists.map { it.name }.toImmutableList()
}
}
SimpleTextSpinner( SimpleTextSpinner(
placeholder = allLists.firstOrNull { it.code == listName }?.name?.name() ?: "Select an Option", placeholderCode = listName,
options = followNames, options = allLists,
onSelect = { onSelect = {
onChange(allLists.getOrNull(it) ?: kind3Follow) onChange(allLists.getOrNull(it) ?: followListsModel.kind3Follow)
}
)
}
@Composable
fun FollowListWithoutRoutes(
followListsModel: FollowListViewModel,
listName: String,
onChange: (CodeName) -> Unit
) {
val allLists by followListsModel.kind3GlobalPeople.collectAsState()
SimpleTextSpinner(
placeholderCode = listName,
options = allLists,
onSelect = {
onChange(allLists.getOrNull(it) ?: followListsModel.kind3Follow)
} }
) )
} }
@@ -582,6 +567,7 @@ enum class CodeNameType {
abstract class Name { abstract class Name {
abstract fun name(): String abstract fun name(): String
open fun name(context: Context) = name()
} }
class GeoHashName(val geoHashTag: String) : Name() { class GeoHashName(val geoHashTag: String) : Name() {
@@ -590,8 +576,9 @@ class GeoHashName(val geoHashTag: String) : Name() {
class HashtagName(val hashTag: String) : Name() { class HashtagName(val hashTag: String) : Name() {
override fun name() = "#$hashTag" override fun name() = "#$hashTag"
} }
class ResourceName(val resourceId: Int, val context: Context) : Name() { class ResourceName(val resourceId: Int) : Name() {
override fun name() = context.getString(resourceId) override fun name() = " $resourceId " // Space to make sure it goes first
override fun name(context: Context) = context.getString(resourceId)
} }
class PeopleListName(val note: AddressableNote) : Name() { class PeopleListName(val note: AddressableNote) : Name() {
@@ -606,11 +593,14 @@ data class CodeName(val code: String, val name: Name, val type: CodeNameType)
@Stable @Stable
class FollowListViewModel(val account: Account) : ViewModel() { class FollowListViewModel(val account: Account) : ViewModel() {
private var _peopleLists = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList()) val kind3Follow = CodeName(KIND3_FOLLOWS, ResourceName(R.string.follow_list_kind3follows), CodeNameType.HARDCODED)
val peopleLists = _peopleLists.asStateFlow() val globalFollow = CodeName(GLOBAL_FOLLOWS, ResourceName(R.string.follow_list_global), CodeNameType.HARDCODED)
private var _routes = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList()) private var _kind3GlobalPeopleRoutes = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val routes = _routes.asStateFlow() val kind3GlobalPeopleRoutes = _kind3GlobalPeopleRoutes.asStateFlow()
private var _kind3GlobalPeople = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val kind3GlobalPeople = _kind3GlobalPeople.asStateFlow()
fun refresh() { fun refresh() {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
@@ -632,11 +622,7 @@ class FollowListViewModel(val account: Account) : ViewModel() {
} else { } else {
null null
} }
}.sortedBy { it.name.name() }.toImmutableList() }.sortedBy { it.name.name() }
if (!equalImmutableLists(_peopleLists.value, newFollowLists)) {
_peopleLists.emit(newFollowLists)
}
val communities = account.userProfile().cachedFollowingCommunitiesSet().mapNotNull { val communities = account.userProfile().cachedFollowingCommunitiesSet().mapNotNull {
LocalCache.checkGetOrCreateAddressableNote(it)?.let { communityNote -> LocalCache.checkGetOrCreateAddressableNote(it)?.let { communityNote ->
@@ -652,10 +638,18 @@ class FollowListViewModel(val account: Account) : ViewModel() {
CodeName("Geohash/$it", GeoHashName(it), CodeNameType.ROUTE) CodeName("Geohash/$it", GeoHashName(it), CodeNameType.ROUTE)
} }
val routeList = (communities + hashtags + geotags).sortedBy { it.name.name() }.toImmutableList() val routeList = (communities + hashtags + geotags).sortedBy { it.name.name() }
if (!equalImmutableLists(_routes.value, routeList)) { val kind3GlobalPeopleRouteList = listOf(listOf(kind3Follow, globalFollow), newFollowLists, routeList).flatten().toImmutableList()
_routes.emit(routeList)
if (!equalImmutableLists(_kind3GlobalPeopleRoutes.value, kind3GlobalPeopleRouteList)) {
_kind3GlobalPeopleRoutes.emit(kind3GlobalPeopleRouteList)
}
val kind3GlobalPeopleList = listOf(listOf(kind3Follow, globalFollow), newFollowLists).flatten().toImmutableList()
if (!equalImmutableLists(_kind3GlobalPeople.value, kind3GlobalPeopleList)) {
_kind3GlobalPeople.emit(kind3GlobalPeopleList)
} }
} }
@@ -691,14 +685,24 @@ class FollowListViewModel(val account: Account) : ViewModel() {
@Composable @Composable
fun SimpleTextSpinner( fun SimpleTextSpinner(
placeholder: String, placeholderCode: String,
options: ImmutableList<Name>, options: ImmutableList<CodeName>,
onSelect: (Int) -> Unit, onSelect: (Int) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
var optionsShowing by remember { mutableStateOf(false) } var optionsShowing by remember { mutableStateOf(false) }
var currentText by remember(placeholder) { mutableStateOf(placeholder) }
val context = LocalContext.current
val selectAnOption = stringResource(
id = R.string.select_an_option
)
var currentText by remember {
mutableStateOf(
options.firstOrNull { it.code == placeholderCode }?.name?.name(context) ?: selectAnOption
)
}
Box( Box(
modifier = modifier, modifier = modifier,
@@ -706,7 +710,7 @@ fun SimpleTextSpinner(
) { ) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.size(20.dp)) Spacer(modifier = Modifier.size(20.dp))
Text(placeholder) Text(currentText)
Icon( Icon(
imageVector = Icons.Default.ExpandMore, imageVector = Icons.Default.ExpandMore,
null, null,
@@ -732,22 +736,22 @@ fun SimpleTextSpinner(
options = options, options = options,
onDismiss = { optionsShowing = false }, onDismiss = { optionsShowing = false },
onSelect = { onSelect = {
currentText = options[it].name() currentText = options[it].name.name(context)
optionsShowing = false optionsShowing = false
onSelect(it) onSelect(it)
} }
) { ) {
RenderOption(it) RenderOption(it.name)
} }
} }
} }
} }
@Composable @Composable
fun RenderOption(it: Name) { fun RenderOption(option: Name) {
when (it) { when (option) {
is GeoHashName -> { is GeoHashName -> {
LoadCityName(it.geoHashTag) { LoadCityName(option.geoHashTag) {
Row( Row(
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
@@ -761,7 +765,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text(text = it.name(), color = MaterialTheme.colorScheme.onSurface) Text(text = option.name(), color = MaterialTheme.colorScheme.onSurface)
} }
} }
is ResourceName -> { is ResourceName -> {
@@ -769,7 +773,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text(text = stringResource(id = it.resourceId), color = MaterialTheme.colorScheme.onSurface) Text(text = stringResource(id = option.resourceId), color = MaterialTheme.colorScheme.onSurface)
} }
} }
is PeopleListName -> { is PeopleListName -> {
@@ -777,7 +781,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
Text(text = it.name(), color = MaterialTheme.colorScheme.onSurface) Text(text = option.name(), color = MaterialTheme.colorScheme.onSurface)
} }
} }
is CommunityName -> { is CommunityName -> {
@@ -785,7 +789,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
val name by it.note.live().metadata.map { val name by option.note.live().metadata.map {
"/n/" + (it.note as? AddressableNote)?.dTag() "/n/" + (it.note as? AddressableNote)?.dTag()
}.observeAsState() }.observeAsState()
+2
View File
@@ -600,4 +600,6 @@
<string name="hide_new_word_label">Hide new word or sentence</string> <string name="hide_new_word_label">Hide new word or sentence</string>
<string name="automatically_show_profile_picture">Profile Picture</string> <string name="automatically_show_profile_picture">Profile Picture</string>
<string name="automatically_show_profile_picture_description">Show Profile pictures</string> <string name="automatically_show_profile_picture_description">Show Profile pictures</string>
<string name="select_an_option">Select an Option</string>
</resources> </resources>