From 74e7e19cf2a639afe23ac84960a2ae16629e64d0 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Thu, 8 Oct 2026 02:26:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(satellites):=20=E5=8B=BE=E9=80=89=E7=BD=AE?= =?UTF-8?q?=E9=A1=B6=E6=98=BE=E7=A4=BA=E2=80=94=E2=80=94=E5=B7=B2=E9=80=89?= =?UTF-8?q?/=E5=8F=AF=E7=94=A8=E5=88=86=E7=BB=84=EF=BC=8B=E9=A1=B6?= =?UTF-8?q?=E9=83=A8=E8=AE=A1=E6=95=B0=E6=9D=A1=EF=BC=88=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E4=B8=8A=E6=B8=B8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/data/repository/SelectionRepo.kt | 11 ++++- .../repository/SelectionRepoSearchTest.kt | 18 +++++++ .../src/main/res/values-es/strings.xml | 4 ++ .../src/main/res/values-ru/strings.xml | 4 ++ .../src/main/res/values-si/strings.xml | 4 ++ .../src/main/res/values-tr/strings.xml | 4 ++ .../src/main/res/values-uk/strings.xml | 4 ++ .../src/main/res/values-zh/strings.xml | 4 ++ .../src/main/res/values/strings.xml | 4 ++ .../feature/satellites/SatellitesScreen.kt | 47 ++++++++++++++++++- 10 files changed, 101 insertions(+), 3 deletions(-) diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SelectionRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SelectionRepo.kt index 2f961397..bcac043b 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SelectionRepo.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SelectionRepo.kt @@ -66,8 +66,17 @@ class SelectionRepo( } } + // Selected satellites are pinned to the top (matches upstream); ordering + // within each group stays name/catnum. Sits on the reactive chain, so + // ticking an entry re-sorts the visible list immediately. private val itemsWithQuery = currentQuery.flatMapLatest { query -> - itemsWithTypes.map { items -> filterByQuery(items, query) } + itemsWithTypes.map { items -> + filterByQuery(items, query).sortedWith( + compareByDescending { it.isSelected } + .thenBy { it.name } + .thenBy { it.catnum } + ) + } } override fun getCurrentTypes() = currentTypes.value diff --git a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/SelectionRepoSearchTest.kt b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/SelectionRepoSearchTest.kt index 4207fdc9..3449e2f5 100644 --- a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/SelectionRepoSearchTest.kt +++ b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/SelectionRepoSearchTest.kt @@ -284,6 +284,24 @@ class SelectionRepoSearchTest { assertEquals(sampleItems.map { it.catnum }.toSet(), results.map { it.catnum }.toSet()) } + @Test + fun `selected satellites are shown first`() = runTest { + // Pinning ported from upstream: ticked satellites sort above the rest, + // each group keeping the name order. + val repo = createRepo( + items = listOf( + SatItem(catnum = 44444, name = "Zeta"), + SatItem(catnum = 25544, name = "Alpha"), + SatItem(catnum = 40967, name = "Beta") + ) + ) + val flow = repo.getEntriesFlow() + repo.setSelection(listOf(40967), true) + val results = flow.first() + assertEquals(listOf(40967, 25544, 44444), results.map { it.catnum }) + assertEquals(listOf(true, false, false), results.map { it.isSelected }) + } + private fun createRepo( items: List, sstvIds: List = emptyList() diff --git a/core/presentation/src/main/res/values-es/strings.xml b/core/presentation/src/main/res/values-es/strings.xml index 46b1f131..2e70c3f2 100644 --- a/core/presentation/src/main/res/values-es/strings.xml +++ b/core/presentation/src/main/res/values-es/strings.xml @@ -19,6 +19,10 @@ Vaciar Vaciar todo Seleccionar todo + Seleccionados + Disponibles + Seleccionados (%1$d) + Disponibles (%1$d) Asegúrese de que su consulta de búsqueda sea correcta y que la base de datos esté actualizada Alarma\! diff --git a/core/presentation/src/main/res/values-ru/strings.xml b/core/presentation/src/main/res/values-ru/strings.xml index 0d332c66..22981379 100644 --- a/core/presentation/src/main/res/values-ru/strings.xml +++ b/core/presentation/src/main/res/values-ru/strings.xml @@ -19,6 +19,10 @@ Очистить Очистить Выбрать + Выбранные + Доступные + Выбранные (%1$d) + Доступные (%1$d) Убедитесь, что ваш поисковый запрос верен и база данных обновлена Внимание\! diff --git a/core/presentation/src/main/res/values-si/strings.xml b/core/presentation/src/main/res/values-si/strings.xml index ec3ed49b..7b356f94 100644 --- a/core/presentation/src/main/res/values-si/strings.xml +++ b/core/presentation/src/main/res/values-si/strings.xml @@ -19,6 +19,10 @@ පිරිසිදු ක° සියල්ල පිරිසිදු ක° සියල්ල තෝරන්න + තෝරාගත් + තිබෙන + තෝරාගත් (%1$d) + තිබෙන (%1$d) ඔබගේ සෙවුම් විමසුම නිවැරදි බවත් දත්ත සමුදාය යාවත්කාලීන කර ඇති බවත් සහතික කර ගන්න අවවාදයයි\! diff --git a/core/presentation/src/main/res/values-tr/strings.xml b/core/presentation/src/main/res/values-tr/strings.xml index 7e57e25c..182436db 100644 --- a/core/presentation/src/main/res/values-tr/strings.xml +++ b/core/presentation/src/main/res/values-tr/strings.xml @@ -20,6 +20,10 @@ Temizle Tümünü temizle Tümünü seç + Seçilenler + Kullanılabilir + Seçilenler (%1$d) + Kullanılabilir (%1$d) "Arama sorgunuzun doğru olduğundan ve veritabanının güncellendiğinden emin olun" Uyarı\! diff --git a/core/presentation/src/main/res/values-uk/strings.xml b/core/presentation/src/main/res/values-uk/strings.xml index d747a6bf..7a192ea1 100644 --- a/core/presentation/src/main/res/values-uk/strings.xml +++ b/core/presentation/src/main/res/values-uk/strings.xml @@ -19,6 +19,10 @@ Очистити Очистити всі Вибрати всі + Обрані + Доступні + Обрані (%1$d) + Доступні (%1$d) Переконайтеся, що ваш пошуковий запит правильний, а база даних оновлена Увага\! diff --git a/core/presentation/src/main/res/values-zh/strings.xml b/core/presentation/src/main/res/values-zh/strings.xml index 45fb505c..8cd61a33 100644 --- a/core/presentation/src/main/res/values-zh/strings.xml +++ b/core/presentation/src/main/res/values-zh/strings.xml @@ -20,6 +20,10 @@ 清空 全部清空 全选 + 已选择 + 可用 + 已选择(%1$d) + 可用(%1$d) 请确保您的搜索查询正确且数据库已更新 警告\! 此应用收录了超过9000颗卫星信息\n同时追踪所有卫星并不现实\n建议始终通过搜索和分类筛选功能仅勾选您感兴趣的卫星 diff --git a/core/presentation/src/main/res/values/strings.xml b/core/presentation/src/main/res/values/strings.xml index b07db58f..7c4e98d8 100644 --- a/core/presentation/src/main/res/values/strings.xml +++ b/core/presentation/src/main/res/values/strings.xml @@ -21,6 +21,10 @@ Clear Clear all Select all + Selected + Available + Selected (%1$d) + Available (%1$d) "Make sure your search query is correct and the DB is updated" Warning\! diff --git a/feature/satellites/src/main/java/com/rtbishop/look4sat/feature/satellites/SatellitesScreen.kt b/feature/satellites/src/main/java/com/rtbishop/look4sat/feature/satellites/SatellitesScreen.kt index 6310ce27..b7cebe91 100644 --- a/feature/satellites/src/main/java/com/rtbishop/look4sat/feature/satellites/SatellitesScreen.kt +++ b/feature/satellites/src/main/java/com/rtbishop/look4sat/feature/satellites/SatellitesScreen.kt @@ -326,9 +326,52 @@ private fun SatellitesPreview() { @Composable private fun SatellitesCard(items: List, onSelected: (Int, Boolean) -> Unit) { + val selectedItems = items.filter { it.isSelected } + val availableItems = items.filterNot { it.isSelected } + LazyVerticalGrid(columns = GridCells.Adaptive(320.dp)) { - items(items = items, key = { item -> item.catnum }) { entry -> - Satellite(entry, onSelected, Modifier.animateItem()) + stickyHeader(key = "sat_summary_header") { + SummaryHeader( + selectedText = stringResource(R.string.sat_group_selected_count, selectedItems.size), + availableText = stringResource(R.string.sat_group_available_count, availableItems.size) + ) + } + + if (selectedItems.isNotEmpty()) { + items(items = selectedItems, key = { item -> item.catnum }) { entry -> + Satellite(entry, onSelected, Modifier.animateItem()) + } + } + + if (availableItems.isNotEmpty()) { + items(items = availableItems, key = { item -> item.catnum }) { entry -> + Satellite(entry, onSelected, Modifier.animateItem()) + } } } } + +@Composable +private fun SummaryHeader(selectedText: String, availableText: String) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surfaceContainerHighest) + .padding(horizontal = 12.dp, vertical = 4.dp) + ) { + Text( + text = selectedText, + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Text( + text = availableText, + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.SemiBold, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } +}