This commit is contained in:
2026-07-13 01:38:13 +03:00
parent 9eda119527
commit 98c5a7a1d1
54 changed files with 860 additions and 454 deletions

View File

@@ -4,24 +4,9 @@ import 'dart:ui' as ui;
import 'package:bot_toast/bot_toast.dart';
import 'package:be_happy/domain/entities/client_notification.dart';
import 'package:be_happy/domain/usecase/book_scooter_usecase.dart';
import 'package:be_happy/domain/usecase/get_client_orders_usecase.dart';
import 'package:be_happy/domain/usecase/get_map_settings_usecase.dart';
import 'package:be_happy/domain/usecase/get_payment_cards_usecase.dart';
import 'package:be_happy/domain/usecase/get_pedestrian_routes_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_usecase.dart';
import 'package:be_happy/domain/usecase/save_map_settings_usecase.dart';
import 'package:be_happy/presentation/components/fine_notification_card.dart';
import 'package:be_happy/presentation/components/map_icon_painter/clusterized_icon_painter.dart';
import 'package:be_happy/presentation/components/payment_notification_card.dart';
import 'package:be_happy/presentation/components/sheet/current_rides_sheet.dart';
import 'package:be_happy/presentation/components/sheet/map_settings_sheet.dart';
import 'package:be_happy/presentation/components/sheet/tariff_sheet.dart';
import 'package:be_happy/presentation/event/current_rides_event.dart';
import 'package:be_happy/presentation/event/map_settings_modal_event.dart';
import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart';
import 'package:be_happy/presentation/viewmodel/map_settings_modal_bloc.dart';
import 'package:be_happy/presentation/viewmodel/tariff_sheet_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
@@ -32,18 +17,12 @@ import '../../core/app_colors.dart';
import '../../di/service_locator.dart';
import '../../domain/entities/scooter.dart';
import '../../domain/entities/zone.dart';
import '../../domain/usecase/get_address_by_point_usecase.dart';
import '../../domain/usecase/get_available_tariffs_usecase.dart';
import '../../domain/usecase/get_notifications_stream_usecase.dart';
import '../components/notification_toast.dart';
import '../components/sheet/scooter_bottom_sheet.dart';
import '../components/side_menu.dart';
import '../components/unpaid_order_notification_card.dart';
import '../event/map_event.dart';
import '../event/scooter_detail_modal_event.dart';
import '../state/map_state.dart';
import '../viewmodel/map_bloc.dart';
import '../viewmodel/scooter_detail_modal_bloc.dart';
class MapScreen extends StatefulWidget {
const MapScreen({super.key});
@@ -609,28 +588,33 @@ class _MapScreenState extends State<MapScreen> {
if (zones == null || zones.isEmpty) return [];
List<MapObject> objects = [];
List<LinearRing> allZoneHoles = [];
List<LinearRing> driveOuterRings = [];
for (var zone in zones) {
var points = zone.points.map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
if (zone.type == "Drive") {
for (var polygonData in zone.geometry) {
if (polygonData.isEmpty) continue;
var cleanPoints = <Point>[];
for (var p in points) {
if (cleanPoints.isEmpty || cleanPoints.last != p) {
cleanPoints.add(p);
var outerPoints = polygonData[0].map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
var cleanPoints = <Point>[];
for (var p in outerPoints) {
if (cleanPoints.isEmpty || cleanPoints.last != p) {
cleanPoints.add(p);
}
}
if (cleanPoints.length > 2) {
if (cleanPoints.first != cleanPoints.last) {
cleanPoints.add(cleanPoints.first);
}
driveOuterRings.add(LinearRing(points: cleanPoints));
}
}
}
if (cleanPoints.length > 2) {
if (cleanPoints.first != cleanPoints.last) {
cleanPoints.add(cleanPoints.first);
}
allZoneHoles.add(LinearRing(points: cleanPoints));
}
}
// Добавляем глобальную маску (все, что НЕ Drive — затеняется красным)
objects.add(
PolygonMapObject(
mapId: const MapObjectId('global_inverse_mask'),
@@ -641,7 +625,7 @@ class _MapScreenState extends State<MapScreen> {
Point(latitude: -85, longitude: 179.9),
Point(latitude: -85, longitude: -179.9),
]),
innerRings: allZoneHoles,
innerRings: driveOuterRings, // Вырезаем только зоны Drive
),
strokeWidth: 0,
fillColor: Colors.red.withOpacity(0.15),
@@ -649,27 +633,63 @@ class _MapScreenState extends State<MapScreen> {
),
);
// 2. Отрисовываем каждую зону (включая MultiPolygon и вложенные NotDrive/Finish)
for (var zone in zones) {
Color borderColor;
Color fillColor;
// Стилизация в зависимости от типа зоны
if (zone.type == "Drive") {
borderColor = const Color(0xFF5ECD4C);
borderColor = const Color(0xFF5ECD4C); // Зеленый бордюр
fillColor = Colors.transparent; // Прозрачная внутри маски
} else if (zone.type == "NotDrive") {
borderColor = const Color(0xFFEF4444);
borderColor = const Color(0xFFEF4444); // Красный бордюр
fillColor = const Color(0xFFEF4444).withOpacity(0.3); // Красная полупрозрачная заливка для наглядности внутри Drive
} else {
borderColor = const Color(0xFFA78BFA);
borderColor = const Color(0xFFA78BFA); // Фиолетовый бордюр (Парковка)
fillColor = const Color(0xFFA78BFA).withOpacity(0.25); // Фиолетовая заливка
}
objects.add(
PolylineMapObject(
mapId: MapObjectId('zone_contour_${zone.id}'),
polyline: Polyline(
points: zone.points.map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList(),
int polyIndex = 0;
for (var polygonData in zone.geometry) {
if (polygonData.isEmpty) continue;
// Строим внешнее кольцо текущего полигона
var outerPoints = polygonData[0].map((p) => Point(latitude: p.latitude, longitude: p.longitude)).toList();
if (outerPoints.first != outerPoints.last) {
outerPoints.add(outerPoints.first);
}
LinearRing outerRing = LinearRing(points: outerPoints);
// Строим внутренние кольца (дыры), если они есть у этого полигона
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();
if (innerPoints.isNotEmpty) {
if (innerPoints.first != innerPoints.last) {
innerPoints.add(innerPoints.first);
}
innerRings.add(LinearRing(points: innerPoints));
}
}
// Рендерим полноценный PolygonMapObject (он поддерживает и заливку, и обводку)
objects.add(
PolygonMapObject(
mapId: MapObjectId('zone_poly_${zone.type}_${zone.id}_$polyIndex'),
polygon: Polygon(
outerRing: outerRing,
innerRings: innerRings,
),
strokeColor: borderColor,
strokeWidth: 2.0,
fillColor: fillColor,
// Поднимаем зоны ограничений и парковок выше маски и контуров Drive
zIndex: zone.type == "Drive" ? 1 : 2,
),
strokeColor: borderColor,
strokeWidth: 2.0,
zIndex: 1,
),
);
);
polyIndex++;
}
}
return objects;
@@ -684,7 +704,10 @@ class _MapScreenState extends State<MapScreen> {
child: Builder(
builder: (innerContext) => _RoundIconButton(
icon: Icons.menu,
onPressed: () => {Scaffold.of(innerContext).openDrawer()},
onPressed: () {
context.read<MapBloc>().add(FetchProfileData());
Scaffold.of(innerContext).openDrawer();
},
),
),
),