refactor(app): remove unsupported runtime and UI state
This commit is contained in:
1 parent
9ac236a981
commit
0ed7bf27b5
19 files changed
+173
-381
No files matched your search
@@ -18,23 +18,32 @@ abstract final class ConnectionSettings {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final storedMode = prefs.getString(_modeKey);
|
||||
|
||||
// Any unrecognized value (including the pre-V3 'auto') is TUN. 'proxy' is
|
||||
// the only persisted value that selects the SOCKS5 mode.
|
||||
// Only the explicit current proxy value restores SOCKS5. Unknown and
|
||||
// obsolete values, including the former 'auto'/'ass' labels, fail closed
|
||||
// to full-tunnel TUN instead of silently selecting a weaker route.
|
||||
_mode = storedMode == ConnectionMode.proxy.name
|
||||
? ConnectionMode.proxy
|
||||
: ConnectionMode.tun;
|
||||
|
||||
if (storedMode != _mode.name) {
|
||||
await prefs.setString(_modeKey, _mode.name);
|
||||
final migrated = await prefs.setString(_modeKey, _mode.name);
|
||||
if (!migrated) {
|
||||
throw StateError('Could not persist migrated connection mode.');
|
||||
}
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
static Future<void> setMode(ConnectionMode mode) async {
|
||||
static Future<bool> setMode(ConnectionMode mode) async {
|
||||
if (_initialized && _mode == mode) return true;
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final saved = await prefs.setString(_modeKey, mode.name);
|
||||
if (!saved) return false;
|
||||
|
||||
_mode = mode;
|
||||
_initialized = true;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_modeKey, mode.name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// Background-survival controls.
|
||||
///
|
||||
/// Android stops background services of apps that are not exempt from Doze and
|
||||
/// App Standby, and it tears down the whole process group when a task is swiped
|
||||
/// away. Those are OS behaviours, not app bugs; the battery-optimisation
|
||||
/// exemption is the one sanctioned way an app can ask for around them, and it
|
||||
/// still needs one user tap.
|
||||
/// Android background-survival controls that ReVolt can actually verify.
|
||||
abstract final class PowerSettings {
|
||||
PowerSettings._();
|
||||
|
||||
@@ -15,7 +9,6 @@ abstract final class PowerSettings {
|
||||
'com.revoltvpn.app/power',
|
||||
);
|
||||
|
||||
/// Whether the OS has exempted this app from Doze / App Standby.
|
||||
static Future<bool> isBatteryOptimisationDisabled() async {
|
||||
if (kIsWeb) return true;
|
||||
try {
|
||||
@@ -28,8 +21,6 @@ abstract final class PowerSettings {
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows the system exemption dialog. Returns false only when no system UI
|
||||
/// could be opened at all — a user declining still returns true.
|
||||
static Future<bool> requestDisableBatteryOptimisation() async {
|
||||
if (kIsWeb) return true;
|
||||
try {
|
||||
@@ -41,53 +32,4 @@ abstract final class PowerSettings {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the VPN runtime is genuinely alive.
|
||||
///
|
||||
/// The Xray service runs in a separate process, so nothing it stores in
|
||||
/// statics is visible to us. This asks the OS instead: is our service process
|
||||
/// running, and (for TUN) is there an active VPN transport?
|
||||
static Future<VpnRuntimeState> runtimeState() async {
|
||||
if (kIsWeb) return const VpnRuntimeState(processAlive: false, vpnTransport: false);
|
||||
try {
|
||||
final result = await _channel.invokeMapMethod<String, dynamic>(
|
||||
'isVpnRuntimeAlive',
|
||||
);
|
||||
return VpnRuntimeState(
|
||||
processAlive: result?['processAlive'] == true,
|
||||
vpnTransport: result?['vpnTransport'] == true,
|
||||
);
|
||||
} catch (_) {
|
||||
return const VpnRuntimeState(processAlive: false, vpnTransport: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes the absolute session-expiry timestamp (epoch ms) to the VPN
|
||||
/// service so it can tear the tunnel down even when the UI process is gone.
|
||||
static Future<void> setSessionExpiry(int expiresAtMs) async {
|
||||
if (kIsWeb) return;
|
||||
try {
|
||||
await _channel.invokeMethod<void>('setSessionExpiry', {
|
||||
'expiresAtMs': expiresAtMs,
|
||||
});
|
||||
} catch (_) {
|
||||
// Best-effort. The daemon also keeps its last persisted expiry.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class VpnRuntimeState {
|
||||
final bool processAlive;
|
||||
final bool vpnTransport;
|
||||
|
||||
const VpnRuntimeState({
|
||||
required this.processAlive,
|
||||
required this.vpnTransport,
|
||||
});
|
||||
|
||||
/// TUN needs both a live service and a real VPN interface. Proxy mode has no
|
||||
/// VPN interface at all, so the service process is the whole signal.
|
||||
bool aliveFor({required bool tunMode}) =>
|
||||
processAlive && (!tunMode || vpnTransport);
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
// ── lib/logic/server_list.dart ──────────────────────────────────────────────
|
||||
// Server data model and ChangeNotifier — shared by StatusBar (shows current
|
||||
// server name/flag) and SelectionScreen (lets user pick a server).
|
||||
//
|
||||
// Each server is defined by its tunnel IP/port. Reality credentials (public
|
||||
// key, shortId) come from /session/status per session; only the transport
|
||||
// parameters live in AppConfig.
|
||||
//
|
||||
// When multi-server ships:
|
||||
// - _all becomes a fetched list (from /api/servers or bundled config)
|
||||
// - SelectionScreen shows multiple rows
|
||||
// - select() triggers a disconnect/reconnect cycle if the tunnel is active
|
||||
|
||||
class ServerInfo {
|
||||
final String id;
|
||||
final String name;
|
||||
final String flagAsset;
|
||||
final String ip;
|
||||
final int port;
|
||||
|
||||
const ServerInfo({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.flagAsset,
|
||||
required this.ip,
|
||||
required this.port,
|
||||
});
|
||||
}
|
||||
|
||||
class ServerList extends ChangeNotifier {
|
||||
static const _all = [
|
||||
ServerInfo(
|
||||
id: 'finland',
|
||||
name: 'Helsinki, Finland',
|
||||
flagAsset: 'assets/finland_flag_256.png',
|
||||
ip: '204.168.246.88',
|
||||
port: 443,
|
||||
),
|
||||
];
|
||||
|
||||
int _selectedIndex = 0;
|
||||
|
||||
List<ServerInfo> get all => _all;
|
||||
int get selectedIndex => _selectedIndex;
|
||||
ServerInfo get selected => _all[_selectedIndex];
|
||||
|
||||
// Loads persisted selection from SharedPreferences.
|
||||
// Fire-and-forget — UI starts with default, updates when prefs load.
|
||||
Future<void> init() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final saved = prefs.getInt('selected_server_index') ?? 0;
|
||||
if (saved >= 0 && saved < _all.length && saved != _selectedIndex) {
|
||||
_selectedIndex = saved;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Switches to a different server. Persists the choice.
|
||||
Future<void> select(int index) async {
|
||||
if (index == _selectedIndex || index < 0 || index >= _all.length) return;
|
||||
_selectedIndex = index;
|
||||
notifyListeners();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setInt('selected_server_index', index);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user