Voice Chat Fixes & Audio Player Implementation
							parent
							
								
									fb3b3e8e46
								
							
						
					
					
						commit
						09c401a157
					
				| @ -0,0 +1,189 @@ | ||||
| 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<Duration>? onChanged; | ||||
|   final ValueChanged<Duration>? 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<SeekBar> { | ||||
|   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<double> activationAnimation, | ||||
|     required Animation<double> 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: <Color>[ | ||||
|             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, | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue