import 'dart:math'; import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; class SeekBar extends StatefulWidget { final Duration duration; final Duration position; final Duration bufferedPosition; final ValueChanged? onChanged; final ValueChanged? onChangeEnd; const SeekBar({ Key? key, required this.duration, required this.position, required this.bufferedPosition, this.onChanged, this.onChangeEnd, }) : super(key: key); @override SeekBarState createState() => SeekBarState(); } class SeekBarState extends State { double? _dragValue; late SliderThemeData _sliderThemeData; @override void didChangeDependencies() { super.didChangeDependencies(); _sliderThemeData = SliderTheme.of(context).copyWith( // trackHeight: 2.0, thumbColor: MyColors.lightGreenColor, activeTrackColor: MyColors.lightGreenColor, inactiveTrackColor: MyColors.grey57Color.withOpacity(0.4), ); } @override Widget build(BuildContext context) { return Stack( children: [ SliderTheme( data: _sliderThemeData.copyWith( thumbShape: HiddenThumbComponentShape(), ), child: ExcludeSemantics( child: Slider( min: 0.0, max: widget.duration.inMilliseconds.toDouble(), value: min(widget.bufferedPosition.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()), onChanged: (value) { setState(() { _dragValue = value; }); if (widget.onChanged != null) { widget.onChanged!(Duration(milliseconds: value.round())); } }, onChangeEnd: (value) { if (widget.onChangeEnd != null) { widget.onChangeEnd!(Duration(milliseconds: value.round())); } _dragValue = null; }, ), ), ), SliderTheme( data: _sliderThemeData.copyWith( inactiveTrackColor: Colors.transparent, ), child: Slider( min: 0.0, max: widget.duration.inMilliseconds.toDouble(), value: min(_dragValue ?? widget.position.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()), onChanged: (value) { setState(() { _dragValue = value; }); if (widget.onChanged != null) { widget.onChanged!(Duration(milliseconds: value.round())); } }, onChangeEnd: (value) { if (widget.onChangeEnd != null) { widget.onChangeEnd!(Duration(milliseconds: value.round())); } _dragValue = null; }, ), ), ], ); } } class PositionData { final Duration position; final Duration bufferedPosition; final Duration duration; PositionData(this.position, this.bufferedPosition, this.duration); } class HiddenThumbComponentShape extends SliderComponentShape { @override Size getPreferredSize(bool isEnabled, bool isDiscrete) => Size.zero; @override void paint( PaintingContext context, Offset center, { required Animation activationAnimation, required Animation enableAnimation, required bool isDiscrete, required TextPainter labelPainter, required RenderBox parentBox, required SliderThemeData sliderTheme, required TextDirection textDirection, required double value, required double textScaleFactor, required Size sizeWithOverflow, }) {} } class WaveBubble extends StatelessWidget { final PlayerController playerController; final VoidCallback onTap; final bool isPlaying; const WaveBubble({ Key? key, required this.playerController, required this.onTap, required this.isPlaying, }) : super(key: key); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.all(10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), gradient: const LinearGradient( transform: GradientRotation(.83), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ MyColors.gradiantEndColor, MyColors.gradiantStartColor, ], ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( onPressed: onTap, icon: Icon(isPlaying ? Icons.stop : Icons.play_arrow), color: Colors.white, splashColor: Colors.transparent, highlightColor: Colors.transparent, ), AudioFileWaveforms( size: Size(MediaQuery.of(context).size.width / 2, 10), playerController: playerController, padding: EdgeInsets.zero, margin: EdgeInsets.zero, enableSeekGesture: true, // density: 1, playerWaveStyle: const PlayerWaveStyle( fixedWaveColor: Colors.white, liveWaveColor: MyColors.greenColor, showTop: true, showBottom: true, waveCap: StrokeCap.round, seekLineThickness: 2, // visualizerHeight: 4, backgroundColor: Colors.transparent, ), ), ], ), ); } }