bug fixes

This commit is contained in:
2026-09-04 13:41:57 +03:00
parent cf5b56e365
commit 5f57af2ad2
14 changed files with 201 additions and 89 deletions

View File

@@ -71,10 +71,10 @@ class _MapScreenState extends State<MapScreen> {
BlocConsumer<MapBloc, ScooterState>(
listenWhen: (previous, current) {
return current.lastNotification !=
previous.lastNotification ||
previous.lastNotification ||
current.flags != previous.flags ||
previous.selectedScooterForFocus?.id
!= current.selectedScooterForFocus?.id;
previous.selectedScooterForFocus?.id !=
current.selectedScooterForFocus?.id;
},
listener: (context, state) {
@@ -176,7 +176,8 @@ class _MapScreenState extends State<MapScreen> {
final reservedScooters = _buildScooterPlacemarks(
scooters: state.reservedScooters ?? [],
iconAsset: 'assets/icons/scooter_reserved_placemark_fill.png',
iconAsset:
'assets/icons/scooter_reserved_placemark_fill.png',
isClickable: false,
);
@@ -193,10 +194,10 @@ class _MapScreenState extends State<MapScreen> {
},
onCameraPositionChanged:
(cameraPosition, reason, finished) {
if (finished) {
_fetchScooters();
}
},
if (finished) {
_fetchScooters();
}
},
mapObjects: [
...zonePolygons,
...reservedScooters,
@@ -210,7 +211,7 @@ class _MapScreenState extends State<MapScreen> {
final clusteredPlacemarks = cluster.placemarks;
final filtered = state.scooters.where((scooter) {
return clusteredPlacemarks.any(
(pm) => pm.mapId.value == scooter.id.toString(),
(pm) => pm.mapId.value == scooter.id.toString(),
);
}).toList();
_onMarkerTap(filtered);
@@ -241,7 +242,7 @@ class _MapScreenState extends State<MapScreen> {
BlocBuilder<MapBloc, ScooterState>(
buildWhen: (previous, current) =>
previous.status != current.status,
previous.status != current.status,
builder: (context, state) {
if (state.status == ScooterStatus.loading) {
return const Positioned(
@@ -368,6 +369,7 @@ class _MapScreenState extends State<MapScreen> {
}
});
}
Future<void> _moveCameraToPoint(
double lat,
double lon, {
@@ -401,17 +403,13 @@ class _MapScreenState extends State<MapScreen> {
}
if (flags.hasUnpaidOrder) {
_showExistingNotification(
child: UnpaidOrderNotificationCard(
onClose: () => BotToast.cleanAll(),
),
child: UnpaidOrderNotificationCard(onClose: () => BotToast.cleanAll()),
);
return;
}
if (flags.hasFine) {
_showExistingNotification(
child: FineNotificationCard(
onClose: () => BotToast.cleanAll(),
),
child: FineNotificationCard(onClose: () => BotToast.cleanAll()),
);
return;
}
@@ -567,7 +565,8 @@ class _MapScreenState extends State<MapScreen> {
}) {
return scooters.map((scooter) {
return PlacemarkMapObject(
mapId: MapObjectId('${isClickable ? "" : "reserved_"}${scooter.id}'), // уникальный ID для карты
mapId: MapObjectId('${isClickable ? "" : "reserved_"}${scooter.id}'),
// уникальный ID для карты
point: Point(latitude: scooter.longitude, longitude: scooter.latitude),
icon: PlacemarkIcon.single(
PlacemarkIconStyle(
@@ -595,7 +594,9 @@ class _MapScreenState extends State<MapScreen> {
for (var polygonData in zone.geometry) {
if (polygonData.isEmpty) continue;
var outerPoints = polygonData[0].map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
var outerPoints = polygonData[0]
.map((p) => Point(latitude: p.latitude, longitude: p.longitude))
.toList();
var cleanPoints = <Point>[];
for (var p in outerPoints) {
@@ -619,12 +620,14 @@ class _MapScreenState extends State<MapScreen> {
PolygonMapObject(
mapId: const MapObjectId('global_inverse_mask'),
polygon: Polygon(
outerRing: const LinearRing(points: [
Point(latitude: 85, longitude: -179.9),
Point(latitude: 85, longitude: 179.9),
Point(latitude: -85, longitude: 179.9),
Point(latitude: -85, longitude: -179.9),
]),
outerRing: const LinearRing(
points: [
Point(latitude: 85, longitude: -179.9),
Point(latitude: 85, longitude: 179.9),
Point(latitude: -85, longitude: 179.9),
Point(latitude: -85, longitude: -179.9),
],
),
innerRings: driveOuterRings, // Вырезаем только зоны Drive
),
strokeWidth: 0,
@@ -641,13 +644,17 @@ class _MapScreenState extends State<MapScreen> {
// Стилизация в зависимости от типа зоны
if (zone.type == "Drive") {
borderColor = const Color(0xFF5ECD4C); // Зеленый бордюр
fillColor = Colors.transparent; // Прозрачная внутри маски
fillColor = Colors.transparent; // Прозрачная внутри маски
} else if (zone.type == "NotDrive") {
borderColor = const Color(0xFFEF4444); // Красный бордюр
fillColor = const Color(0xFFEF4444).withOpacity(0.3); // Красная полупрозрачная заливка для наглядности внутри Drive
fillColor = const Color(0xFFEF4444).withOpacity(
0.3,
); // Красная полупрозрачная заливка для наглядности внутри Drive
} else {
borderColor = const Color(0xFFA78BFA); // Фиолетовый бордюр (Парковка)
fillColor = const Color(0xFFA78BFA).withOpacity(0.25); // Фиолетовая заливка
fillColor = const Color(
0xFFA78BFA,
).withOpacity(0.25); // Фиолетовая заливка
}
int polyIndex = 0;
@@ -655,7 +662,9 @@ class _MapScreenState extends State<MapScreen> {
if (polygonData.isEmpty) continue;
// Строим внешнее кольцо текущего полигона
var outerPoints = polygonData[0].map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
var outerPoints = polygonData[0]
.map((p) => Point(latitude: p.latitude, longitude: p.longitude))
.toList();
if (outerPoints.first != outerPoints.last) {
outerPoints.add(outerPoints.first);
}
@@ -664,7 +673,9 @@ class _MapScreenState extends State<MapScreen> {
// Строим внутренние кольца (дыры), если они есть у этого полигона
List<LinearRing> innerRings = [];
for (int i = 1; i < polygonData.length; i++) {
var innerPoints = polygonData[i].map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
var innerPoints = polygonData[i]
.map((p) => Point(latitude: p.latitude, longitude: p.longitude))
.toList();
if (innerPoints.isNotEmpty) {
if (innerPoints.first != innerPoints.last) {
innerPoints.add(innerPoints.first);
@@ -677,10 +688,7 @@ class _MapScreenState extends State<MapScreen> {
objects.add(
PolygonMapObject(
mapId: MapObjectId('zone_poly_${zone.type}_${zone.id}_$polyIndex'),
polygon: Polygon(
outerRing: outerRing,
innerRings: innerRings,
),
polygon: Polygon(outerRing: outerRing, innerRings: innerRings),
strokeColor: borderColor,
strokeWidth: 2.0,
fillColor: fillColor,
@@ -707,7 +715,7 @@ class _MapScreenState extends State<MapScreen> {
onPressed: () {
context.read<MapBloc>().add(FetchProfileData());
Scaffold.of(innerContext).openDrawer();
},
},
),
),
),
@@ -721,10 +729,21 @@ class _MapScreenState extends State<MapScreen> {
onPressed: () => context.push("/home/notifications"),
),
const SizedBox(height: 12),
_RoundButton(
imagePath: 'assets/icons/scooter_placemark.png',
onPressed: () => context.push("/home/current-rides-sheet"),
)
BlocBuilder<MapBloc, ScooterState>(
buildWhen: (previous, current) =>
previous.activeRidesCount != current.activeRidesCount,
builder: (context, state) {
return _RoundButton(
imagePath: 'assets/icons/scooter_placemark.png',
count: state.activeRidesCount ?? 0,
onPressed: () {
context.push("/home/current-rides-sheet").then((_) {
context.read<MapBloc>().add(FetchActiveOrders());
});
},
);
},
),
],
),
),
@@ -765,9 +784,7 @@ class _MapScreenState extends State<MapScreen> {
}
if (flags.hasFine) {
_showExistingNotification(
child: FineNotificationCard(
onClose: () => BotToast.cleanAll(),
),
child: FineNotificationCard(onClose: () => BotToast.cleanAll()),
);
return;
}
@@ -870,32 +887,63 @@ class _RoundIconButton extends StatelessWidget {
class _RoundButton extends StatelessWidget {
final String imagePath;
final VoidCallback onPressed;
final int count;
const _RoundButton({
required this.imagePath,
required this.onPressed,
this.count = 0,
});
@override
Widget build(BuildContext context) {
return Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColors.darkBlue,
borderRadius: BorderRadius.circular(12),
),
child: GestureDetector(
onTap: onPressed,
child: Center(
child: Image.asset(
imagePath,
width: 20,
height: 20,
fit: BoxFit.contain,
color: Colors.white,
return GestureDetector(
onTap: onPressed,
child: Stack(
clipBehavior: Clip.none,
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColors.darkBlue,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Image.asset(
imagePath,
width: 20,
height: 20,
fit: BoxFit.contain,
color: Colors.white,
),
),
),
),
if (count > 0)
Positioned(
top: -4,
right: -4,
child: Container(
padding: const EdgeInsets.all(4),
decoration: const BoxDecoration(
color: Colors.redAccent,
shape: BoxShape.circle,
),
constraints: const BoxConstraints(minWidth: 18, minHeight: 18),
child: Center(
child: Text(
'$count',
style: const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
),
),
],
),
);
}
@@ -929,10 +977,12 @@ void _showExistingNotification({required Widget child}) {
duration: null, // не исчезает, пока пользователь не закроет
toastBuilder: (_) {
return Container(
margin: const EdgeInsets.only(top: 120), // тот же отступ, что в listener
margin: const EdgeInsets.only(top: 120),
// тот же отступ, что в listener
child: Material(
color: Colors.transparent,
child: child, // PaymentNotificationCard / UnpaidOrderNotificationCard / FineNotificationCard
child:
child, // PaymentNotificationCard / UnpaidOrderNotificationCard / FineNotificationCard
),
);
},