import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:ocarina/api/audio/audioplayer_service.dart'; import 'package:ocarina/api/subsonic/song.dart'; import 'package:ocarina/main.dart'; import 'package:ocarina/util/util.dart'; import 'package:responsive_sizer/responsive_sizer.dart'; import 'package:shimmer/shimmer.dart'; import 'package:text_scroll/text_scroll.dart'; /// The player widget /// /// Showcases the playing song's details and features playback controls class Player extends StatefulWidget { /// The player widget /// /// Showcases the playing song's details and features playback controls const Player({super.key}); @override State createState() => PlayerState(); } /// State of [Player] class PlayerState extends State { void update() { logger.d(AudioPlayerService().song?.coverArtUrl); setState(() {}); } var _showFullControls = false; final _sheetController = DraggableScrollableController(); @override Widget build(BuildContext context) { return NotificationListener( onNotification: (n) { if (n.extent > 0.3) { _showFullControls = true; } else { _showFullControls = false; } setState(() {}); return false; }, child: DraggableScrollableSheet( controller: _sheetController, initialChildSize: 0.1, snap: true, snapSizes: const [0.1, 1], minChildSize: 0.1, builder: (c, s) => SingleChildScrollView( controller: s, child: Column( children: [ AnimatedOpacity( opacity: _showFullControls ? 0 : 1, duration: const Duration(milliseconds: 300), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: GestureDetector( onTap: () { _sheetController.animateTo( (_sheetController.size == 1) ? 0.1 : 1, duration: const Duration(milliseconds: 300), curve: Curves.easeIn, ); }, child: Container( color: Theme.of(context).colorScheme.primaryContainer, height: 10.h, width: 100.w, child: Padding( padding: const EdgeInsets.all(8), child: ValueListenableBuilder( valueListenable: songNotifier, builder: (c, t, w) { return Row( children: [ SizedBox( height: 10.h, width: 10.h, child: Padding( padding: const EdgeInsets.all(8), child: ClipRRect( child: (t == null) ? ColoredBox( color: Theme.of(context) .colorScheme .primaryContainer, child: Center( child: Icon( Icons.music_note, color: Theme.of(context) .colorScheme .onPrimaryContainer, ), ), ) : CachedNetworkImage( cacheKey: t.coverArtId, imageUrl: t.coverArtUrl, placeholder: (c, d) => Shimmer.fromColors( baseColor: Colors.grey.shade300, highlightColor: Colors.grey.shade100, child: Container( color: Colors.grey, ), ), errorWidget: (c, _, __) { logger ..e(_) ..e(__); return ColoredBox( color: Theme.of(context) .colorScheme .primaryContainer, child: Center( child: Icon( Icons.music_note, color: Theme.of(context) .colorScheme .onPrimaryContainer, ), ), ); }, ), ), ), ), const SizedBox( width: 5, ), Expanded( child: AutoSizeText( AudioPlayerService().song == null ? "Nothing" : AudioPlayerService().song!.title, style: TextStyle( color: Theme.of(context) .colorScheme .onPrimaryContainer, fontSize: 14, decoration: TextDecoration.none, ), overflowReplacement: TextScroll( AudioPlayerService().song == null ? "Nothing" : AudioPlayerService().song!.title, ), ), ), SizedBox( width: 35.w, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () { AudioPlayerService().previous(); }, icon: const Icon(Icons.skip_previous), ), IconButton( onPressed: () async { if (AudioPlayerService().song == null) { return; } if (AudioPlayerService().isPlaying) { await AudioPlayerService().pause(); } else { AudioPlayerService().resume(); } setState(() {}); }, icon: AnimatedCrossFade( firstChild: const Icon(Icons.play_arrow), secondChild: const Icon(Icons.pause), crossFadeState: (AudioPlayerService().isPlaying) ? CrossFadeState.showSecond : CrossFadeState.showFirst, duration: const Duration(milliseconds: 300), ), ), IconButton( onPressed: () { AudioPlayerService().next(); }, icon: const Icon(Icons.skip_next), ), ], ), ), ], ); }, ), ), ), ), ), ), SizedBox( height: 90.h, width: 100.w, child: Center( child: Column( children: [ ClipRRect( child: (AudioPlayerService().song == null) ? ColoredBox( color: Theme.of(context) .colorScheme .primaryContainer, child: Center( child: Icon( Icons.music_note, color: Theme.of(context) .colorScheme .onPrimaryContainer, ), ), ) : (CachedNetworkImage( cacheKey: AudioPlayerService().song!.coverArtId, imageUrl: AudioPlayerService().song!.coverArtUrl, placeholder: (c, d) => Shimmer.fromColors( baseColor: Colors.grey.shade300, highlightColor: Colors.grey.shade100, child: Container( color: Colors.grey, ), ), errorWidget: (c, _, __) { logger ..e(_) ..e(__); return ColoredBox( color: Theme.of(context) .colorScheme .primaryContainer, child: Center( child: Icon( Icons.music_note, color: Theme.of(context) .colorScheme .onPrimaryContainer, ), ), ); }, )), ), ], ), ), ), ], ), ), ), ); } }