import 'dart:async'; import 'dart:developer'; import 'dart:ffi'; import 'package:wanisdriver/utils/colors.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wanisdriver/config/AppSnackbar.dart'; import 'package:wanisdriver/widgets/RideStatusWidget/EndWidget.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../Provider/RideProvider.dart'; import '../Provider/RideStatusProvider.dart' show RideStatusProvider, rideprovidersiglton; import '../Provider/driver_provider.dart'; import '../Provider/utils_singleton.dart'; import '../Screen/CancelRideDialog.dart'; import '../config/enum/ride_enum.dart'; import '../models/RideUpdateRequest.dart'; import '../services/PubNubDriverManager.dart'; import 'RideStatusWidget/CompleteWidget.dart'; import 'RideStatusWidget/DriverArrivedWidget.dart'; import 'RideStatusWidget/ToClientWidget.dart'; class CardTripInfo extends StatefulWidget { final String duration; final String clientname; final String distance; final String userimageurl; final String driverphonenumber; final double price; final RideEnum rideStatus; final bool havestops; final bool isfinaldist; final ValueChanged onchangestate; final VoidCallback onCancel; const CardTripInfo({ Key? key, required this.duration, required this.clientname, required this.distance, required this.userimageurl, required this.driverphonenumber, required this.rideStatus, required this.price, required this.havestops, required this.isfinaldist, required this.onchangestate, required this.onCancel, }) : super(key: key); @override _CardTripInfoState createState() => _CardTripInfoState(); } class _CardTripInfoState extends State { late StreamSubscription _netSub; bool _hasInternet = true; late RideStatusProvider? _rideStatusProvider; late bool _isprocessingToClinet = false; late RideProvider _rideProvider; bool _isLocalLoading = false; @override void initState() { super.initState(); _rideStatusProvider = context.read(); _rideProvider = context.read(); // whenever provider’s loading flag flips off, clear our local spinner _rideProvider.addListener(_syncLocalLoading); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().startCountdown(); _listenToFlutterConnectivity(); }); } void _syncLocalLoading() { if (_isLocalLoading && !_rideProvider.isChangeStatusLoading) { if (!mounted) return; setState(() => _isLocalLoading = false); } } void _listenToFlutterConnectivity() { _netSub = Connectivity().onConnectivityChanged.listen((dynamic event) { // `event` might already be a ConnectivityResult, or a List List results; if (event is List) { results = event; } else if (event is ConnectivityResult) { results = [event]; } else { // unexpected type, assume offline results = [ConnectivityResult.none]; } final nowOnline = results.any((r) => r != ConnectivityResult.none); if (nowOnline != _hasInternet) { setState(() => _hasInternet = nowOnline); if (nowOnline) { _onBackOnline(); } else { AppSnackbar.showInfo("No Connection", "You’re offline — actions are disabled until you reconnect."); } } }); } Future _onBackOnline() async { log("ride id 02-------"); final rideProvider = context.read(); if(rideProvider.currentride != null) { log("ride id -------"); await rideProvider.finbyidWithUpdate(rideProvider.currentride!.id); }else{ log("currentride null !! no need for finbyid"); } setState(() {}); AppSnackbar.showSuccess( "Back Online", "You’ve reconnected to the internet!"); // restart PubNub (or any other service you paused) final pubnub = context.read(); pubnub.connect(uuid: utils.user!.username!); } @override void didUpdateWidget(covariant CardTripInfo oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.rideStatus != widget.rideStatus) { WidgetsBinding.instance.addPostFrameCallback((_) { context.read().startCountdown(); }); } } @override void dispose() { _rideStatusProvider?.cancelCountdown(); _rideProvider.removeListener(_syncLocalLoading); _netSub.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final rideProvider = context.watch(); final rideStatusProvider = context.watch(); Widget currentWidget; log("######################################## ${widget.rideStatus}"); switch (widget.rideStatus) { case RideEnum.to_client: currentWidget = ToClientWidget( duration: widget.duration, clientname: widget.clientname, driverphonenumber: widget.driverphonenumber, distance: widget.distance, userimageurl: widget.userimageurl, canChangeState: rideStatusProvider.canChangeState, isChangeStatusLoading: _isprocessingToClinet || rideProvider.isChangeStatusLoading, remainingSeconds: rideStatusProvider.remainingSecondsToGoNextStep, onCancel: widget.onCancel, onchangestate: () { if (!_hasInternet) { AppSnackbar.showWarning("Internet Connection", "Connection lost. Ensure you’re online before continuing."); return; } if (!rideStatusProvider.canChangeState) return; // set your local loader immediately setState(() { _isprocessingToClinet = true; }); widget.onchangestate(RideEnum.driver_arrived); if (!mounted) return; setState(() => _isprocessingToClinet = false); }, ); break; case RideEnum.driver_arrived: currentWidget = DriverArrivedWidget( duration: widget.duration, driverphonenumber: widget.driverphonenumber, clientname: widget.clientname, distance: widget.distance, canChangeState: rideStatusProvider.canChangeState, remainingSeconds: rideStatusProvider.remainingSecondsToGoNextStep, isChangeStatusLoading: _isprocessingToClinet || rideProvider.isChangeStatusLoading, onCancel: widget.onCancel, onchangestate: () { if (!_hasInternet) { AppSnackbar.showWarning("Internet Connection", "Connection lost. Ensure you’re online before continuing."); return; } if (!rideStatusProvider.canChangeState) return; setState(() { _isprocessingToClinet = true; }); widget.onchangestate(RideEnum.start_ride); if (!mounted) return; setState(() => _isprocessingToClinet = false); }, ); break; case RideEnum.start_ride || RideEnum.stop: currentWidget = CompleteWidget( duration: widget.duration, clientname: widget.clientname, price: widget.price, havestops: widget.havestops || !widget.isfinaldist, canChangeState: rideStatusProvider.canChangeState, remainingSeconds: rideStatusProvider.remainingSecondsToGoNextStep, isChangeStatusLoading: _isprocessingToClinet || rideProvider.isChangeStatusLoading, onchangestate: () { if (!_hasInternet) { AppSnackbar.showWarning("Internet Connection", "Connection lost. Ensure you’re online before continuing."); return; } if (!rideStatusProvider.canChangeState) return; setState(() { _isprocessingToClinet = true; }); if (widget.havestops || !widget.isfinaldist) { widget.onchangestate(RideEnum.stop); } else { widget.onchangestate(RideEnum.rate_client); } if (!mounted) return; setState(() => _isprocessingToClinet = false); }, ); break; default: currentWidget = const EndWidget(); break; } return LayoutBuilder( builder: (context, constraints) { return Container( height: 230.sp, margin: const EdgeInsets.all(0.0), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), decoration: BoxDecoration( color:Theme.of(context).brightness == Brightness.dark? AppColors.blackBackgroundColor: AppColors.whiteBackgroundColor, borderRadius: const BorderRadius.only( topLeft: Radius.circular(30.0), topRight: Radius.circular(30.0), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8.0, offset: const Offset(0, 4), ), ], ), child: currentWidget, ); }, ); } }