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

Merged
Naveax merged 1 commits from pr/remove-unsupported-server-selector into main 2026-09-06 11:18:28 +03:00
4 changed files with 28 additions and 194 deletions

No files matched your search

+28 -57
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,66 +24,39 @@ 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: () { padding:
Navigator.of(context).push( const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
PageRouteBuilder( decoration: BoxDecoration(
transitionDuration: const Duration(milliseconds: 300), color: AppColors.bgCard,
pageBuilder: (_, __, ___) => const SelectionScreen(), borderRadius: BorderRadius.circular(16),
transitionsBuilder: (_, animation, __, child) { border: Border.all(color: AppColors.slate15),
return SlideTransition( ),
position: Tween<Offset>( child: Row(
begin: const Offset(1.0, 0.0), children: [
end: Offset.zero, Image.asset(
).animate( 'assets/finland_flag_256.png',
CurvedAnimation( width: 20,
parent: animation, height: 20,
curve: Curves.easeOut,
),
),
child: child,
);
},
), ),
); const SizedBox(width: 8),
}, const Expanded(
child: Container( child: Text(
padding: 'Helsinki, Finland',
const EdgeInsets.symmetric(horizontal: 20, vertical: 12), style: TextStyle(
decoration: BoxDecoration( color: AppColors.accent,
color: AppColors.bgCard, fontWeight: FontWeight.w600,
borderRadius: BorderRadius.circular(16), fontSize: 13,
border: Border.all(color: AppColors.slate15), letterSpacing: 0.5,
),
child: Row(
children: [
Image.asset(server.flagAsset, width: 20, height: 20),
const SizedBox(width: 8),
Expanded(
child: Text(
server.name,
style: const TextStyle(
color: AppColors.accent,
fontWeight: FontWeight.w600,
fontSize: 13,
letterSpacing: 0.5,
),
), ),
), ),
const Icon( ),
Icons.chevron_right, ],
color: AppColors.textDim,
size: 20,
),
],
),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
-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),
);
},
),
);
}
}