import 'package:didvan/config/theme_data.dart'; import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:provider/provider.dart'; import '../../../config/design_config.dart'; import '../../../constants/app_icons.dart'; import '../../../models/enums.dart'; import '../../../models/requests/radar.dart'; import '../../../routes/routes.dart'; import '../../../services/media/media.dart'; import '../../../utils/action_sheet.dart'; import '../../podcasts/podcasts_state.dart'; import '../../podcasts/studio_details/studio_details_state.dart'; import '../../podcasts/studio_details/widgets/studio_details_widget.dart'; import '../didvan/icon_button.dart'; import '../didvan/text.dart'; import '../skeleton_image.dart'; import 'audio_player_widget.dart'; import 'audio_slider.dart'; class PlayerNavBar extends StatefulWidget { final bool inHome; const PlayerNavBar({Key? key, required this.inHome}) : super(key: key); @override State createState() => _PlayerNavBarState(); } class _PlayerNavBarState extends State { bool _enablePlayerController(StudioDetailsState state) => MediaService.currentPodcast != null || (MediaService.audioPlayerTag?.contains('podcast') ?? false); @override Widget build(BuildContext context) { return StreamBuilder( stream: MediaService.audioPlayer.playingStream, builder: (context, isPlaying) => GestureDetector( onTap: () => (MediaService.currentPodcast == null && (MediaService.audioPlayerTag ?? '') .split('-')[1] .isNotEmpty) || MediaService.currentPodcast?.description == 'radar' ? Navigator.of(context).pushNamed( Routes.radarDetails, arguments: { 'onMarkChanged': (id, value) {}, 'onCommentsChanged': (id, value) {}, 'id': MediaService.currentPodcast?.id, 'args': const RadarRequestArgs(page: 0), 'hasUnmarkConfirmation': false, }, ) : (MediaService.audioPlayerTag ?? '').split('-')[1].isNotEmpty ? _showPlayerBottomSheet(context) : null, child: Consumer( builder: (context, state, child) => AnimatedContainer( height: widget.inHome ? _enablePlayerController(state) ? 72 + 32 + 32 : 72 : null, duration: DesignConfig.lowAnimationDuration, decoration: BoxDecoration( color: DesignConfig.isDark ? Theme.of(context).colorScheme.focused : Theme.of(context).colorScheme.navigation, borderRadius: BorderRadius.vertical( top: const Radius.circular(16), bottom: widget.inHome ? Radius.zero : const Radius.circular(16)), ), alignment: widget.inHome ? Alignment.topCenter : Alignment.center, child: Builder(builder: (context) { if (!_enablePlayerController(state)) { return const SizedBox(); } if (state.appState == AppState.failed) { Future.delayed(const Duration(seconds: 2), () { MediaService.resetAudioPlayer(); state.update(); // _enablePlayerController(state); }); return Padding( padding: const EdgeInsets.only(top: 18.0), child: DidvanText( 'اتصال اینترنت برقرار نمی‌باشد', color: DesignConfig.isDark ? Theme.of(context).colorScheme.title : Theme.of(context).colorScheme.secondCTA, ), ); } if (MediaService.currentPodcast == null) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16) .copyWith(bottom: widget.inHome ? 72 + 16 : 16), child: Row( children: [ DidvanIconButton( icon: DidvanIcons.close_regular, color: DesignConfig.isDark ? null : Theme.of(context).colorScheme.secondCTA, gestureSize: 28, onPressed: () async { await MediaService.resetAudioPlayer(); }, ), Expanded( child: Center( child: Padding( padding: const EdgeInsets.only(left: 48), child: SpinKitThreeBounce( size: 18, color: DesignConfig.isDark ? Theme.of(context).colorScheme.title : Theme.of(context).colorScheme.secondCTA, ), ), ), ), ], ), ); } return Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ DidvanIconButton( icon: DidvanIcons.close_regular, color: DesignConfig.isDark ? null : Theme.of(context).colorScheme.secondCTA, gestureSize: 28, onPressed: () async { await MediaService.resetAudioPlayer(); // _enablePlayerController(state); // state.update(); }, ), const SizedBox(width: 8), SkeletonImage( imageUrl: MediaService.currentPodcast!.image, width: 32, height: 32, ), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ DidvanText( MediaService.currentPodcast!.title, maxLines: 1, overflow: TextOverflow.ellipsis, color: DesignConfig.isDark ? null : Theme.of(context).colorScheme.secondCTA, ), AudioSlider( disableThumb: true, tag: MediaService.audioPlayerTag!, ), ], ), ), const SizedBox( width: 8, ), // StreamBuilder( // stream: MediaService.audioPlayer.onReadyToPlay, // builder: (context, snapshot) { // if (snapshot.data == null || // state.appState == AppState.busy && // MediaService.currentPodcast?.description != // 'radar') { // return SizedBox( // height: 18, // width: 18, // child: CircularProgressIndicator( // strokeWidth: 2, // color: DesignConfig.isDark // ? Theme.of(context).colorScheme.title // : Theme.of(context).colorScheme.secondCTA, // ), // ); // } // return const SizedBox(); // }, // ), (state.appState != AppState.busy && isPlaying.data != null || MediaService.currentPodcast?.description == 'radar') ? DidvanIconButton( gestureSize: 28, color: DesignConfig.isDark ? null : Theme.of(context).colorScheme.secondCTA, icon: isPlaying.data! ? DidvanIcons.pause_solid : DidvanIcons.play_solid, onPressed: () { if (state.args?.type == 'video') { state.getStudioDetails( MediaService.currentPodcast!.id, args: state.podcastArgs, fetchOnly: true, ); } MediaService.handleAudioPlayback( audioSource: MediaService.currentPodcast!.link, id: MediaService.currentPodcast!.id, isVoiceMessage: false, ); }, ) : SizedBox( height: 18, width: 18, child: CircularProgressIndicator( strokeWidth: 2, color: DesignConfig.isDark ? Theme.of(context).colorScheme.title : Theme.of(context).colorScheme.secondCTA, ), ) ], ), ); }), ), ), ), ); } void _showPlayerBottomSheet(BuildContext context) { final sheetKey = GlobalKey(); bool isExpanded = false; final detailsState = context.read(); if (detailsState.args?.type == 'video') { detailsState.getStudioDetails( MediaService.currentPodcast!.id, args: detailsState.podcastArgs, fetchOnly: true, ); } final state = context.read(); showModalBottomSheet( constraints: BoxConstraints( maxWidth: ActionSheetUtils(context).mediaQueryData.size.width, ), backgroundColor: Colors.transparent, context: context, isScrollControlled: true, builder: (context) => ChangeNotifierProvider.value( value: state, child: Consumer( builder: (context, state, child) => MediaQuery( data: ActionSheetUtils(context).mediaQueryData, child: ExpandableBottomSheet( key: sheetKey, background: Align( alignment: Alignment.bottomCenter, child: Container( height: MediaQuery.of(context).size.height * 0.7, color: Theme.of(context).colorScheme.surface, ), ), persistentHeader: GestureDetector( onVerticalDragUpdate: (details) { if (details.delta.dy > 10) { Navigator.of(context).pop(); } }, child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ AudioPlayerWidget( podcast: MediaService.currentPodcast!, ), Container( width: MediaQuery.of(context).size.width, color: Theme.of(context).colorScheme.surface, child: Column( children: [ DidvanIconButton( size: 32, icon: DidvanIcons.angle_up_regular, onPressed: () { if (!isExpanded) { sheetKey.currentState?.expand(); isExpanded = true; } else { isExpanded = false; sheetKey.currentState?.contract(); } }, ), const SizedBox(height: 16), ], ), ), ], ), ), expandableContent: state.appState == AppState.busy ? Container( height: MediaQuery.of(context).size.height / 2, alignment: Alignment.center, child: SpinKitSpinningLines( color: Theme.of(context).colorScheme.primary, ), ) : StudioDetailsWidget( onMarkChanged: (id, value) => context .read() .changeMark(id, value, true), ), ), ), ), ), ); } }