Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.github.kr328.clash.proxy.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.animateScrollBy
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -14,7 +15,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.selection.selectable
Expand Down Expand Up @@ -61,6 +64,7 @@ import com.github.kr328.clash.proxy.vm.ProxyViewModel
import com.github.kr328.clash.proxy.vm.ProxyViewModel.SelectedProxy
import com.github.kr328.clash.ui.component.Spacer
import com.github.kr328.clash.ui.component.TabbyScaffold
import com.github.kr328.clash.ui.icon.BaselineCircleCenter
import com.github.kr328.clash.ui.icon.BaselineFlashOn
import com.github.kr328.clash.ui.icon.BaselineMoreVert
import com.github.kr328.clash.ui.icon.TabbyIcons
Expand Down Expand Up @@ -124,6 +128,7 @@ private fun ProxyContent(
onProxySelected: (Int, String) -> Unit,
) {
var menuVisible by remember { mutableStateOf(false) }
var centerSelectedRequestVersion by remember { mutableStateOf(0) }
val currentGroup = uiState.groups.getOrNull(uiState.currentPage)
val showUrlTestAction = uiState.groupNames.isNotEmpty()

Expand Down Expand Up @@ -178,6 +183,13 @@ private fun ProxyContent(
}
}

IconButton(onClick = { centerSelectedRequestVersion += 1 }) {
Icon(
imageVector = TabbyIcons.BaselineCircleCenter,
contentDescription = stringResource(R.string.center_selected),
)
}

IconButton(onClick = { menuVisible = true }) {
Icon(
imageVector = TabbyIcons.BaselineMoreVert,
Expand All @@ -198,6 +210,7 @@ private fun ProxyContent(
ProxyPagerContent(
uiState = uiState,
selectedProxies = selectedProxies,
centerSelectedRequestVersion = centerSelectedRequestVersion,
onPageChanged = onPageChanged,
onProxySelected = onProxySelected,
)
Expand All @@ -210,6 +223,7 @@ private fun ProxyContent(
private fun ProxyPagerContent(
uiState: ProxyViewModel.UiState,
selectedProxies: List<SelectedProxy>,
centerSelectedRequestVersion: Int,
onPageChanged: (Int) -> Unit,
onProxySelected: (Int, String) -> Unit,
) {
Expand Down Expand Up @@ -245,6 +259,9 @@ private fun ProxyPagerContent(
index = page,
proxyLine = uiState.proxyLine,
group = uiState.groups.getOrNull(page) ?: ProxyViewModel.UiState.ProxyGroupUiState(),
selectedProxyName = selectedProxies.getOrNull(page)?.name,
isCurrentPage = page == pagerState.currentPage,
centerSelectedRequestVersion = centerSelectedRequestVersion,
selectedProxies = selectedProxies,
onProxySelected = onProxySelected,
)
Expand All @@ -257,17 +274,31 @@ private fun ProxyGroupPage(
index: Int,
proxyLine: Int,
group: ProxyViewModel.UiState.ProxyGroupUiState,
selectedProxyName: String?,
isCurrentPage: Boolean,
centerSelectedRequestVersion: Int,
selectedProxies: List<SelectedProxy>,
onProxySelected: (Int, String) -> Unit,
) {
val sources = group.sources
val refreshVersion = group.refreshVersion
val gridState = rememberLazyGridState()
val selectedControl = MaterialTheme.colorScheme.onPrimary
val selectedBackground = MaterialTheme.colorScheme.primary
val unselectedControl = MaterialTheme.colorScheme.onSurface
val unselectedBackground = MaterialTheme.colorScheme.surface

LaunchedEffect(centerSelectedRequestVersion, isCurrentPage, selectedProxyName, sources) {
if (!isCurrentPage || centerSelectedRequestVersion == 0) return@LaunchedEffect

val selectedIndex = sources.indexOfFirst { it.proxy.name == selectedProxyName }
if (selectedIndex < 0) return@LaunchedEffect

gridState.animateScrollItemToCenter(selectedIndex)
}

LazyVerticalGrid(
state = gridState,
columns = GridCells.Fixed(columnsForProxyLine(proxyLine)),
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(gridContentPadding),
Expand Down Expand Up @@ -487,6 +518,19 @@ private fun columnsForProxyLine(proxyLine: Int): Int =
else -> 3
}

private suspend fun LazyGridState.animateScrollItemToCenter(index: Int) {
animateScrollToItem(index)

val selectedItem = layoutInfo.visibleItemsInfo.firstOrNull { it.index == index } ?: return
val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2
val itemCenter = selectedItem.offset.y + selectedItem.size.height / 2
val delta = itemCenter - viewportCenter

if (delta != 0) {
animateScrollBy(delta.toFloat())
}
}

@PreviewWrapper(TabbyThemeWrapper::class)
@PreviewTabby
@Composable
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-ja-rJP/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">レイテンシ</string>
<string name="center_selected">選択項目を中央に表示</string>
<string name="delay_test">接続テスト</string>
<string name="doubles">ダブルカラム</string>
<string name="layout">レイアウト</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-ko-rKR/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">지연 수치</string>
<string name="center_selected">선택 항목 가운데로 이동</string>
<string name="delay_test">지연 수치 테스트</string>
<string name="doubles">더블</string>
<string name="layout">레이아웃</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="PluralsCandidate">

<string name="delay">Задержка</string>
<string name="center_selected">По центру к выбранному</string>
<string name="delay_test">Проверка задержки</string>
<string name="doubles">Двойное</string>
<string name="layout">Отображение</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-vi/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">Độ trễ</string>
<string name="center_selected">Đưa mục đã chọn vào giữa</string>
<string name="delay_test">Kiểm tra độ trễ</string>
<string name="doubles">Hai cột</string>
<string name="layout">Bố cục</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-zh-rHK/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">延遲</string>
<string name="center_selected">置中目前選擇</string>
<string name="delay_test">延遲測試</string>
<string name="doubles">雙列</string>
<string name="layout">佈局</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">延遲</string>
<string name="center_selected">置中目前選擇</string>
<string name="delay_test">延遲測試</string>
<string name="doubles">雙欄</string>
<string name="layout">佈局</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources>

<string name="delay">延迟</string>
<string name="center_selected">居中当前选择</string>
<string name="delay_test">延迟测试</string>
<string name="doubles">双列</string>
<string name="layout">布局</string>
Expand Down
1 change: 1 addition & 0 deletions ui/proxy/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="PluralsCandidate">

<string name="delay">Delay</string>
<string name="center_selected">Center Selected</string>
<string name="delay_test">Delay Test</string>
<string name="doubles">Double</string>
<string name="layout">Layout</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.github.kr328.clash.ui.icon

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp

@Suppress("UnusedReceiverParameter")
val TabbyIcons.BaselineCircleCenter: ImageVector
get() {
if (_BaselineCircleCenter != null) return _BaselineCircleCenter!!

_BaselineCircleCenter =
ImageVector.Builder(
name = "record-circle",
defaultWidth = 24.dp,
defaultHeight = 24.dp,
viewportWidth = 16f,
viewportHeight = 16f,
)
.apply {
path(fill = SolidColor(Color.White)) {
moveTo(8f, 15f)
arcTo(7f, 7f, 0f, true, true, 8f, 1f)
arcToRelative(7f, 7f, 0f, false, true, 0f, 14f)
moveToRelative(0f, 1f)
arcTo(8f, 8f, 0f, true, false, 8f, 0f)
arcToRelative(8f, 8f, 0f, false, false, 0f, 16f)
}
path(fill = SolidColor(Color.White)) {
moveTo(11f, 8f)
arcToRelative(3f, 3f, 0f, true, true, -6f, 0f)
arcToRelative(3f, 3f, 0f, false, true, 6f, 0f)
}
}
.build()

return _BaselineCircleCenter!!
}

@Suppress("ObjectPropertyName") private var _BaselineCircleCenter: ImageVector? = null