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(
|
||||
padding: const EdgeInsets.only(left: 12, top: 8),
|
||||
child: CircleAvatar(
|
||||
radius: 22,
|
||||
backgroundColor: const Color(0xFFFFFBF5),
|
||||
foregroundColor: const Color(0xFF17211D),
|
||||
backgroundImage: photoUrl == null ? null : NetworkImage(photoUrl),
|
||||
child: photoUrl == null
|
||||
? Text(
|
||||
fallback,
|
||||
style: const TextStyle(fontWeight: FontWeight.w900),
|
||||
)
|
||||
: null,
|
||||
child: ClipOval(
|
||||
child: SizedBox.square(
|
||||
dimension: 44,
|
||||
child: photoUrl == null || photoUrl.isEmpty
|
||||
? _AvatarFallback(text: fallback)
|
||||
: Image.network(
|
||||
photoUrl,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, _, _) => _AvatarFallback(text: fallback),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -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 {
|
||||
const _TelegramLoginScreen({required this.onAuthenticated});
|
||||
|
||||
@@ -193,6 +215,8 @@ class _TelegramLoginScreen extends StatefulWidget {
|
||||
class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
final _api = MapflowApi();
|
||||
Timer? _pollTimer;
|
||||
Timer? _countdownTimer;
|
||||
DateTime? _loginExpiresAt;
|
||||
var _loading = false;
|
||||
var _message = '';
|
||||
|
||||
@@ -216,6 +240,7 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
@override
|
||||
void dispose() {
|
||||
_pollTimer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -228,13 +253,20 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
telegram_session.savePendingTelegramLoginToken(login.token);
|
||||
telegram_session.openExternalUrl(login.botUrl);
|
||||
_pollTimer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
_pollTimer = Timer.periodic(
|
||||
const Duration(seconds: 2),
|
||||
(_) => _pollLogin(login.token),
|
||||
);
|
||||
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (_) {
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
setState(() {
|
||||
_loading = false;
|
||||
_message = 'Подтверди вход в боте.';
|
||||
_loginExpiresAt = login.expiresAt;
|
||||
_message = '';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -242,10 +274,12 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
final status = await _api.fetchTelegramBotLoginStatus(token);
|
||||
if (status.isExpired) {
|
||||
_pollTimer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
telegram_session.clearPendingTelegramLoginToken();
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_loginExpiresAt = null;
|
||||
setState(() => _message = 'Ссылка устарела. Запусти вход заново.');
|
||||
return;
|
||||
}
|
||||
@@ -255,12 +289,27 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
}
|
||||
|
||||
_pollTimer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
telegram_session.saveMapflowSessionToken(status.sessionToken!);
|
||||
telegram_session.clearPendingTelegramLoginToken();
|
||||
widget.onAuthenticated();
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -280,6 +329,16 @@ class _TelegramLoginScreenState extends State<_TelegramLoginScreen> {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
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) ...[
|
||||
const SizedBox(height: 14),
|
||||
Text(
|
||||
|
||||
Reference in New Issue
Block a user