- 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.
* add composeui dependencies and component
* remove multidex
* BaseComponentActivity and HelperBaseComponentActivity
* migrate AppPicker/PerAppProxy Activity and use Snackbar
* migrate AboutActivity to composeui
* migrate BackupActivity to composeui
* migrate CheckUpdateActivity to composeui
* migrate Logcat to composeui
* migrate Scanner to composeui and camerax
* migrate sc start/stop/switch to compose
* migrate TaskerActivity to composeui
* migrate UrlSchemeActivity to composeui
* migrate UserAsset to composeui
* migrate ServerActivity to composeui
* migrate ServerCustomConfigActivity to composeui
* migrate ServerGroupActivity to composeui
* migrate ServerProxyChainActivity to composeui
* migrate SettingsActivity to composeui
* migrate SubEdit/SubSetting Activity to composeui
* migrate routingEdit/routingSetting Activity to composeui
* migrate MainActivity to composeui
* clode clean and chore change
* Fix
* add scrollbar
* fix imePadding
* fix FormDropdownField scrollbar and ime conflict
* update servercostomconfigactivity with linenum and scrollbar
* fix AppPickerActivity filter wrong toogle
* fix App theme xml
* fix scrollbar not work in SettingsActivity
* final inset
* fix servercustomconfigactivity when open not begin line
* try optimize mainactivity performance
* use launch intent and fix not refresh when second edit use equals
* fix a ghost error
* update string
* update miss string
* optimize mainactivity and mainviewmodel
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
- Fixed completely inaccurate and literal translations
- Added missing string translations for newer features
- Improved technical terminology to accurately reflect standard VPN and networking concepts in Persian
- Rewrote the overall text for better readability and a more natural user experience.
* feat: add a root, system-wide run mode without VpnService
Adds an optional Root mode for rooted devices that routes the whole device's
traffic through the existing in-process core without Android's VpnService, plus
an opt-in LAN/tethering sharing feature. Non-root devices are unaffected and keep
VPN / Proxy-only (VPN stays the default).
- ERunMode (VPN, PROXY_ONLY, TUN2SOCKS) persisted in the existing PREF_MODE;
RootManager gates root modes (greyed-out for non-root, service refuses to start).
- CoreRootService + core/root/RootProxyManager run hev-socks5-tunnel as a
standalone root process into the core's SOCKS inbound, steered by an iptables
mangle MARK chain + a dedicated route table. Full TCP + UDP. hev-socks5-tunnel
is the same engine already bundled for the VPN hev path, so no new third-party
dependency is added.
- Capture parity with VpnService incl. per-app proxy/bypass; DNS funneled into the
core (netd-aware, no uid filter) so names resolve through the configured
resolver with no LAN-resolver leak.
- IPv6 parity: routed into the tun when enabled, otherwise native v6 is blackholed
for the captured apps (REJECT) so they fall back to v4-through-proxy, like a
v4-only VpnService.
- MTU taken from the existing VPN MTU setting; hev tun multi-queue + SOCKS
tcp-fastopen enabled.
- CI fetches the hev-socks5-tunnel binary per-ABI from heiher/hev-socks5-tunnel
releases (the same upstream the VPN hev path uses).
* build: compile libhevsockstun.so from source instead of downloading
Build the standalone hev-socks5-tunnel binary used by Root mode from the
pinned hev-socks5-tunnel submodule in compile-hevtun.sh, alongside the
existing JNI shared library, and drop the prebuilt release download from
the build workflow.
Both hev artifacts now come from the same in-tree source, so the binary
is fully auditable and version-locked to the submodule rather than a
fetched release asset. The executable is built without -DENABLE_LIBRARY
(so hev-main.c's main() is included) via BUILD_EXECUTABLE, reusing the
NDK toolchain already used for the JNI library.
* refactor(root): address review feedback
- LAN-sharing guard now checks the cheap, usually-false PREF_ROOT_LAN_SHARING
preference before RootManager.cachedRoot(), so the common path short-circuits
without touching root state.
- Move RootManager into the core.root package next to RootProxyManager and
RootShell (CoreRootService stays under service/).
- Probe su only when the user opts into a root feature — selecting a root mode
or enabling LAN sharing — instead of automatically on every Settings open.
If root is denied the selection is reverted with a toast. This avoids an
unsolicited root-grant prompt for the common non-root case; root mode for a
persisted selection is still re-verified when the service starts.
* refactor(root): use coroutines instead of Thread for su probing
Replace raw Thread usage in the root path with kotlinx coroutines, as
requested in review. RootManager.refreshAsync (a callback + daemon Thread)
becomes a suspending refresh() that runs the blocking su probe on
Dispatchers.IO and returns the result.
Callers updated accordingly:
- SettingsActivity probes on demand via lifecycleScope.launch and updates
the UI directly on resume (no manual runOnUiThread).
- CoreVpnService starts the LAN-sharing client over CoroutineScope(IO)
instead of a daemon Thread.
* fix(root): don't capture all apps when per-app proxy resolves no uids
In allow (proxy-only) mode the mangle/v6 builders fell through to the
catch-all "mark/reject everything" branch whenever selectedUids was empty.
That is a fail-open: if the selected packages momentarily fail to resolve to
uids (e.g. at early boot, before PackageManager is ready), every unselected
app gets tunneled instead of none — a privacy leak and the cause of per-app
"proxying everything" after a reboot.
Gate the catch-all on the mode itself (all-apps or bypass) rather than on
"selected list happened to be non-empty". In allow mode mark only the
resolved uids; if none resolved, mark nothing (fail closed). Mirror the same
fix in the IPv6 blackhole chain.
* fix(root): wait for async rule setup before teardown on stop
CoreRootService/CoreVpnService post the foreground notification as soon as the
core starts but install the root routing rules in a launched coroutine, which
can take seconds (the setup script waits for the tun device to appear). If the
user stops the service during that window, onDestroy/stopAllService ran the
synchronous teardown first and the still-running setup then re-installed the
rules and tun afterwards — leaving orphan routing rules and a tun forwarding
into a now-dead core, which blackholes all traffic until the next start/stop
cycle clears it (the "disconnect from the notification kills the internet,
reconnect+disconnect to fix it" bug).
Track the setup job and cancelAndJoin it before tearing down so teardown always
runs last and removes everything the setup installed.
* Adjust root package and add RootLanSharing object
* Remove ERunMode , add PREF_ROOT_MODE_ENABLE
* fix(root): handle tethered clients' IPv6 in LAN sharing to stop leaks
LAN/tethering sharing only set up IPv4 forwarding for clients, so a
hotspot/USB-tethered client with a native (RA-assigned) global IPv6
egressed the upstream interface directly, bypassing the proxy — an
IPv6 leak.
buildLanShareSetup now handles forwarded clients' v6:
- IPv6 enabled: route it through the tun. A mangle PREROUTING chain
marks non-LOCAL-sourced (forwarded) v6 into the tun route table,
keeps loopback/link-local/ULA/multicast direct, and hijacks client
DNS; FORWARD accepts traffic to/from the tun. A trailing REJECT
fails closed so anything not marked into the tun (e.g. addrtype
match unavailable) is dropped instead of leaked.
- IPv6 disabled: REJECT all forwarded v6 (the device's own v6 is
already blackholed in OUTPUT).
Teardown drops the two new ip6tables chains; the v6 route/rule into
the tun table were already cleaned.
Ported from vincentng295/Magic_V2Ray cae4f7f.
* Update build.gradle.kts
* Adjust settings
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>