Skip to content

1.4.6

Choose a tag to compare

@Gitefy Gitefy released this 05 Sep 03:09
· 147 commits to main since this release

Summary / 概述

This PR prepares NekoBox 1.4.6 by resolving several critical lifecycle, concurrency, network resource, and UI defects, with a particular focus on decoupling drag-and-drop reordering in Router Groups to prevent cross-subscription order corruption, while retaining full drag-and-drop functionality for users.

本次提交为 NekoBox 1.4.6 准备版本,修复了多个关键的服务生命周期、并发控制、Socket 资源泄漏及 UI 缺陷;重点优化了路由分组(Router Group)下的拖拽排序机制,使路由分组内拖拽排序独立持久化,彻底解决了过去拖拽会打乱各节点在原本所属订阅中排序的问题,同时完整保留了路由分组的拖拽排序体验。


Key Changes / 主要变更

1. 🔀 Router Group Drag-and-Drop Order Decoupling (路由分组拖拽排序解耦)

  • Problem: Dragging nodes within a router group previously overwrote proxy_entities.userOrder, corrupting the original sequence of profiles in their respective source subscription groups.
  • Solution:
    • Added updateUserOrder query and @Transaction updateOrders batch update to RouterMember.Dao.
    • In ConfigurationAdapter.move(), intercepted inRouterGroupMode to only reorder the in-memory item IDs without touching ProxyEntity.userOrder.
    • In ConfigurationAdapter.commitMove(), persisted the reordered sequence into router_members.userOrder and notified sing-box service reload smoothly.
    • Seamlessly integrates with RouterReconciler.kt, ensuring user-defined order in router groups is safely preserved across subscription refreshes.

2. 🛡️ Subscription Concurrency Lock Protection (订阅更新并发互斥锁保护)

  • Problem: In GroupUpdater.executeUpdate(), duplicate update attempts or user cancellation of warning dialogs threw CancellationException via cancel(), causing caller scope failures and prematurely unlocking the running update mutex in catch blocks.
  • Solution: Replaced cancel() with return@coroutineScope false to prevent exception leakage and maintain strict mutex lifecycle.

3. 🌐 WebDAV Connection & Socket Leak Prevention (WebDAV OkHttp 连接防泄漏)

  • Problem: In WebDAVSettingsActivity, client.newCall().execute() calls for auth and directory creation were not closed, leaking OkHttp sockets and connection pool resources.
  • Solution: Wrapped both network calls in Kotlin's .use { response -> ... } blocks to ensure deterministic socket closing.

4. 🔄 ViewPager2 Memory Leak & UI Lifecycle Fixes (Fragment 视图生命周期与内存泄漏修复)

  • Problem: In ConfigurationFragment.GroupFragment, listeners were registered in onViewCreated() but only removed in onDestroy(). In ViewPager2, swiping pages out calls onDestroyView() while keeping the fragment instance, accumulating duplicate listeners and leaking views. Furthermore, routerGroup was not parcelled across screen rotations.
  • Solution:
    • Added onDestroyView() to unregister ProfileManager and GroupManager listeners, detach touch helpers, and clean up adapters.
    • Properly parcelled and restored routerGroup in onSaveInstanceState and onViewStateRestored.
    • Optimized reloadProfiles() in router group mode by replacing the N+1 getById() loop with a single batch getEntities(memberIds) query.

5. 🔒 libcore Core Access Mutex & Lifecycle Check (Go sing-box 核心线程安全加锁)

  • Problem: SelectOutbound and SelectOutboundFor in libcore/box.go lacked b.access.Lock() and b.state checks, risking data races or nil dereferences during core stop or reload.
  • Solution: Acquired b.access.Lock() and verified b.state == 1 before accessing selectors and outbounds, matching CurrentOutboundFor.

6. ⚠️ Router Group Deletion Confirmation Dialog (路由分组删除防误触)

  • Added MaterialAlertDialogBuilder confirmation dialog before executing router group deletion in RouterGroupSettingsActivity.

7. 🧹 Post-Import Invalidation Cleanup (备份恢复后悬空数据清理)

  • In BackupFragment.finishImport(), automatically invoked SagerDatabase.routerGroupDao.clearInvalidSelections() and GroupManager.cleanupDanglingRouterMembers() after restoring router groups to prevent dangling node IDs.

8. ⚡ Traffic Looper & Version Bump (流量轮询节流与版本升级)

  • Optimized TrafficLooper sampling intervals and background notifications.
  • Bumped version to 1.4.6 (versionCode: 49) in nb4a.properties.

Compatibility & Database Schema / 兼容性与数据库

  • Room Database Schema: Kept at Version 10 (SagerDatabase.kt). No migration required.
  • RuleEntity: RuleEntity.routerGroupId remains @IgnoredOnParcel to preserve legacy Android Parcel binary compatibility.
  • Native ABI: Verified full compatibility with libcore.aar and libhev-socks5-tunnel.so across arm64-v8a, armeabi-v7a, x86, and x86_64.

Verification & Testing / 验证与测试结果

  • ./gradlew.bat testOssDebugUnitTest --offline passed (all 35 tasks successful).
  • ./gradlew.bat compileOssDebugKotlin --offline passed (0 compilation errors).
  • :app:verifyLibcore and :app:verifyOssDebugLibcoreCallers passed.
  • Packaged full set of 1.4.6 debug APKs under app/build/outputs/apk/oss/debug/.