- Refactor subscription synchronization and testing from static object to a dedicated foreground service.
- Implement SubscriptionUpdateService with accurate lifecycle management using AtomicInteger (runningTasks).
- Enforce serial execution of subscription updates via Semaphore(1) to ensure data integrity and bandwidth control.
- Fix NetworkOnMainThreadException by switching service execution to Dispatchers.IO.
- Decouple update logic from Main UI components for better modularity.
- Prevent rapid rescheduling loops by updating 'lastUpdated' timestamp at the start of the task.
- Simplify messaging by supporting multiple subscription IDs in a single SubscriptionUpdateMessage.
Refactored MainActivity and its Compose UI components to use a single
onAction: (MainAction) -> Unit callback. This significantly simplifies
component signatures and centralizes interaction logic.
- Updated MainContract.kt to include all UI-triggered actions.
- Modified MainScreen and sub-components (TopBar, BottomBar, Drawer, etc.)
to use the unified onAction dispatcher.
- Implemented a centralized action handler in MainActivity to dispatch
between ViewModel and Activity-specific tasks.
- Removed redundant ImportConfigViaSub action.
- Moved QR code generation state into MainUiState for MVI consistency.
This change reduces parameter drilling and improves maintainability of
the main interface.
Improve settings UX consistency across Compose screens: disabled setting text now uses proper muted alpha for title/description, domain strategy and geo source pickers now use shared `SettingsListItem` instead of custom click/dialog state, routing rule row UI was extracted into a reusable composable, and several settings toggles were un-gated so they can be changed outside VPN-only conditions.
Move manual subscription updates to WorkManager-based background jobs and simplify scheduler logic by handling auto-update checks in `scheduleOne`. Add post-update server testing support with optional invalid-node cleanup and sorting, plus MMKV/AngConfig helpers to remove multiple servers and reorder subscription servers by test delay. Update the subscriptions UI flow and zh-TW strings to reflect background execution and new auto-test options.
- Implement BaseViewModel to centralize loading state and UI event handling.
- Migrate all ViewModels (Main, Backup, Logcat, etc.) to inherit from BaseViewModel.
- Convert MainViewModel from AndroidViewModel to standard ViewModel using global app context.
- Standardize UI events using ViewModelEvent/BaseViewModelEvent sealed interfaces.
- Simplify loading logic with launchLoading helper and direct toast notifications.
- Cleanup redundant loading/toast boilerplate code across the application.
- Update LogcatActivity to observe the unified isLoading state.
- Create BaseViewModel to encapsulate common UI state (isLoading) and logic (toasts, finishing activity).
- Implement ViewModelEvent and BaseViewModelEvent for standardized UI communication via SideEffects.
- Move core business logic (I/O, Zip, WebDAV) from BackupActivity to BackupViewModel.
- Standardize code naming conventions and update documentation to English.
- Improve Activity purity by delegating state management and background tasks to the ViewModel.
Update compileSdk and targetSdk to 37. Adjust AndroidManifest: remove legacy storage read permissions, add tools:ignore for FOREGROUND_SERVICE policy and keep FOREGROUND_SERVICE_SPECIAL_USE with minSdk 34. Wrap ContextCompat.startForegroundService with SecurityException handling and special-case ForegroundServiceStartNotAllowedException (logged and rethrown as IllegalStateException) to surface permission/OS restrictions. Remove the READ_STORAGE PermissionType and related runtime permission request in HelperBaseActivity (file chooser now launches directly). These changes align permissions and service startup behavior with newer Android SDK requirements.
Rework CoreConfigContextBuilder and CoreConfigManager to centralize and simplify outbound resolution and runtime config assembly. Key changes: handle CUSTOM profiles early, introduce ResolvedOutbound and resolvedOutbounds list, resolve routing-target outbounds separately, and unify normal/group/chain build flows into buildUnifiedConfig. Routing, DNS, inbounds, outbounds and balancer logic were modularized (configureInbounds/configureRouting/configureDns/configureFakeDns/configureLocalDns/etc.), balancer strategies and observability are consolidated, and domain pre-resolution/hosts handling preserved. Also added new balancer tag naming (TAG_BALANCER_PRE) and small API/utility adjustments across CoreOutboundBuilder, DTOs and enums to support the new flow. These changes improve clarity of the build pipeline, make custom/routing outbounds handling explicit, and prepare for richer policy-group balancing behavior.
Add OutboundTrafficStat DTO and a CoreServiceManager.queryAllOutboundTrafficStats() method to fetch/reset all outbound counters in one core call and parse Go-side payload. Remove ProfileItem.getAllOutboundTags() and simplify NotificationManager API (startSpeedNotification()/stopSpeedNotification()) to use aggregated stats via the new core query. Replace per-tag polling with a single aggregated update loop (updateSpeedNotificationOnce) to reduce IPC and CPU usage, and update CoreServiceManager call sites accordingly.