PlayListNotifier
unknown
dart
3 years ago
8.7 kB
4
Indexable
import 'dart:async'; import 'dart:developer'; import 'package:audioplayers/audioplayers.dart'; import 'package:base_architecture/data_layer/api/api_provider.dart'; import 'package:base_architecture/data_layer/models/api_models/Dto/add_to_library_dto.dart'; import 'package:base_architecture/presentation/notifiers/book_view_notifier.dart'; import 'package:base_architecture/presentation/pages/main/main_page.dart'; import 'package:card_swiper/card_swiper.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:volume_controller/volume_controller.dart'; class PlayListNotifier extends ChangeNotifier { int? _listIndex = 0; changeIndex(int index) { _listIndex = index; notifyListeners(); } bool isLiked = false; void changeIsLiked() { isLiked = !isLiked; notifyListeners(); } bool _isDrive = false; void setIsDrive() { _isDrive = !isDrive; notifyListeners(); } final SwiperController _swiperController = SwiperController(); // Player related final AudioPlayer _player = AudioPlayer(); AudioPlayer get player => _player; bool _isPlaying = false; Duration _reach50 = Duration(); Duration _reach85 = Duration(); bool _didSetSource = false; bool _setNewSource = false; Duration _currentPosition = const Duration( seconds: 0, minutes: 0, ); Duration _duration = const Duration( seconds: 0, minutes: 0, ); VolumeController _volumeController = VolumeController(); double _volumeListenerValue = 0; double _getVolume = 0; double _setVolumeValue = 0; double _playRate = 1.0; // Player Getters bool get isPlaying => _isPlaying; Duration? get reach50 => _reach50; bool get didSetSource => _didSetSource; Duration get position => _currentPosition; Duration get duration => _duration; VolumeController get volumeController => _volumeController; double get playRate => _playRate; int? get listIndex => _listIndex; Future<void> play(String url) async { if (!didSetSource) { await setSource( url, ); } if (isPlaying) { _player.pause(); _isPlaying = false; } else { _player.resume(); _isPlaying = true; } checkPlayTime(); notifyListeners(); } Future<void> setSource(String source) async { await _player.setSourceUrl( source, ); volumeController.listener((double volume) { _volumeListenerValue = volume; _player.setVolume(_volumeListenerValue); notifyListeners(); }); // await _player.play(UrlSource(source)); Timer.periodic(const Duration(seconds: 1), (Timer timer) async { await _player.getCurrentPosition().then( (Duration? value) { _currentPosition = value!; notifyListeners(); }, ); await _player.getDuration().then( (Duration? value) { _duration = value!; notifyListeners(); }, ); if (_currentPosition == duration) { _isPlaying = false; notifyListeners(); } }); _player.onPlayerComplete.listen((complete) { _isPlaying = false; notifyListeners(); }); _didSetSource = true; notifyListeners(); } void handleSeek(double seconds) { _currentPosition = Duration(seconds: seconds.floor().toInt()); _player.seek(_currentPosition); notifyListeners(); } void pause() { _player.pause(); _isPlaying = false; notifyListeners(); } void resume() { _player.resume(); _isPlaying = true; notifyListeners(); } void getComplete() { _currentPosition = _duration; _isPlaying = false; notifyListeners(); } void disposePlayer() { _player.dispose(); _isPlaying = false; } double? playTime50; bool didLog50 = false; double? playTime85; bool didLog85 = false; void checkPlayTime() async { BookViewNotifier bookViewNotifier = Provider.of<BookViewNotifier>( navigatorKey.currentContext!, listen: false, ); await Future.delayed(Duration(seconds: 2)); playTime50 = (_duration.inSeconds ~/ 2).toDouble(); playTime85 = (_duration.inSeconds * 0.85).toDouble(); if (!bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].isFifty! && !bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].isEightyFive!) {} streamDelayer(_player.onPositionChanged, const Duration(seconds: 1)) .listen((Duration event) async { log('Current::::: ${_currentPosition.inSeconds} 50% equals $playTime50'); if (_currentPosition.inSeconds >= playTime50! && !bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].isFifty!) { bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].isFifty = true; print('reached 50%'); setPlayTime50(); } else if (_currentPosition.inSeconds >= playTime85! && !bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].isEightyFive!) { bookViewNotifier.bookDetails.data!.first.soundFiles![listIndex!] .isEightyFive = true; print('reached 85%'); setPlayTime85(); } }); } setPlayTime50() { // _reach50 = pt; // print(_reach50); BookViewNotifier bookViewNotifier = Provider.of<BookViewNotifier>( navigatorKey.currentContext!, listen: false, ); AddToLibraryDto log50 = AddToLibraryDto( related_id: bookViewNotifier.bookDetails.data!.first.id.toString(), chapter_id: bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].id .toString(), type: 1, percentage: 50, ); log(log50.toJson().toString()); addToLibrary(log50); notifyListeners(); } setPlayTime85() { // _reach85 = pt; // print(_reach85); BookViewNotifier bookViewNotifier = Provider.of<BookViewNotifier>( navigatorKey.currentContext!, listen: false, ); AddToLibraryDto log85 = AddToLibraryDto( related_id: bookViewNotifier.bookDetails.data!.first.id.toString(), chapter_id: bookViewNotifier .bookDetails.data!.first.soundFiles![listIndex!].id .toString(), type: 1, percentage: 85, ); log(log85.toJson().toString()); addToLibrary(log85); notifyListeners(); } void seek(Duration duration) { _player.seek(_currentPosition + duration); bool backward = duration.isNegative; Duration newDuration = _currentPosition + duration; if (backward) { bool lessThanMinimum = _currentPosition.inSeconds < 15; Duration zero = Duration.zero; /// Commented By: Hasan Armoush /// Below we do three steps and it should remain in the same order /// We set the value of [_currentPosition] to a value [zero, newDuration] /// Immediately after setting the value we call the [notifyListener] /// In order to reflect state quickly on the UI /// Since [_player.seek is a future] and we should wait for it if (lessThanMinimum) { _currentPosition = zero; notifyListeners(); _player.seek(zero); } else { _currentPosition = newDuration; notifyListeners(); _player.seek(newDuration); } } else { _currentPosition = newDuration; notifyListeners(); _player.seek(newDuration); } } void setPlayRate(double rate) async { await _player.setPlaybackRate(rate); if (!isPlaying) { await _player.pause(); } _playRate = rate; notifyListeners(); } final List<double> _playerSpeeds = [ 0.50, 0.75, 1.0, 1.5, 1.75, 2.0, ]; final List<String> _playerTimers = [ '15', '30', '45', 'نهاية الفصل', ]; double _playerSpeed = 1.0; String _selectedTimer = ''; double get playerSpeed => _playerSpeed; String get selectedTimer => _selectedTimer; List<double> get playerSpeeds => _playerSpeeds; List<String> get playerTimers => _playerTimers; SwiperController get swiperController => _swiperController; bool get isDrive => _isDrive; setPlayerSpeed(double value) { _playerSpeed = value; notifyListeners(); } setPlayerTimer(String value) { _selectedTimer = value; notifyListeners(); } addToLibrary(AddToLibraryDto param) async { await ApiProvider(httpClient: Dio()).postAudioToLibrary(param); } } extension Player on PlayListNotifier {} Stream<T> streamDelayer<T>(Stream<T> inputStream, Duration delay) async* { await for (final val in inputStream) { yield val; await Future.delayed(delay); } }
Editor is loading...