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
@@ -2,7 +2,6 @@ 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';
|
||||
@@ -45,11 +44,10 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
final elapsed = Stopwatch()..start();
|
||||
final vpn = context.read<VpnConnection>();
|
||||
|
||||
// The overlays and haptic layer read these before MainScreen mounts.
|
||||
// Haptics is initialized before runApp. Only visual preferences remain.
|
||||
final settingsPrefs = Future.wait([
|
||||
loadRainPref(),
|
||||
loadLightningPref(),
|
||||
HapticSettings.initialize(),
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -80,11 +78,10 @@ class _IntroScreenState extends State<IntroScreen> with WidgetsBindingObserver {
|
||||
|
||||
void _navigateIfReady() {
|
||||
if (!mounted || _navigated || !_bootComplete) return;
|
||||
if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.paused) {
|
||||
return;
|
||||
}
|
||||
_navigated = true;
|
||||
final lifecycle = WidgetsBinding.instance.lifecycleState;
|
||||
if (lifecycle != null && lifecycle != AppLifecycleState.resumed) return;
|
||||
|
||||
_navigated = true;
|
||||
Navigator.of(context).pushReplacement(
|
||||
PageRouteBuilder(
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
import 'package:revoltvpn/logic/server_list.dart';
|
||||
|
||||
// ── lib/screens/server_selector/selection_screen.dart ──────────────────────
|
||||
// Server picker — reads the server list from the ServerList provider.
|
||||
// Each row shows a flag + city name. Tapping a row persists the choice
|
||||
// and pops back. No latency measurement — the app runs inside a Reality
|
||||
// tunnel and must not emit separate probe traffic.
|
||||
|
||||
class SelectionScreen extends StatelessWidget {
|
||||
const SelectionScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serverList = context.watch<ServerList>();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgDeep,
|
||||
appBar: AppBar(
|
||||
backgroundColor: AppColors.bgSurface,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: AppColors.textWhite),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: const Text(
|
||||
'Select Server',
|
||||
style: TextStyle(
|
||||
color: AppColors.textWhite,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: serverList.all.length,
|
||||
itemBuilder: (context, index) {
|
||||
final server = serverList.all[index];
|
||||
final isSelected = index == serverList.selectedIndex;
|
||||
|
||||
return ListTile(
|
||||
leading: Image.asset(server.flagAsset, width: 28, height: 28),
|
||||
title: Text(server.name,
|
||||
style: TextStyle(
|
||||
color: isSelected ? AppColors.accent : AppColors.textWhite,
|
||||
fontWeight: FontWeight.w600,
|
||||
)),
|
||||
trailing: isSelected
|
||||
? const Icon(Icons.check, color: AppColors.accent)
|
||||
: null,
|
||||
onTap: () {
|
||||
serverList.select(index);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
import 'package:revoltvpn/logic/power_settings.dart';
|
||||
|
||||
/// Keeping the tunnel alive is an OS concern, not an app one.
|
||||
///
|
||||
/// Android stops background services of apps that are not exempt from Doze, and
|
||||
/// removes the whole process group when its task is swiped away. There are
|
||||
/// exactly two sanctioned ways around that, both requiring one user tap, and
|
||||
/// neither can be enabled programmatically. This tile surfaces both.
|
||||
/// Android may restrict background work when battery optimisation is active.
|
||||
/// Surface the OS setting we can actually detect and request; do not promise
|
||||
/// reboot/Always-on restoration that the per-session runtime cannot guarantee.
|
||||
class BackgroundReliabilityTile extends StatefulWidget {
|
||||
const BackgroundReliabilityTile({super.key});
|
||||
|
||||
@@ -35,8 +32,6 @@ class _BackgroundReliabilityTileState extends State<BackgroundReliabilityTile>
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
// The exemption is granted in a system dialog, so the only reliable moment
|
||||
// to re-read it is when we come back to the foreground.
|
||||
if (state == AppLifecycleState.resumed) _refresh();
|
||||
}
|
||||
|
||||
@@ -68,8 +63,8 @@ class _BackgroundReliabilityTileState extends State<BackgroundReliabilityTile>
|
||||
style: TextStyle(color: AppColors.textWhite, fontSize: 15),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Android stops background apps to save power. Disabling battery '
|
||||
'optimisation is what keeps the VPN running when the app is closed.',
|
||||
'Android may restrict background work to save power. ReVolt only '
|
||||
'shows the system control it can verify.',
|
||||
style: TextStyle(color: AppColors.textDim, fontSize: 12),
|
||||
),
|
||||
),
|
||||
@@ -83,8 +78,8 @@ class _BackgroundReliabilityTileState extends State<BackgroundReliabilityTile>
|
||||
? 'Battery optimisation: checking…'
|
||||
: exempt
|
||||
? 'Battery optimisation: disabled for Revolt VPN ✓'
|
||||
: 'Battery optimisation: still active — the system may '
|
||||
'stop the VPN in the background.',
|
||||
: 'Battery optimisation: active — Android may stop '
|
||||
'background VPN work.',
|
||||
style: TextStyle(
|
||||
color: exempt == true ? AppColors.accent : AppColors.textMuted,
|
||||
fontSize: 12,
|
||||
|
||||
@@ -51,8 +51,14 @@ class _ConnectionModeTileState extends State<ConnectionModeTile> {
|
||||
return;
|
||||
}
|
||||
|
||||
await ConnectionSettings.setMode(next);
|
||||
final saved = await ConnectionSettings.setMode(next);
|
||||
if (!mounted) return;
|
||||
if (!saved) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Could not save connection mode.')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_mode = next;
|
||||
@@ -61,10 +67,6 @@ class _ConnectionModeTileState extends State<ConnectionModeTile> {
|
||||
widget.onChanged?.call(next);
|
||||
}
|
||||
|
||||
/// Recovers from an orphaned proxy: tear the runtime down and start a fresh
|
||||
/// session so a readable set of credentials exists again. No rewarded ad —
|
||||
/// the user is repairing a connection they already paid for, not opening a
|
||||
/// new one.
|
||||
Future<void> _reconnect() async {
|
||||
if (_reconnecting) return;
|
||||
final vpn = context.read<VpnConnection>();
|
||||
@@ -168,11 +170,6 @@ class _ConnectionModeTileState extends State<ConnectionModeTile> {
|
||||
builder: (context, vpn, _) {
|
||||
final session = vpn.activeSocksSession;
|
||||
if (session == null) {
|
||||
// The proxy can be running while this session is unknown:
|
||||
// Android killed the app process, the foreground service kept
|
||||
// the listener alive, and its credentials existed only in the
|
||||
// memory that died with it. Saying "Connect" there would be a
|
||||
// lie — the user is already connected.
|
||||
final orphaned = vpn.status == VpnStatus.connected &&
|
||||
vpn.adoptedRunningRuntime;
|
||||
if (orphaned) {
|
||||
|
||||
@@ -2,9 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
|
||||
// ── lib/screens/settings/in_settings/lightning.dart ─────────────────────────
|
||||
// Toggle for the lightning strike overlay on the main screen.
|
||||
|
||||
final ValueNotifier<bool> lightningEnabled = ValueNotifier(true);
|
||||
|
||||
Future<void> loadLightningPref() async {
|
||||
@@ -35,7 +32,9 @@ class _LightningToggleTileState extends State<LightningToggleTile> {
|
||||
|
||||
Future<void> _toggle(bool value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('lightning_effect_enabled', value);
|
||||
final saved = await prefs.setBool('lightning_effect_enabled', value);
|
||||
if (!saved || !mounted) return;
|
||||
|
||||
lightningEnabled.value = value;
|
||||
setState(() => _on = value);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
|
||||
// ── lib/screens/settings/in_settings/rain.dart ──────────────────────────────
|
||||
// Toggle for the animated rain overlay on the main screen.
|
||||
|
||||
final ValueNotifier<bool> rainEnabled = ValueNotifier(true);
|
||||
|
||||
Future<void> loadRainPref() async {
|
||||
@@ -35,7 +32,9 @@ class _RainToggleTileState extends State<RainToggleTile> {
|
||||
|
||||
Future<void> _toggle(bool value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('rain_effect_enabled', value);
|
||||
final saved = await prefs.setBool('rain_effect_enabled', value);
|
||||
if (!saved || !mounted) return;
|
||||
|
||||
rainEnabled.value = value;
|
||||
setState(() => _on = value);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user