feat(app): add secure routing and runtime resilience
Add explicit TUN and SOCKS5 connection modes, app routing controls, authenticated per-session local SOCKS5, Android network monitoring, persistent haptics, resilient session recovery, notification hardening and client-side Hivemind cleanup. Keep the hosted flutter_vless_android 1.1.5 runtime as the base and apply the Android compatibility/security patches at build time instead of restoring the unstable vendored runtime.
This commit is contained in:
1 parent
371db8da9f
commit
8ead3ff249
30 files changed
+3959
-484
No files matched your search
@@ -2,11 +2,11 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
import 'package:revoltvpn/logic/haptic_settings.dart';
|
||||
import 'package:revoltvpn/logic/vpn_connection.dart';
|
||||
import 'package:revoltvpn/screens/main_screen.dart';
|
||||
import 'package:revoltvpn/screens/settings/in_settings/rain.dart';
|
||||
import 'package:revoltvpn/screens/settings/in_settings/lightning.dart';
|
||||
import 'package:revoltvpn/screens/settings/in_settings/haptic.dart';
|
||||
|
||||
class IntroScreen extends StatefulWidget {
|
||||
const IntroScreen({super.key});
|
||||
@@ -45,10 +45,12 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
final elapsed = Stopwatch()..start();
|
||||
final vpn = context.read<VpnConnection>();
|
||||
|
||||
// The overlays read these in initState, so they must land before
|
||||
// MainScreen mounts.
|
||||
final settingsPrefs = Future.wait(
|
||||
[loadRainPref(), loadLightningPref(), loadHapticPref()]);
|
||||
// The overlays and haptic layer read these before MainScreen mounts.
|
||||
final settingsPrefs = Future.wait([
|
||||
loadRainPref(),
|
||||
loadLightningPref(),
|
||||
HapticSettings.initialize(),
|
||||
]);
|
||||
|
||||
try {
|
||||
await vpn.ready.timeout(_bootTimeout);
|
||||
@@ -79,7 +81,7 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
void _navigateIfReady() {
|
||||
if (!mounted || _navigated || !_bootComplete) return;
|
||||
if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.paused) {
|
||||
return; // resume will call back in
|
||||
return;
|
||||
}
|
||||
_navigated = true;
|
||||
|
||||
@@ -101,7 +103,6 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
body: Column(
|
||||
children: [
|
||||
const Spacer(flex: 7),
|
||||
// Image slightly below center
|
||||
Center(
|
||||
child: Image.asset(
|
||||
'assets/brand.png',
|
||||
@@ -116,7 +117,6 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
},
|
||||
),
|
||||
),
|
||||
// Spinner + text paired together below the image
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(
|
||||
width: 40,
|
||||
@@ -137,7 +137,6 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// Says what the spinner is actually waiting on.
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
child: Text(
|
||||
|
||||
Reference in new issue
Block a user