PlayListNotifier
unknown
dart
3 years ago
8.7 kB
11
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...