diff --git a/lib/core/transport/connection.dart b/lib/core/transport/connection.dart index 9aa8869..afb9dd9 100644 --- a/lib/core/transport/connection.dart +++ b/lib/core/transport/connection.dart @@ -13,6 +13,8 @@ enum SocketState { disconnected, connecting, connected } /// Обёртка над TCP + TLS сокетом. /// Отдаёт сырые байты через [dataStream], сборкой пакетов занимается [PacketReceiver]. class Connection { + static const Duration _defaultConnectTimeout = Duration(seconds: 15); + SecureSocket? _socket; StreamSubscription? _subscription; SocketState _state = SocketState.disconnected; @@ -86,28 +88,30 @@ class Connection { ProxySettings proxySettings, { Duration? timeout, }) async { + final connectTimeout = timeout ?? _defaultConnectTimeout; Socket socket; if (proxySettings.isEnabled) { final connector = ProxyConnector(proxySettings); - socket = await connector.connect(host, port); + socket = await connector.connect(host, port).timeout(connectTimeout); logger.i('Подключено через прокси ${proxySettings.type.name}'); } else { - socket = timeout == null - ? await Socket.connect(host, port) - : await Socket.connect(host, port, timeout: timeout); + socket = await Socket.connect(host, port, timeout: connectTimeout); } final allowInsecure = await TlsConfig.isInsecureAllowed(); if (allowInsecure) { logger.w( 'TLS: проверка сертификата отключена (дебаг) — соединение уязвимо к MitM', ); - return SecureSocket.secure( - socket, - host: host, - onBadCertificate: (_) => true, - ); } - return SecureSocket.secure(socket, host: host); + final secured = allowInsecure + ? SecureSocket.secure(socket, host: host, onBadCertificate: (_) => true) + : SecureSocket.secure(socket, host: host); + try { + return await secured.timeout(connectTimeout); + } on TimeoutException { + socket.destroy(); + rethrow; + } } void write(Uint8List data) { diff --git a/lib/main.dart b/lib/main.dart index 89b0cdf..88a8c36 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -91,13 +91,6 @@ void main() async { final storiesFuture = AppStories.load(); final cacheLimitFuture = AppMediaCacheLimit.load(); - await api.connect(); - - final packageInfo = await packageInfoFuture; - if (packageInfo.packageName == 'ru.oneme.app') { - await PushService.instance.init(api: api, account: accountModule); - } - final initialLocale = await localeFuture; await hapticsFuture; @@ -135,6 +128,15 @@ void main() async { initialAccentSeed: initialAccentSeed, ), ); + + unawaited(_initPushIfNeeded(packageInfoFuture)); +} + +Future _initPushIfNeeded(Future packageInfoFuture) async { + final packageInfo = await packageInfoFuture; + if (packageInfo.packageName == 'ru.oneme.app') { + await PushService.instance.init(api: api, account: accountModule); + } } class KometApp extends StatefulWidget { @@ -714,27 +716,25 @@ class _StartupScreenState extends State<_StartupScreen> { } Future _tryAutoLogin() async { + unawaited(api.connect()); + int? accountId = await TokenStorage.getActiveAccountId(); if (accountId == null || await TokenStorage.readToken(accountId) == null) { accountId = await _recoverActiveAccount(); } + if (!mounted) return; + if (accountId == null) { _goToLogin(); return; } - try { - await accountModule.login(accountId: accountId); - } catch (_) {} - - if (mounted) { - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (_) => const AdaptiveShell()), - ); - } + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (_) => const AdaptiveShell()), + ); } Future _recoverActiveAccount() async {