From cf93ca9f7120e2586aa5a5434b3d5840780d7893 Mon Sep 17 00:00:00 2001 From: QIU Date: Fri, 14 Aug 2026 00:43:23 +0000 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E4=BF=AE=E5=A4=8D=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E7=9A=84=E4=B8=89=E4=B8=AA=E4=B8=A5=E9=87=8D?= =?UTF-8?q?=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug #1: moveToMain 误驱逐页面 - 根因:每次调用 moveToMain 都执行驱逐逻辑,即使页面本来就在主菜单 - 场景:拖拽主菜单内部顺序 → SettingsViewModel 遍历新顺序逐个调 moveToMain → 每次都判断 main.size > 5 → 误驱逐最后一个页面 - 修复:只在真正从 More 移到主菜单时才驱逐(加 wasInMore 标志位) Bug #2: onReorder 传 resolve 输出污染状态 - 根因:SettingsScreen 拖拽回调传的是 resolve 输出(mainItems/subItems) 而不是持久化输入(screenOrder/subMenuOrder) - 场景:拖拽主菜单 → onReorder 传 [Radar, ..., Settings](完整列表) → Settings 被显式存入 screenOrder → 下次 resolve 当作用户手动放置 → 参与驱逐逻辑 - 修复: 1. 拖拽主菜单时过滤掉 Settings(锁定页面用默认位置,不存持久化) 2. 另一个菜单用输入的 screenOrder/subMenuOrder,不用 resolve 输出 Bug #3: onReorder More 菜单传错参数 - 根因:拖拽 More 菜单时传的是 mainItems(resolve 输出),不是 screenOrder - 修复:改用输入的 screenOrder 影响:修复前,拖拽主菜单会丢页面,移页面到主菜单可能导致 Settings 消失 --- .../look4sat/core/domain/navigation/MenuLayout.kt | 14 +++++++++----- .../look4sat/feature/settings/SettingsScreen.kt | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/navigation/MenuLayout.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/navigation/MenuLayout.kt index 8b35207e..b49616e9 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/navigation/MenuLayout.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/navigation/MenuLayout.kt @@ -99,16 +99,20 @@ object MenuLayout { val current = resolve(allScreenIds, screenOrder, subMenuOrder, emptyList()) val main = current.mainIds.toMutableList() val more = current.moreIds.toMutableList() + val wasInMore = screenId in more more.remove(screenId) if (screenId !in main) { val at = main.indexOf(SETTINGS_ID).let { if (it == -1) main.size else it } main.add(at, screenId) } - val movable = main.filter { it != SETTINGS_ID && it != screenId } - if (main.size > MAIN_SLOTS && movable.isNotEmpty()) { - val evicted = movable.last() - main.remove(evicted) - more.add(0, evicted) + // Only evict when we actually added a new page from More; internal reordering must not evict. + if (wasInMore) { + val movable = main.filter { it != SETTINGS_ID && it != screenId } + if (main.size > MAIN_SLOTS && movable.isNotEmpty()) { + val evicted = movable.last() + main.remove(evicted) + more.add(0, evicted) + } } return Assignment(screenOrder = main, subMenuOrder = more) } diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt index 45017dbd..7a4bae96 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt @@ -863,7 +863,11 @@ private fun UiSettingsCard( ) onUpdateMenu(moved.screenOrder, moved.subMenuOrder) }, - onReorder = { main -> onUpdateMenu(main, subItems) } + onReorder = { main -> + // Settings is locked last; exclude it so resolve continues to use its default position + val userOrder = main.filter { it != "Settings" } + onUpdateMenu(userOrder, subMenuOrder) + } ) // More-menu area (pages behind "More") Text( @@ -883,7 +887,7 @@ private fun UiSettingsCard( ) onUpdateMenu(moved.screenOrder, moved.subMenuOrder) }, - onReorder = { sub -> onUpdateMenu(mainItems, sub) } + onReorder = { sub -> onUpdateMenu(screenOrder, sub) } ) TextButton(onClick = onResetOrder) { Text(text = stringResource(id = R.string.prefs_ui_order_reset))