diff --git a/lib/auth/telegram_session_stub.dart b/lib/auth/telegram_session_stub.dart index 8229f3d..4e0d022 100644 --- a/lib/auth/telegram_session_stub.dart +++ b/lib/auth/telegram_session_stub.dart @@ -10,6 +10,8 @@ void saveMapflowSessionToken(String token) {} void clearMapflowSession() {} +void configureTelegramWebApp() {} + void openExternalUrl(String url) {} void reloadApp() {} diff --git a/lib/auth/telegram_session_web.dart b/lib/auth/telegram_session_web.dart index 8e6b6e9..faa1a5e 100644 --- a/lib/auth/telegram_session_web.dart +++ b/lib/auth/telegram_session_web.dart @@ -5,13 +5,28 @@ import 'package:web/web.dart' as web; const telegramLoginStorageKey = 'mapflow.telegramLoginData'; const mapflowSessionStorageKey = 'mapflow.sessionToken'; -@JS('window.Telegram.WebApp.initData') -external JSString? get _telegramInitData; +@JS('Telegram') +external _Telegram? get _telegram; + +extension type _Telegram(JSObject _) implements JSObject { + @JS('WebApp') + external _TelegramWebApp? get webApp; +} + +extension type _TelegramWebApp(JSObject _) implements JSObject { + external JSString? get initData; + external void ready(); + external void expand(); + external bool isVersionAtLeast(String version); + external void disableVerticalSwipes(); +} @JS('JSON.stringify') external JSString _jsonStringify(JSAny? value); -String telegramInitData() => _telegramInitData?.toDart ?? ''; +_TelegramWebApp? get _webApp => _telegram?.webApp; + +String telegramInitData() => _webApp?.initData?.toDart ?? ''; String telegramLoginData() => web.window.localStorage.getItem(telegramLoginStorageKey) ?? ''; @@ -38,6 +53,19 @@ void clearMapflowSession() { web.window.localStorage.removeItem(telegramLoginStorageKey); } +void configureTelegramWebApp() { + final webApp = _webApp; + if (webApp == null) { + return; + } + + webApp.ready(); + webApp.expand(); + if (webApp.isVersionAtLeast('7.7')) { + webApp.disableVerticalSwipes(); + } +} + void openExternalUrl(String url) { web.window.location.assign(url); } diff --git a/lib/main.dart b/lib/main.dart index d0dd374..98917e6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,10 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'auth/telegram_session.dart' as telegram_session; import 'screens/mapflow_shell.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); + telegram_session.configureTelegramWebApp(); runApp(const ProviderScope(child: MapflowApp())); } diff --git a/lib/screens/mapflow_shell.dart b/lib/screens/mapflow_shell.dart index dfc1075..a4fa62a 100644 --- a/lib/screens/mapflow_shell.dart +++ b/lib/screens/mapflow_shell.dart @@ -4,6 +4,7 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:latlong2/latlong.dart' hide Path; import 'package:waveform_flutter/waveform_flutter.dart' show Amplitude; import 'package:waveform_recorder/waveform_recorder.dart'; @@ -231,11 +232,7 @@ class _UserAvatar extends StatelessWidget { dimension: 44, child: imageUrl == null ? _AvatarFallback(text: fallback) - : Image.network( - imageUrl, - fit: BoxFit.cover, - errorBuilder: (_, _, _) => _AvatarFallback(text: fallback), - ), + : _AvatarImage(url: imageUrl, fallback: fallback), ), ), ), @@ -264,6 +261,31 @@ class _UserAvatar extends StatelessWidget { enum _AvatarAction { logout } +class _AvatarImage extends StatelessWidget { + const _AvatarImage({required this.url, required this.fallback}); + + final String url; + final String fallback; + + @override + Widget build(BuildContext context) { + if (url.endsWith('.svg') || url.contains('.svg?')) { + return SvgPicture.network( + url, + fit: BoxFit.cover, + placeholderBuilder: (_) => _AvatarFallback(text: fallback), + errorBuilder: (_, _, _) => _AvatarFallback(text: fallback), + ); + } + + return Image.network( + url, + fit: BoxFit.cover, + errorBuilder: (_, _, _) => _AvatarFallback(text: fallback), + ); + } +} + class _AvatarFallback extends StatelessWidget { const _AvatarFallback({required this.text}); @@ -1004,12 +1026,6 @@ class _NearbyPlaceCard extends StatelessWidget { @override Widget build(BuildContext context) { final primaryType = _formatType(place.googlePrimaryType); - final visibleTypes = place.googleTypes - .where((type) => type != place.googlePrimaryType) - .map(_formatType) - .nonNulls - .take(4) - .toList(); return Material( color: const Color(0xFF15111D), @@ -1041,17 +1057,12 @@ class _NearbyPlaceCard extends StatelessWidget { ), ], ), - if (primaryType != null || visibleTypes.isNotEmpty) ...[ + if (primaryType != null) ...[ const SizedBox(height: 12), Wrap( spacing: 6, runSpacing: 6, - children: [ - if (primaryType != null) - _PlaceTypeChip(label: primaryType, primary: true), - for (final type in visibleTypes) - _PlaceTypeChip(label: type, primary: false), - ], + children: [_PlaceTypeChip(label: primaryType, primary: true)], ), ], ], diff --git a/pubspec.lock b/pubspec.lock index 8599621..cfdebb3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -214,6 +214,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f" + url: "https://pub.dev" + source: hosted + version: "2.3.0" flutter_test: dependency: "direct dev" description: flutter @@ -520,6 +528,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: transitive description: @@ -861,6 +877,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.3" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "4d35a36400983c3457c289d4d553b5308f506ea84f7e51c7a564651b5525209a" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "98e7e94de127b46a86ef46197fff84ff99f3d3b80a708390d717ad731efef598" + url: "https://pub.dev" + source: hosted + version: "1.2.2" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9828e1f..85f4d88 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -43,6 +43,7 @@ dependencies: record: ^6.2.0 waveform_recorder: ^1.8.0 waveform_flutter: ^1.2.0 + flutter_svg: ^2.3.0 dev_dependencies: flutter_test: