Improve Compose group paging (#6105)

This commit is contained in:
eliotcougar authored and GitHub committed 2026-08-29 15:53:37 +08:00
1 parent 3c9336f671
commit 26099c198e
2 files changed
+58 -46

No files matched your search

@@ -333,25 +333,14 @@ object CoreServiceManager {
}
}
val endpoint = if (time >= 0) SpeedtestManager.getRemoteIPInfo() else null
val result = ConnectionTestResult(
delayMillis = time,
errorMessage = errorStr,
country = endpoint?.country,
ipAddress = endpoint?.ipAddress,
)
MessageHelper.sendMsg2UI(service, AppConfig.MSG_MEASURE_DELAY_RESULT, result)
// Only fetch IP info if the delay test was successful
if (time >= 0) {
SpeedtestManager.getRemoteIPInfo()?.let { ip ->
MessageHelper.sendMsg2UI(
service,
AppConfig.MSG_MEASURE_DELAY_RESULT,
result.copy(
country = ip.country,
ipAddress = ip.ipAddress,
),
)
}
}
}
}
@@ -1,19 +1,27 @@
package com.v2ray.ang.ui.main
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryScrollableTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRowDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.v2ray.ang.dto.GroupMapItem
@@ -28,32 +36,34 @@ fun GroupTabBar(
onTabClick: (Int) -> Unit,
modifier: Modifier = Modifier
) {
PrimaryScrollableTabRow(
selectedTabIndex = selectedTabIndex.coerceIn(0, groups.lastIndex),
modifier = modifier.fillMaxWidth(),
containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f),
contentColor = MaterialTheme.colorScheme.onSurface,
edgePadding = 16.dp,
minTabWidth = 56.dp,
indicator = {
TabRowDefaults.PrimaryIndicator(
modifier = Modifier
.tabIndicatorOffset(
selectedTabIndex = selectedTabIndex.coerceIn(0, groups.lastIndex),
matchContentSize = true
)
.clip(RoundedCornerShape(3.dp)),
width = Dp.Unspecified,
color = MaterialTheme.colorScheme.secondary
)
},
divider = {}
val selectedIndex = selectedTabIndex.coerceIn(0, groups.lastIndex)
val listState = rememberLazyListState(initialFirstVisibleItemIndex = selectedIndex)
LaunchedEffect(selectedIndex) {
if (listState.layoutInfo.visibleItemsInfo.none { it.index == selectedIndex }) {
listState.animateScrollToItem(selectedIndex)
}
}
LazyRow(
state = listState,
modifier = modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface.copy(alpha = 0.95f)),
contentPadding = PaddingValues(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
groups.forEachIndexed { index, group ->
itemsIndexed(
items = groups,
key = { _, group -> group.id },
) { index, group ->
val serverFlow = remember(group.id, mainViewModel) {
mainViewModel.serversForGroup(group.id)
}
GroupTabItem(
group = group,
selected = index == selectedTabIndex,
serverFlowProvider = { mainViewModel.serversForGroup(group.id) },
selected = index == selectedIndex,
serverFlow = serverFlow,
onClick = { onTabClick(index) }
)
}
@@ -64,20 +74,22 @@ fun GroupTabBar(
private fun GroupTabItem(
group: GroupMapItem,
selected: Boolean,
serverFlowProvider: () -> StateFlow<List<ServersCache>>,
serverFlow: StateFlow<List<ServersCache>>,
onClick: () -> Unit
) {
val serverFlow = remember(group.id) { serverFlowProvider() }
val servers by serverFlow.collectAsStateWithLifecycle()
Tab(
selected = selected,
onClick = onClick,
text = {
val text = if (group.id.isEmpty()) {
group.remarks
} else {
"${group.remarks} (${servers.size})"
}
Box(Modifier.widthIn(min = 56.dp)) {
Tab(
selected = selected,
onClick = onClick,
modifier = Modifier.heightIn(min = 48.dp),
text = {
Text(
text = text,
maxLines = 1,
@@ -86,4 +98,15 @@ private fun GroupTabItem(
)
}
)
if (selected) {
Box(
Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(3.dp)
.clip(RoundedCornerShape(3.dp))
.background(MaterialTheme.colorScheme.secondary)
)
}
}
}