Update codebase
This commit is contained in:
@@ -10,11 +10,38 @@ import '../../../core/ui/app_drawer.dart';
|
||||
import '../cubit/duty_cubit.dart';
|
||||
import '../cubit/duty_state.dart';
|
||||
import '../data/models/geo_point.dart';
|
||||
import '../data/models/route_info.dart';
|
||||
import 'widgets/active_duty_sheet.dart';
|
||||
import 'widgets/duty_toggle.dart';
|
||||
import 'widgets/offer_sheet.dart';
|
||||
import 'widgets/ride_map.dart';
|
||||
|
||||
/// نصيب الورقة السفلية من ارتفاع الشاشة — مطابق لتطبيق الراكب.
|
||||
const double _sheetFraction = 0.33;
|
||||
|
||||
/// ما تحتاجه الخريطة وحدها — تغيّرُ الرصيد أو الانشغال لا يعيد بناءها.
|
||||
class _MapData {
|
||||
const _MapData({this.me, this.pickup, this.dropoff, this.route, this.target});
|
||||
|
||||
final GeoPoint? me;
|
||||
final GeoPoint? pickup;
|
||||
final GeoPoint? dropoff;
|
||||
final RouteInfo? route;
|
||||
final GeoPoint? target;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is _MapData &&
|
||||
other.me == me &&
|
||||
other.pickup == pickup &&
|
||||
other.dropoff == dropoff &&
|
||||
other.route == route &&
|
||||
other.target == target;
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(me, pickup, dropoff, route, target);
|
||||
}
|
||||
|
||||
/// شاشة السائق: خريطة + مفتاح الاتصال أعلى + ورقة تتبدّل بالمرحلة.
|
||||
class DutyPage extends StatefulWidget {
|
||||
const DutyPage({super.key});
|
||||
@@ -42,9 +69,34 @@ class _DutyPageState extends State<DutyPage> {
|
||||
children: [
|
||||
// الخريطة معزولة عن بقية الحالة: نبضة موقع كل 25 متراً يجب ألّا
|
||||
// تعيد بناء الورقة والمفتاح معها.
|
||||
BlocSelector<DutyCubit, DutyState, GeoPoint?>(
|
||||
selector: (s) => s.myLocation,
|
||||
builder: (context, me) => RideMap(origin: me, cameraTarget: me),
|
||||
//
|
||||
// **مرفوعة عن القاع بالثلث** كما في تطبيق الراكب — الورقة لها
|
||||
// مساحتها ولا تغطّي الخريطة.
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: MediaQuery.sizeOf(context).height * _sheetFraction,
|
||||
child: BlocSelector<DutyCubit, DutyState, _MapData>(
|
||||
selector: (s) => _MapData(
|
||||
me: s.myLocation,
|
||||
pickup: s.trip?.origin,
|
||||
dropoff: s.trip?.destination,
|
||||
route: s.navRoute,
|
||||
target: s.navTarget,
|
||||
),
|
||||
// السائق كان يرى **موقعه وحده**: بلا نقطة الراكب ولا الوجهة
|
||||
// ولا خط يقوده. الخريطة الآن تعرض ما تعرضه خريطة الراكب:
|
||||
// نقطتَي الرحلة والمسار الحيّ إلى الهدف الحالي.
|
||||
builder: (context, d) => RideMap(
|
||||
origin: d.pickup ?? d.me,
|
||||
destination: d.dropoff,
|
||||
driver: d.pickup == null ? null : d.me,
|
||||
route: d.route,
|
||||
// الكاميرا تتبع الهدف حين يوجد، وإلا فموقع السائق.
|
||||
cameraTarget: d.target ?? d.me,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SafeArea(
|
||||
@@ -83,7 +135,7 @@ class _DutyPageState extends State<DutyPage> {
|
||||
selector: (s) => s.creditBlocked,
|
||||
builder: (context, blocked) => blocked
|
||||
? StatusBanner(
|
||||
message: context.l10n.errorGeneric,
|
||||
message: context.l10n.creditBlocked,
|
||||
tone: BannerTone.danger,
|
||||
icon: Icons.account_balance_wallet_outlined,
|
||||
)
|
||||
@@ -132,13 +184,21 @@ class _Sheet extends StatelessWidget {
|
||||
),
|
||||
DutyPhase.offered => OfferSheet(offer: state.offer!),
|
||||
DutyPhase.active =>
|
||||
ActiveDutySheet(trip: state.trip!, busy: state.busy),
|
||||
ActiveDutySheet(
|
||||
trip: state.trip!,
|
||||
busy: state.busy,
|
||||
navRoute: state.navRoute,
|
||||
),
|
||||
};
|
||||
|
||||
if (state.phase == DutyPhase.offline) return const SizedBox.shrink();
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
// الحدّ الأدنى = المساحة المحجوزة تحت الخريطة، وإلا ظهر فراغ بينهما.
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.sizeOf(context).height * _sheetFraction,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: context.colors.surface,
|
||||
borderRadius: Radii.sheetTop,
|
||||
|
||||
Reference in New Issue
Block a user