bug fixes
This commit is contained in:
@@ -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
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user