diff --git a/lib/backend/api.dart b/lib/backend/api.dart index 1eeb9dd..aedf00d 100644 --- a/lib/backend/api.dart +++ b/lib/backend/api.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:typed_data'; import '../core/config/config.dart'; +import '../core/config/countries.dart'; import '../core/protocol/opcode_map.dart'; import '../core/protocol/packet.dart'; import '../core/transport/connection.dart'; @@ -33,6 +34,11 @@ class Api { Map? get userAgent => _userAgent; + List? _registrationCountries; + + List get registrationCountries => + _registrationCountries ?? allCountries; + Stream get stateStream => _stateController.stream; SessionState get state => _sessionState; @@ -76,6 +82,7 @@ class Api { try { final response = await sendHandshake(); if (response.isOk) { + _registrationCountries = _parseRegistrationCountries(response.payload); _setSessionState(SessionState.online); _startPinging(); logger.i('Сессия онлайн, хэндшейк ок'); @@ -230,6 +237,28 @@ class Api { }); } + static List? _parseRegistrationCountries(dynamic payload) { + if (payload is! Map) return null; + final raw = payload['reg-country-code']; + if (raw is! List || raw.isEmpty) return null; + final codes = []; + for (final e in raw) { + if (e is String && e.isNotEmpty) codes.add(e.toUpperCase()); + } + if (codes.isEmpty) return null; + var list = countriesInServerOrder(codes); + if (list.isEmpty) return null; + + final loc = payload['location']; + if (loc is String && loc.length == 2) { + final home = countriesByCode[loc.toUpperCase()]; + if (home != null && !list.any((c) => c.code == home.code)) { + list = [home, ...list]; + } + } + return list; + } + void _scheduleReconnect() { if (_reconnectAttempts >= ServerConfig.maxReconnectAttempts) { logger.e('Лимит попыток реконнекта'); diff --git a/lib/core/config/countries.dart b/lib/core/config/countries.dart index d19d055..e87262e 100644 --- a/lib/core/config/countries.dart +++ b/lib/core/config/countries.dart @@ -33,6 +33,15 @@ final Map countriesByCode = { for (final country in allCountries) country.code: country, }; +List countriesInServerOrder(Iterable codes) { + final out = []; + for (final raw in codes) { + final c = countriesByCode[raw.toUpperCase()]; + if (c != null) out.add(c); + } + return out; +} + /// Пример использования: /// ```dart /// final country = exampleCountryLookup('RU'); diff --git a/lib/frontend/screens/auth/login_screen.dart b/lib/frontend/screens/auth/login_screen.dart index 6da104c..579f250 100644 --- a/lib/frontend/screens/auth/login_screen.dart +++ b/lib/frontend/screens/auth/login_screen.dart @@ -33,9 +33,19 @@ class _LoginScreenState extends State { void initState() { super.initState(); _selectedCountry = countriesByCode['RU'] ?? allCountries.first; + _clampCountryToAllowed(); _checkTOS(); } + void _clampCountryToAllowed() { + final allowed = api.registrationCountries; + if (allowed.any((c) => c.code == _selectedCountry.code)) return; + _selectedCountry = allowed.firstWhere( + (c) => c.code == 'RU', + orElse: () => allowed.first, + ); + } + @override void dispose() { _phoneErrorTimer?.cancel(); @@ -66,8 +76,10 @@ class _LoginScreenState extends State { final result = await Navigator.push( context, MaterialPageRoute( - builder: (context) => - SelectCountryScreen(selectedCountry: _selectedCountry), + builder: (context) => SelectCountryScreen( + selectedCountry: _selectedCountry, + countries: api.registrationCountries, + ), ), ); if (result != null) { diff --git a/lib/frontend/screens/auth/select_country_screen.dart b/lib/frontend/screens/auth/select_country_screen.dart index 3c5f5de..bf4bd03 100644 --- a/lib/frontend/screens/auth/select_country_screen.dart +++ b/lib/frontend/screens/auth/select_country_screen.dart @@ -6,8 +6,13 @@ import 'package:komet/l10n/app_localizations.dart'; class SelectCountryScreen extends StatefulWidget { final CountryName selectedCountry; + final List countries; - const SelectCountryScreen({super.key, required this.selectedCountry}); + SelectCountryScreen({ + super.key, + required this.selectedCountry, + List? countries, + }) : countries = countries ?? allCountries; @override State createState() => _SelectCountryScreenState(); @@ -16,7 +21,13 @@ class SelectCountryScreen extends StatefulWidget { class _SelectCountryScreenState extends State { bool _isSearching = false; final TextEditingController _searchController = TextEditingController(); - List _filteredCountries = allCountries; + late List _filteredCountries; + + @override + void initState() { + super.initState(); + _filteredCountries = widget.countries; + } @override void dispose() { @@ -27,10 +38,10 @@ class _SelectCountryScreenState extends State { void _filterCountries(String query) { setState(() { if (query.isEmpty) { - _filteredCountries = allCountries; + _filteredCountries = widget.countries; } else { final q = query.toLowerCase(); - _filteredCountries = allCountries.where((c) { + _filteredCountries = widget.countries.where((c) { return c.ru.toLowerCase().contains(q) || c.en.toLowerCase().contains(q) || c.phoneCode.contains(q); @@ -90,7 +101,7 @@ class _SelectCountryScreenState extends State { _isSearching = !_isSearching; if (!_isSearching) { _searchController.clear(); - _filteredCountries = allCountries; + _filteredCountries = widget.countries; } }); },