feat(auth): server endpoint in bottom sheet on login
This commit is contained in:
@@ -70,7 +70,8 @@ class Api {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await _connection.connect(ServerConfig.host, ServerConfig.port);
|
final endpoint = await ServerConfig.loadEndpoint();
|
||||||
|
await _connection.connect(endpoint.host, endpoint.port);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.e('Не удалось подключиться: $e');
|
logger.e('Не удалось подключиться: $e');
|
||||||
_cleanup();
|
_cleanup();
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
abstract class ServerConfig {
|
abstract class ServerConfig {
|
||||||
static const String host = 'api.oneme.ru';
|
static const String defaultHost = 'api.oneme.ru';
|
||||||
static const int port = 443;
|
static const int defaultPort = 443;
|
||||||
|
static const String prefHostKey = 'server_host_override';
|
||||||
|
static const String prefPortKey = 'server_port_override';
|
||||||
static const Duration pingInterval = Duration(seconds: 30);
|
static const Duration pingInterval = Duration(seconds: 30);
|
||||||
static const Duration requestTimeout = Duration(seconds: 30);
|
static const Duration requestTimeout = Duration(seconds: 30);
|
||||||
static const int maxReconnectAttempts = 50;
|
static const int maxReconnectAttempts = 50;
|
||||||
|
|
||||||
|
static Future<({String host, int port})> loadEndpoint() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final rawHost = prefs.getString(prefHostKey);
|
||||||
|
final rawPort = prefs.getInt(prefPortKey);
|
||||||
|
final host = (rawHost != null && rawHost.trim().isNotEmpty)
|
||||||
|
? rawHost.trim()
|
||||||
|
: defaultHost;
|
||||||
|
var port = defaultPort;
|
||||||
|
if (rawPort != null && rawPort >= 1 && rawPort <= 65535) {
|
||||||
|
port = rawPort;
|
||||||
|
}
|
||||||
|
return (host: host, port: port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import 'package:komet/l10n/terms_of_service.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'code_confirmation_screen.dart';
|
import 'code_confirmation_screen.dart';
|
||||||
import 'select_country_screen.dart';
|
import 'select_country_screen.dart';
|
||||||
|
import 'server_settings_sheet.dart';
|
||||||
import 'spoff_redacted_screen.dart';
|
import 'spoff_redacted_screen.dart';
|
||||||
import '../../widgets/custom_notification.dart';
|
import '../../widgets/custom_notification.dart';
|
||||||
import '../../../main.dart';
|
import '../../../main.dart';
|
||||||
@@ -448,6 +449,23 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
_showPhoneConfirmationDialog(_phoneController.text);
|
_showPhoneConfirmationDialog(_phoneController.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showServerSettingsSheet(BuildContext context) {
|
||||||
|
final cs = Theme.of(context).colorScheme;
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: cs.surfaceContainerHigh,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||||
|
),
|
||||||
|
builder: (_) {
|
||||||
|
return SafeArea(
|
||||||
|
child: const ServerSettingsSheet(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _showSecurityOptions(BuildContext context) {
|
void _showSecurityOptions(BuildContext context) {
|
||||||
final cs = Theme.of(context).colorScheme;
|
final cs = Theme.of(context).colorScheme;
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
@@ -457,7 +475,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||||
),
|
),
|
||||||
builder: (context) {
|
builder: (sheetContext) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
@@ -478,7 +496,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(sheetContext);
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
@@ -498,7 +516,22 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(sheetContext);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Symbols.dns, color: cs.onSurface),
|
||||||
|
title: Text(
|
||||||
|
l10n.loginChangeServer,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: cs.onSurface,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(sheetContext);
|
||||||
|
_showServerSettingsSheet(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:komet/backend/api.dart';
|
||||||
|
import 'package:komet/core/config/config.dart';
|
||||||
|
import 'package:komet/l10n/app_localizations.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../../main.dart';
|
||||||
|
import '../../widgets/custom_notification.dart';
|
||||||
|
|
||||||
|
class ServerSettingsSheet extends StatefulWidget {
|
||||||
|
const ServerSettingsSheet({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ServerSettingsSheet> createState() => _ServerSettingsSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ServerSettingsSheetState extends State<ServerSettingsSheet> {
|
||||||
|
final TextEditingController _hostController = TextEditingController(
|
||||||
|
text: ServerConfig.defaultHost,
|
||||||
|
);
|
||||||
|
final TextEditingController _portController = TextEditingController(
|
||||||
|
text: '${ServerConfig.defaultPort}',
|
||||||
|
);
|
||||||
|
bool _busy = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _load() async {
|
||||||
|
final endpoint = await ServerConfig.loadEndpoint();
|
||||||
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
_hostController.text = endpoint.host;
|
||||||
|
_portController.text = '${endpoint.port}';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _apply(AppLocalizations l10n) async {
|
||||||
|
final host = _hostController.text.trim();
|
||||||
|
final port = int.tryParse(_portController.text.trim());
|
||||||
|
if (host.isEmpty || port == null || port < 1 || port > 65535) {
|
||||||
|
showCustomNotification(context, l10n.serverInvalidHostOrPort);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() => _busy = true);
|
||||||
|
try {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.setString(ServerConfig.prefHostKey, host);
|
||||||
|
await prefs.setInt(ServerConfig.prefPortKey, port);
|
||||||
|
await api.disconnect();
|
||||||
|
await api.connect();
|
||||||
|
if (!mounted) return;
|
||||||
|
if (api.state == SessionState.online) {
|
||||||
|
showCustomNotification(context, l10n.serverSettingsSaved);
|
||||||
|
} else {
|
||||||
|
showCustomNotification(context, l10n.serverReconnectFailed);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) setState(() => _busy = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _resetToDefault(AppLocalizations l10n) async {
|
||||||
|
setState(() => _busy = true);
|
||||||
|
try {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.remove(ServerConfig.prefHostKey);
|
||||||
|
await prefs.remove(ServerConfig.prefPortKey);
|
||||||
|
_hostController.text = ServerConfig.defaultHost;
|
||||||
|
_portController.text = '${ServerConfig.defaultPort}';
|
||||||
|
await api.disconnect();
|
||||||
|
await api.connect();
|
||||||
|
if (!mounted) return;
|
||||||
|
if (api.state == SessionState.online) {
|
||||||
|
showCustomNotification(context, l10n.serverSettingsSaved);
|
||||||
|
} else {
|
||||||
|
showCustomNotification(context, l10n.serverReconnectFailed);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (mounted) setState(() => _busy = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_hostController.dispose();
|
||||||
|
_portController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final cs = Theme.of(context).colorScheme;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final bottomInset = MediaQuery.viewInsetsOf(context).bottom;
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: bottomInset),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 8, 16, 24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
width: 40,
|
||||||
|
height: 4,
|
||||||
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: cs.onSurfaceVariant.withValues(alpha: 0.35),
|
||||||
|
borderRadius: BorderRadius.circular(2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
l10n.serverSettingsTitle,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: cs.onSurface,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildTextField(
|
||||||
|
controller: _hostController,
|
||||||
|
label: l10n.serverHostLabel,
|
||||||
|
hintText: ServerConfig.defaultHost,
|
||||||
|
cs: cs,
|
||||||
|
keyboardType: TextInputType.url,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildTextField(
|
||||||
|
controller: _portController,
|
||||||
|
label: l10n.serverPortLabel,
|
||||||
|
hintText: '${ServerConfig.defaultPort}',
|
||||||
|
cs: cs,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.digitsOnly,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
FilledButton(
|
||||||
|
onPressed: _busy ? null : () => _apply(l10n),
|
||||||
|
child: Text(l10n.serverApply),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: _busy ? null : () => _resetToDefault(l10n),
|
||||||
|
child: Text(l10n.serverUseDefault),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextField({
|
||||||
|
required TextEditingController controller,
|
||||||
|
required String label,
|
||||||
|
required ColorScheme cs,
|
||||||
|
String? hintText,
|
||||||
|
TextInputType? keyboardType,
|
||||||
|
List<TextInputFormatter>? inputFormatters,
|
||||||
|
}) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: cs.onSurfaceVariant,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
TextField(
|
||||||
|
controller: controller,
|
||||||
|
keyboardType: keyboardType,
|
||||||
|
inputFormatters: inputFormatters,
|
||||||
|
enabled: !_busy,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: cs.onSurface,
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: hintText,
|
||||||
|
hintStyle: GoogleFonts.inter(
|
||||||
|
color: cs.onSurfaceVariant.withValues(alpha: 0.6),
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: cs.surfaceContainerHighest,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,15 @@
|
|||||||
"loginReadTermsNotification": "Please read the terms of use first",
|
"loginReadTermsNotification": "Please read the terms of use first",
|
||||||
"loginSpoofRedacted": "Spoof redaction",
|
"loginSpoofRedacted": "Spoof redaction",
|
||||||
"loginProxy": "Proxy",
|
"loginProxy": "Proxy",
|
||||||
|
"loginChangeServer": "Change server",
|
||||||
|
"serverSettingsTitle": "Server",
|
||||||
|
"serverHostLabel": "Host",
|
||||||
|
"serverPortLabel": "Port",
|
||||||
|
"serverApply": "Apply and reconnect",
|
||||||
|
"serverUseDefault": "Reset to default",
|
||||||
|
"serverInvalidHostOrPort": "Enter a valid host and port (1–65535)",
|
||||||
|
"serverSettingsSaved": "Server settings applied",
|
||||||
|
"serverReconnectFailed": "Could not connect to the server",
|
||||||
"loginSignInWithQr": "Sign in with QR code",
|
"loginSignInWithQr": "Sign in with QR code",
|
||||||
"loginSignInWithToken": "Sign in with token",
|
"loginSignInWithToken": "Sign in with token",
|
||||||
"loginSignInWithSessionFile": "Sign in with session file",
|
"loginSignInWithSessionFile": "Sign in with session file",
|
||||||
|
|||||||
@@ -188,6 +188,60 @@ abstract class AppLocalizations {
|
|||||||
/// **'Proxy'**
|
/// **'Proxy'**
|
||||||
String get loginProxy;
|
String get loginProxy;
|
||||||
|
|
||||||
|
/// No description provided for @loginChangeServer.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Change server'**
|
||||||
|
String get loginChangeServer;
|
||||||
|
|
||||||
|
/// No description provided for @serverSettingsTitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Server'**
|
||||||
|
String get serverSettingsTitle;
|
||||||
|
|
||||||
|
/// No description provided for @serverHostLabel.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Host'**
|
||||||
|
String get serverHostLabel;
|
||||||
|
|
||||||
|
/// No description provided for @serverPortLabel.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Port'**
|
||||||
|
String get serverPortLabel;
|
||||||
|
|
||||||
|
/// No description provided for @serverApply.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Apply and reconnect'**
|
||||||
|
String get serverApply;
|
||||||
|
|
||||||
|
/// No description provided for @serverUseDefault.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Reset to default'**
|
||||||
|
String get serverUseDefault;
|
||||||
|
|
||||||
|
/// No description provided for @serverInvalidHostOrPort.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Enter a valid host and port (1–65535)'**
|
||||||
|
String get serverInvalidHostOrPort;
|
||||||
|
|
||||||
|
/// No description provided for @serverSettingsSaved.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Server settings applied'**
|
||||||
|
String get serverSettingsSaved;
|
||||||
|
|
||||||
|
/// No description provided for @serverReconnectFailed.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Could not connect to the server'**
|
||||||
|
String get serverReconnectFailed;
|
||||||
|
|
||||||
/// No description provided for @loginSignInWithQr.
|
/// No description provided for @loginSignInWithQr.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -54,6 +54,33 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get loginProxy => 'Proxy';
|
String get loginProxy => 'Proxy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loginChangeServer => 'Change server';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverSettingsTitle => 'Server';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverHostLabel => 'Host';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverPortLabel => 'Port';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverApply => 'Apply and reconnect';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverUseDefault => 'Reset to default';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverInvalidHostOrPort => 'Enter a valid host and port (1–65535)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverSettingsSaved => 'Server settings applied';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverReconnectFailed => 'Could not connect to the server';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get loginSignInWithQr => 'Sign in with QR code';
|
String get loginSignInWithQr => 'Sign in with QR code';
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,34 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get loginProxy => 'Прокси';
|
String get loginProxy => 'Прокси';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loginChangeServer => 'Смена сервера';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverSettingsTitle => 'Сервер';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverHostLabel => 'Хост';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverPortLabel => 'Порт';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverApply => 'Применить и переподключиться';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverUseDefault => 'Сбросить к умолчанию';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverInvalidHostOrPort =>
|
||||||
|
'Укажите корректный хост и порт (1–65535)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverSettingsSaved => 'Настройки сервера применены';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get serverReconnectFailed => 'Не удалось подключиться к серверу';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get loginSignInWithQr => 'По QR code';
|
String get loginSignInWithQr => 'По QR code';
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,15 @@
|
|||||||
"loginReadTermsNotification": "Сначала прочитайте условия использования",
|
"loginReadTermsNotification": "Сначала прочитайте условия использования",
|
||||||
"loginSpoofRedacted": "Подделка спуфа",
|
"loginSpoofRedacted": "Подделка спуфа",
|
||||||
"loginProxy": "Прокси",
|
"loginProxy": "Прокси",
|
||||||
|
"loginChangeServer": "Смена сервера",
|
||||||
|
"serverSettingsTitle": "Сервер",
|
||||||
|
"serverHostLabel": "Хост",
|
||||||
|
"serverPortLabel": "Порт",
|
||||||
|
"serverApply": "Применить и переподключиться",
|
||||||
|
"serverUseDefault": "Сбросить к умолчанию",
|
||||||
|
"serverInvalidHostOrPort": "Укажите корректный хост и порт (1–65535)",
|
||||||
|
"serverSettingsSaved": "Настройки сервера применены",
|
||||||
|
"serverReconnectFailed": "Не удалось подключиться к серверу",
|
||||||
"loginSignInWithQr": "По QR code",
|
"loginSignInWithQr": "По QR code",
|
||||||
"loginSignInWithToken": "По токену",
|
"loginSignInWithToken": "По токену",
|
||||||
"loginSignInWithSessionFile": "По файлу сессии",
|
"loginSignInWithSessionFile": "По файлу сессии",
|
||||||
|
|||||||
+8
-8
@@ -21,10 +21,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.1"
|
version: "1.4.0"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -313,18 +313,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.19"
|
version: "0.12.17"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.0"
|
version: "0.11.1"
|
||||||
material_symbols_icons:
|
material_symbols_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -638,10 +638,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.7"
|
||||||
timezone:
|
timezone:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user