refactor(app): remove unsupported server selector state (#6)

Remove UI and provider state that does not control the authoritative tunnel destination while preserving the existing connection-health status behavior.
This commit was merged in pull request #6.
This commit is contained in:
Naveax authored and GitHub committed 2026-09-06 11:18:28 +03:00
1 parent 6da601b565
commit ecdf6e549f
4 files changed
+12 -178

No files matched your search

+12 -41
View File
@@ -1,11 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:revoltvpn/logic/app_colors.dart';
import 'package:revoltvpn/logic/vpn_connection.dart';
import 'package:revoltvpn/logic/session_timer.dart';
import 'package:revoltvpn/logic/server_list.dart';
import 'package:revoltvpn/components/online_dot.dart'; import 'package:revoltvpn/components/online_dot.dart';
import 'package:revoltvpn/screens/server_selector/selection_screen.dart'; import 'package:revoltvpn/logic/app_colors.dart';
import 'package:revoltvpn/logic/session_timer.dart';
import 'package:revoltvpn/logic/vpn_connection.dart';
class StatusBar extends StatelessWidget { class StatusBar extends StatelessWidget {
const StatusBar({super.key}); const StatusBar({super.key});
@@ -26,37 +24,12 @@ class StatusBar extends StatelessWidget {
? 'Connecting…' ? 'Connecting…'
: (vpn.serverReachable ? 'Ready' : 'Offline')); : (vpn.serverReachable ? 'Ready' : 'Offline'));
final server = context.watch<ServerList>().selected;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24), padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
GestureDetector( Container(
onTap: () {
Navigator.of(context).push(
PageRouteBuilder(
transitionDuration: const Duration(milliseconds: 300),
pageBuilder: (_, __, ___) => const SelectionScreen(),
transitionsBuilder: (_, animation, __, child) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
),
child: child,
);
},
),
);
},
child: Container(
padding: padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 12), const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -66,12 +39,16 @@ class StatusBar extends StatelessWidget {
), ),
child: Row( child: Row(
children: [ children: [
Image.asset(server.flagAsset, width: 20, height: 20), Image.asset(
'assets/finland_flag_256.png',
width: 20,
height: 20,
),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( const Expanded(
child: Text( child: Text(
server.name, 'Helsinki, Finland',
style: const TextStyle( style: TextStyle(
color: AppColors.accent, color: AppColors.accent,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 13, fontSize: 13,
@@ -79,15 +56,9 @@ class StatusBar extends StatelessWidget {
), ),
), ),
), ),
const Icon(
Icons.chevron_right,
color: AppColors.textDim,
size: 20,
),
], ],
), ),
), ),
),
const SizedBox(height: 8), const SizedBox(height: 8),
Container( Container(
padding: padding:
-69
View File
@@ -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);
}
}
-5
View File
@@ -7,7 +7,6 @@ import 'package:revoltvpn/logic/ad_manager.dart';
import 'package:revoltvpn/logic/app_colors.dart'; import 'package:revoltvpn/logic/app_colors.dart';
import 'package:revoltvpn/logic/connection_settings.dart'; import 'package:revoltvpn/logic/connection_settings.dart';
import 'package:revoltvpn/logic/haptic_settings.dart'; import 'package:revoltvpn/logic/haptic_settings.dart';
import 'package:revoltvpn/logic/server_list.dart';
import 'package:revoltvpn/logic/session_timer.dart'; import 'package:revoltvpn/logic/session_timer.dart';
import 'package:revoltvpn/logic/vpn_connection.dart'; import 'package:revoltvpn/logic/vpn_connection.dart';
import 'package:revoltvpn/screens/intro.dart'; import 'package:revoltvpn/screens/intro.dart';
@@ -56,10 +55,6 @@ class ReVoltApp extends StatelessWidget {
prev ?? SessionTimer(vpnConnection: vpn), prev ?? SessionTimer(vpnConnection: vpn),
), ),
ChangeNotifierProvider(create: (_) => AdManager()), ChangeNotifierProvider(create: (_) => AdManager()),
ChangeNotifierProvider(
create: (_) => ServerList()..init(),
lazy: false,
),
], ],
child: MaterialApp( child: MaterialApp(
title: 'ReVolt VPN', title: 'ReVolt VPN',
@@ -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),
);
},
),
);
}
}