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.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
@@ -24,7 +23,6 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -60,8 +58,6 @@ fun keyboardAsState(): State<Keyboard> {
val keyboardState = remember { mutableStateOf(Keyboard.Closed) }
val view = LocalView.current
println("AAA - KeyboardState")
DisposableEffect(view) {
val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
val rect = Rect()
@@ -128,8 +124,6 @@ private fun RowScope.HasNewItemsIcon(
}
}
println("AAA HasNewItemsIcon")
val size = remember {
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.SpinnerSelectionDialog
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.HalfVertSpacer
import com.vitorpamplona.amethyst.ui.theme.HeaderPictureModifier
@@ -376,11 +377,9 @@ fun StoriesTopBar(followLists: FollowListViewModel, drawerState: DrawerState, ac
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.storiesListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList(
FollowListWithRoutes(
followListsModel = followLists,
listName = list,
withGlobal = true,
withRoutes = false
listName = list
) { listName ->
accountViewModel.account.changeDefaultStoriesFollowList(listName.code)
}
@@ -392,11 +391,9 @@ fun HomeTopBar(followLists: FollowListViewModel, drawerState: DrawerState, accou
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.homeListLiveData.observeAsState(KIND3_FOLLOWS)
FollowList(
FollowListWithRoutes(
followListsModel = followLists,
listName = list,
withGlobal = true,
withRoutes = true
listName = list
) { listName ->
if (listName.type == CodeNameType.ROUTE) {
nav(listName.code)
@@ -412,11 +409,9 @@ fun NotificationTopBar(followLists: FollowListViewModel, drawerState: DrawerStat
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.notificationListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList(
FollowListWithoutRoutes(
followListsModel = followLists,
listName = list,
withGlobal = true,
withRoutes = false
listName = list
) { listName ->
accountViewModel.account.changeDefaultNotificationFollowList(listName.code)
}
@@ -428,11 +423,9 @@ fun DiscoveryTopBar(followLists: FollowListViewModel, drawerState: DrawerState,
GenericMainTopBar(drawerState, accountViewModel, nav) { accountViewModel ->
val list by accountViewModel.discoveryListLiveData.observeAsState(GLOBAL_FOLLOWS)
FollowList(
FollowListWithoutRoutes(
followListsModel = followLists,
listName = list,
withGlobal = true,
withRoutes = false
listName = list
) { listName ->
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
) {
val profilePicture by accountViewModel.account.userProfile().live().profilePictureChanges.observeAsState()
val pubkeyHex = remember { accountViewModel.userProfile().pubkeyHex }
val automaticallyShowProfilePicture = remember {
@@ -536,42 +528,35 @@ private fun LoggedInUserPictureDrawer(
}
@Composable
fun FollowList(
fun FollowListWithRoutes(
followListsModel: FollowListViewModel,
listName: String,
withGlobal: Boolean,
withRoutes: Boolean,
onChange: (CodeName) -> Unit
) {
val context = LocalContext.current
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()
}
}
val allLists by followListsModel.kind3GlobalPeopleRoutes.collectAsState()
SimpleTextSpinner(
placeholder = allLists.firstOrNull { it.code == listName }?.name?.name() ?: "Select an Option",
options = followNames,
placeholderCode = listName,
options = allLists,
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 fun name(): String
open fun name(context: Context) = name()
}
class GeoHashName(val geoHashTag: String) : Name() {
@@ -590,8 +576,9 @@ class GeoHashName(val geoHashTag: String) : Name() {
class HashtagName(val hashTag: String) : Name() {
override fun name() = "#$hashTag"
}
class ResourceName(val resourceId: Int, val context: Context) : Name() {
override fun name() = context.getString(resourceId)
class ResourceName(val resourceId: Int) : Name() {
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() {
@@ -606,11 +593,14 @@ data class CodeName(val code: String, val name: Name, val type: CodeNameType)
@Stable
class FollowListViewModel(val account: Account) : ViewModel() {
private var _peopleLists = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val peopleLists = _peopleLists.asStateFlow()
val kind3Follow = CodeName(KIND3_FOLLOWS, ResourceName(R.string.follow_list_kind3follows), CodeNameType.HARDCODED)
val globalFollow = CodeName(GLOBAL_FOLLOWS, ResourceName(R.string.follow_list_global), CodeNameType.HARDCODED)
private var _routes = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val routes = _routes.asStateFlow()
private var _kind3GlobalPeopleRoutes = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val kind3GlobalPeopleRoutes = _kind3GlobalPeopleRoutes.asStateFlow()
private var _kind3GlobalPeople = MutableStateFlow<ImmutableList<CodeName>>(emptyList<CodeName>().toPersistentList())
val kind3GlobalPeople = _kind3GlobalPeople.asStateFlow()
fun refresh() {
viewModelScope.launch(Dispatchers.Default) {
@@ -632,11 +622,7 @@ class FollowListViewModel(val account: Account) : ViewModel() {
} else {
null
}
}.sortedBy { it.name.name() }.toImmutableList()
if (!equalImmutableLists(_peopleLists.value, newFollowLists)) {
_peopleLists.emit(newFollowLists)
}
}.sortedBy { it.name.name() }
val communities = account.userProfile().cachedFollowingCommunitiesSet().mapNotNull {
LocalCache.checkGetOrCreateAddressableNote(it)?.let { communityNote ->
@@ -652,10 +638,18 @@ class FollowListViewModel(val account: Account) : ViewModel() {
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)) {
_routes.emit(routeList)
val kind3GlobalPeopleRouteList = listOf(listOf(kind3Follow, globalFollow), newFollowLists, routeList).flatten().toImmutableList()
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
fun SimpleTextSpinner(
placeholder: String,
options: ImmutableList<Name>,
placeholderCode: String,
options: ImmutableList<CodeName>,
onSelect: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val interactionSource = remember { MutableInteractionSource() }
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(
modifier = modifier,
@@ -706,7 +710,7 @@ fun SimpleTextSpinner(
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.size(20.dp))
Text(placeholder)
Text(currentText)
Icon(
imageVector = Icons.Default.ExpandMore,
null,
@@ -732,22 +736,22 @@ fun SimpleTextSpinner(
options = options,
onDismiss = { optionsShowing = false },
onSelect = {
currentText = options[it].name()
currentText = options[it].name.name(context)
optionsShowing = false
onSelect(it)
}
) {
RenderOption(it)
RenderOption(it.name)
}
}
}
}
@Composable
fun RenderOption(it: Name) {
when (it) {
fun RenderOption(option: Name) {
when (option) {
is GeoHashName -> {
LoadCityName(it.geoHashTag) {
LoadCityName(option.geoHashTag) {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
@@ -761,7 +765,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
) {
Text(text = it.name(), color = MaterialTheme.colorScheme.onSurface)
Text(text = option.name(), color = MaterialTheme.colorScheme.onSurface)
}
}
is ResourceName -> {
@@ -769,7 +773,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center,
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 -> {
@@ -777,7 +781,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
) {
Text(text = it.name(), color = MaterialTheme.colorScheme.onSurface)
Text(text = option.name(), color = MaterialTheme.colorScheme.onSurface)
}
}
is CommunityName -> {
@@ -785,7 +789,7 @@ fun RenderOption(it: Name) {
horizontalArrangement = Arrangement.Center,
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()
}.observeAsState()
+2
View File
@@ -600,4 +600,6 @@
<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_description">Show Profile pictures</string>
<string name="select_an_option">Select an Option</string>
</resources>