Polish Telegram login screen
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 2m4s
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 2m4s
This commit is contained in:
@@ -151,17 +151,17 @@ class _UserAvatar extends StatelessWidget {
|
|||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 12, top: 8),
|
padding: const EdgeInsets.only(left: 12, top: 8),
|
||||||
child: CircleAvatar(
|
child: ClipOval(
|
||||||
radius: 22,
|
child: SizedBox.square(
|
||||||
backgroundColor: const Color(0xFFFFFBF5),
|
dimension: 44,
|
||||||
foregroundColor: const Color(0xFF17211D),
|
child: photoUrl == null || photoUrl.isEmpty
|
||||||
backgroundImage: photoUrl == null ? null : NetworkImage(photoUrl),
|
? _AvatarFallback(text: fallback)
|
||||||
child: photoUrl == null
|
: Image.network(
|
||||||
? Text(
|
photoUrl,
|
||||||
fallback,
|
fit: BoxFit.cover,
|
||||||
style: const TextStyle(fontWeight: FontWeight.w900),
|
errorBuilder: (_, _, _) => _AvatarFallback(text: fallback),
|
||||||
)
|
),
|
||||||
: null,
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -181,6 +181,28 @@ class _UserAvatar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AvatarFallback extends StatelessWidget {
|
||||||
|
const _AvatarFallback({required this.text});
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ColoredBox(
|
||||||
|
color: const Color(0xFFFFFBF5),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Color(0xFF17211D),
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _TelegramLoginScreen extends StatefulWidget {
|
class _TelegramLoginScreen extends StatefulWidget {
|
||||||
const _TelegramLoginScreen({required this.onAuthenticated});
|
const _TelegramLoginScreen({required this.onAuthenticated});
|
||||||
|
|
||||||
@@ -193,6 +215,8 @@ class _TelegramLoginScreen extends StatefulWidget {
|
|||||||
class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||||
final _api = MapflowApi();
|
final _api = MapflowApi();
|
||||||
Timer? _pollTimer;
|
Timer? _pollTimer;
|
||||||
|
Timer? _countdownTimer;
|
||||||
|
DateTime? _loginExpiresAt;
|
||||||
var _loading = false;
|
var _loading = false;
|
||||||
var _message = '';
|
var _message = '';
|
||||||
|
|
||||||
@@ -216,6 +240,7 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_pollTimer?.cancel();
|
_pollTimer?.cancel();
|
||||||
|
_countdownTimer?.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,13 +253,20 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
|||||||
telegram_session.savePendingTelegramLoginToken(login.token);
|
telegram_session.savePendingTelegramLoginToken(login.token);
|
||||||
telegram_session.openExternalUrl(login.botUrl);
|
telegram_session.openExternalUrl(login.botUrl);
|
||||||
_pollTimer?.cancel();
|
_pollTimer?.cancel();
|
||||||
|
_countdownTimer?.cancel();
|
||||||
_pollTimer = Timer.periodic(
|
_pollTimer = Timer.periodic(
|
||||||
const Duration(seconds: 2),
|
const Duration(seconds: 2),
|
||||||
(_) => _pollLogin(login.token),
|
(_) => _pollLogin(login.token),
|
||||||
);
|
);
|
||||||
|
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (_) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
});
|
||||||
setState(() {
|
setState(() {
|
||||||
_loading = false;
|
_loading = false;
|
||||||
_message = 'Подтверди вход в боте.';
|
_loginExpiresAt = login.expiresAt;
|
||||||
|
_message = '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,10 +274,12 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
|||||||
final status = await _api.fetchTelegramBotLoginStatus(token);
|
final status = await _api.fetchTelegramBotLoginStatus(token);
|
||||||
if (status.isExpired) {
|
if (status.isExpired) {
|
||||||
_pollTimer?.cancel();
|
_pollTimer?.cancel();
|
||||||
|
_countdownTimer?.cancel();
|
||||||
telegram_session.clearPendingTelegramLoginToken();
|
telegram_session.clearPendingTelegramLoginToken();
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_loginExpiresAt = null;
|
||||||
setState(() => _message = 'Ссылка устарела. Запусти вход заново.');
|
setState(() => _message = 'Ссылка устарела. Запусти вход заново.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -255,12 +289,27 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_pollTimer?.cancel();
|
_pollTimer?.cancel();
|
||||||
|
_countdownTimer?.cancel();
|
||||||
telegram_session.saveMapflowSessionToken(status.sessionToken!);
|
telegram_session.saveMapflowSessionToken(status.sessionToken!);
|
||||||
telegram_session.clearPendingTelegramLoginToken();
|
telegram_session.clearPendingTelegramLoginToken();
|
||||||
widget.onAuthenticated();
|
widget.onAuthenticated();
|
||||||
telegram_session.reloadApp();
|
telegram_session.reloadApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get _remainingText {
|
||||||
|
final expiresAt = _loginExpiresAt;
|
||||||
|
if (expiresAt == null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
final seconds = expiresAt.difference(DateTime.now()).inSeconds;
|
||||||
|
if (seconds <= 0) {
|
||||||
|
return '00:00';
|
||||||
|
}
|
||||||
|
final minutes = seconds ~/ 60;
|
||||||
|
final rest = (seconds % 60).toString().padLeft(2, '0');
|
||||||
|
return '$minutes:$rest';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -280,6 +329,16 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
TelegramLoginButton(onPressed: _startLogin, loading: _loading),
|
TelegramLoginButton(onPressed: _startLogin, loading: _loading),
|
||||||
|
if (_remainingText.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
_remainingText,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
letterSpacing: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
if (_message.isNotEmpty) ...[
|
if (_message.isNotEmpty) ...[
|
||||||
const SizedBox(height: 14),
|
const SizedBox(height: 14),
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
Reference in New Issue
Block a user