Polish Telegram auth UI state
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 2m15s

This commit is contained in:
Ruslan Bakiev
2026-05-08 19:14:08 +07:00
parent e463ab09d4
commit cd62a0a428
2 changed files with 69 additions and 10 deletions

View File

@@ -37,6 +37,7 @@ class _TelegramLoginButtonState extends State<TelegramLoginButton> {
if (mounted) { if (mounted) {
widget.onAuthenticated(); widget.onAuthenticated();
} }
web.window.location.reload();
}).toJS; }).toJS;
_window.setProperty(_callbackName.toJS, callback); _window.setProperty(_callbackName.toJS, callback);
ui_web.platformViewRegistry.registerViewFactory(_viewType, _buildElement); ui_web.platformViewRegistry.registerViewFactory(_viewType, _buildElement);

View File

@@ -44,6 +44,9 @@ class _MapContent extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final selected = state.selectedPlace; final selected = state.selectedPlace;
final availableTraits = {
for (final place in state.recommendations) ...place.traits,
}.toList();
return Scaffold( return Scaffold(
body: Stack( body: Stack(
@@ -78,10 +81,20 @@ class _MapContent extends ConsumerWidget {
), ),
SafeArea( SafeArea(
child: Align( child: Align(
alignment: Alignment.topCenter, alignment: Alignment.topLeft,
child: _TraitBar(selectedTrait: state.selectedTrait), child: _UserAvatar(user: state.currentUser),
), ),
), ),
if (availableTraits.isNotEmpty)
SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: _TraitBar(
selectedTrait: state.selectedTrait,
traits: availableTraits,
),
),
),
Align( Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: SafeArea( child: SafeArea(
@@ -124,6 +137,48 @@ class _MapContent extends ConsumerWidget {
} }
} }
class _UserAvatar extends StatelessWidget {
const _UserAvatar({required this.user});
final AppUser? user;
@override
Widget build(BuildContext context) {
final photoUrl = user?.photoUrl;
final fallback = _fallbackText();
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,
),
);
}
String _fallbackText() {
final firstName = user?.firstName?.trim();
if (firstName != null && firstName.isNotEmpty) {
return firstName.characters.first.toUpperCase();
}
final username = user?.username?.trim();
if (username != null && username.isNotEmpty) {
return username.characters.first.toUpperCase();
}
return 'M';
}
}
class _TelegramLoginScreen extends StatelessWidget { class _TelegramLoginScreen extends StatelessWidget {
const _TelegramLoginScreen({required this.onAuthenticated}); const _TelegramLoginScreen({required this.onAuthenticated});
@@ -264,23 +319,24 @@ class _MapAttribution extends StatelessWidget {
} }
class _TraitBar extends ConsumerWidget { class _TraitBar extends ConsumerWidget {
const _TraitBar({required this.selectedTrait}); const _TraitBar({required this.selectedTrait, required this.traits});
final PlaceTrait selectedTrait; final PlaceTrait selectedTrait;
final List<PlaceTrait> traits;
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final controller = ref.read(placeControllerProvider.notifier); final controller = ref.read(placeControllerProvider.notifier);
return Container( return SizedBox(
height: 58, height: 54,
margin: const EdgeInsets.fromLTRB(10, 8, 10, 0),
child: ListView.separated( child: ListView.separated(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: PlaceTrait.values.length, padding: const EdgeInsets.fromLTRB(68, 8, 12, 0),
separatorBuilder: (_, _) => const SizedBox(width: 8), itemCount: traits.length,
separatorBuilder: (_, _) => const SizedBox(width: 6),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = PlaceTrait.values[index]; final item = traits[index];
return ChoiceChip( return ChoiceChip(
avatar: Icon(item.icon, size: 17), avatar: Icon(item.icon, size: 17),
label: Text(item.label), label: Text(item.label),
@@ -288,7 +344,9 @@ class _TraitBar extends ConsumerWidget {
onSelected: (_) => controller.selectTrait(item), onSelected: (_) => controller.selectTrait(item),
backgroundColor: const Color(0xFFFFFBF5), backgroundColor: const Color(0xFFFFFBF5),
selectedColor: Theme.of(context).colorScheme.primaryContainer, selectedColor: Theme.of(context).colorScheme.primaryContainer,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), side: BorderSide.none,
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 9),
); );
}, },
), ),