refactor(app): debloat 3.3.1 and fix startup restoration

Maintainer changes on top of PR #2 (Naveax). Reduces the release to two
deliberate connection modes and resolves the issues found in review:

- Lock-screen privacy: move VISIBILITY_PRIVATE and a generic publicVersion
  into MainActivity.updateVpnNotification. The PR's fix lived in an
  unreferenced class and never reached the live notification.
- Haptics: restore the default to off, and reduce HapticSettings to a
  single success() on connect/disconnect via the native channel.
- SOCKS5: make it a real proxyOnly local-proxy mode rather than a TUN
  connection under a different label. TUN stays the default.
- Health probe: restore the idle-only guard so /health is no longer polled
  every 30s while connected.
- Recovery: add a _connectionEpoch counter so connect() aborts an
  in-flight Extreme recovery.
- Startup restoration: rebuild the recovery snapshot from the still-active
  session after an app-process restart (TUN), and surface an honest
  orphaned state with a Reconnect action in proxy mode.

Drops per-app routing entirely. It only ever functioned in TUN --
addDisallowedApplication lives inside the VPN-interface setup that
proxyOnly skips -- and its allowlist half had no Dart caller.

Also removes flutter_local_notifications, the global tap-haptic surface,
and unused runtime telemetry.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
esefxdzandClaude Opus 5 committed 2026-08-31 23:31:51 +03:00
1 parent a71161e7e5
commit 6fcde9dd7b
18 files changed
+271 -1027

No files matched your search

+9 -21
View File
@@ -4,8 +4,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
enum HapticKind { tap, selection, success }
abstract final class HapticSettings {
HapticSettings._();
@@ -13,7 +11,7 @@ abstract final class HapticSettings {
static const MethodChannel _channel =
MethodChannel('com.revoltvpn.app/haptics');
static bool _enabled = true;
static bool _enabled = false;
static bool _initialized = false;
static bool get enabled => _enabled;
@@ -23,10 +21,10 @@ abstract final class HapticSettings {
try {
final prefs = await SharedPreferences.getInstance();
_enabled = prefs.getBool(_prefKey) ?? true;
_enabled = prefs.getBool(_prefKey) ?? false;
} catch (e) {
debugPrint('[Haptics] Failed to load preference: $e');
_enabled = true;
_enabled = false;
} finally {
_initialized = true;
}
@@ -48,11 +46,11 @@ abstract final class HapticSettings {
}
}
static void tap() => unawaited(_impact(HapticKind.tap));
static void selection() => unawaited(_impact(HapticKind.selection));
static void success() => unawaited(_impact(HapticKind.success));
/// Confirmation haptic for a successful connect/disconnect. Best-effort: a
/// vibration failure must never block or fail the VPN action.
static void success() => unawaited(_impact());
static Future<void> _impact(HapticKind kind) async {
static Future<void> _impact() async {
if (!_initialized) await initialize();
if (!_enabled || kIsWeb) return;
@@ -60,7 +58,7 @@ abstract final class HapticSettings {
try {
final handled = await _channel.invokeMethod<bool>(
'impact',
<String, Object>{'kind': kind.name},
<String, Object>{'kind': 'success'},
) ??
false;
if (handled) return;
@@ -69,16 +67,6 @@ abstract final class HapticSettings {
}
}
switch (kind) {
case HapticKind.tap:
await HapticFeedback.lightImpact();
break;
case HapticKind.selection:
await HapticFeedback.selectionClick();
break;
case HapticKind.success:
await HapticFeedback.mediumImpact();
break;
}
await HapticFeedback.mediumImpact();
}
}