fix(settings): drag-reorder tracks live position; grip becomes a single dot

Two drag issues from user testing:
1. Only adjacent swaps worked - the drag gesture could not move an
   item past multiple positions. Root cause: the pointerInput closure
   kept the index captured at composition; after the live swap
   (items.add(target, removeAt(index))) the closure's index was
   stale, so subsequent targets were computed from the wrong origin
   and the saved order got corrupted (also made previously moved
   items snap back).
   Fix: track the dragged item's live position via draggingIndex -
   onDragStart resolves it with items.indexOf(screen), onDrag computes
   the target from draggingIndex and updates it after each swap.
2. The six-dot grip icon was ugly; replaced with a single 8dp themed
   dot (Box + CircleShape inside the 48dp touch area, onSurfaceVariant
   color). ic_drag.xml removed.

What's-new rewritten in en/zh/tr with ONLY this release's changes
(user rule: replace, never append history). Version stays 4.4.9
(覆盖 per user). Verified: settings + app compile, check_strings.py
clean.
This commit is contained in:
mckero committed 2026-08-04 01:10:13 +00:00
1 parent 6636dd8e98
commit ff408747cd
5 files changed
+26 -23

No files matched your search

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,18c0,1.1 -0.9,2 -2,2s-2,-0.9 -2,-2 0.9,-2 2,-2 2,0.9 2,2zM9,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM9,4c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM15,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM15,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM15,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
</vector>
@@ -51,7 +51,8 @@
\n\nDoğru tahminler alabilmek için veritabanını en az haftada bir güncelleyin.</string>
<string name="pass_whatsnew_title" translatable="false">What\'s new in Look4Sat</string>
<string name="pass_whatsnew_message" translatable="false">
* Ayarlar sayfasında kaydırırken oluşan çökme düzeltildi (sayfa sırası listesi yüksekliği)</string>
* Ayarlar sayfasında kaydırırken oluşan çökme düzeltildi
* Sayfa sırası: tek hareketle birden fazla konum atlanabilir; tutamaç tek nokta oldu</string>
<!-- Radar screen -->
<string name="radar_back">Geri</string>
@@ -41,7 +41,8 @@
<string name="pass_welcome_message">请务必在设置中通过GPS、经纬度或QTH定位您的位置\n建议至少每周更新一次数据库,以确保预测结果的准确性</string>
<string name="pass_whatsnew_title">Look4Sat Pro 更新内容</string>
<string name="pass_whatsnew_message" translatable="false">
* 修复设置页滑动时闪退的问题(页面顺序列表高度)</string>
* 修复设置页滑动时闪退的问题
* 页面顺序:可一次拖动越过多个位置;拖拽手柄改为小圆点</string>
<!-- Radar screen -->
<string name="radar_back">后退</string>
@@ -53,7 +53,8 @@
\n\nPlease update the database at least weekly to get accurate predictions.</string>
<string name="pass_whatsnew_title" translatable="false">What\'s new in Look4Sat</string>
<string name="pass_whatsnew_message" translatable="false">
* Fixed a crash when scrolling the Settings page (page-order list height)</string>
* Fixed a crash when scrolling the Settings page
* Page order: drag a page past multiple positions in one gesture; grip is now a single dot</string>
<!-- Radar screen -->
<string name="radar_back">Back</string>
@@ -22,15 +22,19 @@ import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.height
@@ -639,23 +643,22 @@ private fun DragOrderList(
text = stringResource(id = screen.first),
modifier = Modifier.weight(1f)
)
Icon(
painter = painterResource(id = R.drawable.ic_drag),
contentDescription = stringResource(id = R.string.prefs_ui_order_title),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
Box(
modifier = Modifier
.size(48.dp)
.padding(20.dp)
.pointerInput(screen.second) {
detectDragGestures(
onDragStart = { draggingIndex = index },
onDragStart = { draggingIndex = items.indexOf(screen) },
onDrag = { change, dragAmount ->
change.consume()
dragOffset += dragAmount.y
val target = (index + (dragOffset / itemHeightPx).roundToInt())
val currentIndex = draggingIndex
val target = (currentIndex + (dragOffset / itemHeightPx).roundToInt())
.coerceIn(0, items.size - 1)
if (target != index) {
items.add(target, items.removeAt(index))
dragOffset += (index - target) * itemHeightPx
if (target != currentIndex) {
items.add(target, items.removeAt(currentIndex))
dragOffset += (currentIndex - target) * itemHeightPx
draggingIndex = target
}
},
@@ -670,7 +673,14 @@ private fun DragOrderList(
}
)
}
)
) {
// 小圆点手柄(触控区 padding 20dp 居中 -> 8dp 圆点)
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.onSurfaceVariant, CircleShape)
)
}
}
}
}