Replace Telegram widget with bot login
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 2m22s

This commit is contained in:
Ruslan Bakiev
2026-05-08 19:32:01 +07:00
parent cd62a0a428
commit 5f33a5e880
9 changed files with 276 additions and 95 deletions

View File

@@ -5,7 +5,9 @@ import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:latlong2/latlong.dart';
import '../api/mapflow_api.dart';
import '../auth/telegram_login_button.dart';
import '../auth/telegram_session.dart' as telegram_session;
import '../models/place_models.dart';
import '../state/place_controller.dart';
@@ -179,11 +181,86 @@ class _UserAvatar extends StatelessWidget {
}
}
class _TelegramLoginScreen extends StatelessWidget {
class _TelegramLoginScreen extends StatefulWidget {
const _TelegramLoginScreen({required this.onAuthenticated});
final VoidCallback onAuthenticated;
@override
State<_TelegramLoginScreen> createState() => _TelegramLoginScreenState();
}
class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
final _api = MapflowApi();
Timer? _pollTimer;
var _loading = false;
var _message = '';
@override
void initState() {
super.initState();
final urlToken = telegram_session.telegramLoginTokenFromUrl();
final pendingToken = urlToken.isNotEmpty
? urlToken
: telegram_session.pendingTelegramLoginToken();
if (pendingToken.isNotEmpty) {
telegram_session.savePendingTelegramLoginToken(pendingToken);
_pollLogin(pendingToken);
_pollTimer = Timer.periodic(
const Duration(seconds: 2),
(_) => _pollLogin(pendingToken),
);
}
}
@override
void dispose() {
_pollTimer?.cancel();
super.dispose();
}
Future<void> _startLogin() async {
setState(() {
_loading = true;
_message = '';
});
final login = await _api.startTelegramBotLogin();
telegram_session.savePendingTelegramLoginToken(login.token);
telegram_session.openExternalUrl(login.botUrl);
_pollTimer?.cancel();
_pollTimer = Timer.periodic(
const Duration(seconds: 2),
(_) => _pollLogin(login.token),
);
setState(() {
_loading = false;
_message = 'Подтверди вход в боте.';
});
}
Future<void> _pollLogin(String token) async {
final status = await _api.fetchTelegramBotLoginStatus(token);
if (status.isExpired) {
_pollTimer?.cancel();
telegram_session.clearPendingTelegramLoginToken();
if (!mounted) {
return;
}
setState(() => _message = 'Ссылка устарела. Запусти вход заново.');
return;
}
if (!status.isConfirmed) {
return;
}
_pollTimer?.cancel();
telegram_session.saveMapflowSessionToken(status.sessionToken!);
telegram_session.clearPendingTelegramLoginToken();
widget.onAuthenticated();
telegram_session.reloadApp();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -202,7 +279,15 @@ class _TelegramLoginScreen extends StatelessWidget {
),
),
const SizedBox(height: 24),
TelegramLoginButton(onAuthenticated: onAuthenticated),
TelegramLoginButton(onPressed: _startLogin, loading: _loading),
if (_message.isNotEmpty) ...[
const SizedBox(height: 14),
Text(
_message,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
),
],
],
),
),