new audio player package basic implementaion
This commit is contained in:
parent
2836b6f335
commit
6d55a3cf52
|
|
@ -4,6 +4,8 @@
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
<application
|
<application
|
||||||
android:label="Didvan"
|
android:label="Didvan"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|
@ -12,13 +14,17 @@
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
android:name="com.ryanheise.audioservice.AudioServiceActivity"
|
||||||
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
||||||
|
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
|
|
@ -40,10 +46,16 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<service android:name="com.ryanheise.audioservice.AudioService">
|
||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
<intent-filter>
|
||||||
android:screenOrientation="portrait"
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
</application>
|
</application>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
PODS:
|
PODS:
|
||||||
- audio_session (0.0.1):
|
- assets_audio_player (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- assets_audio_player_web (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- better_player (0.0.1):
|
- better_player (0.0.1):
|
||||||
- Cache (~> 6.0.0)
|
- Cache (~> 6.0.0)
|
||||||
|
|
@ -83,8 +85,6 @@ PODS:
|
||||||
- TOCropViewController (~> 2.6.1)
|
- TOCropViewController (~> 2.6.1)
|
||||||
- image_picker (0.0.1):
|
- image_picker (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- just_audio (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- nanopb (2.30908.0):
|
- nanopb (2.30908.0):
|
||||||
- nanopb/decode (= 2.30908.0)
|
- nanopb/decode (= 2.30908.0)
|
||||||
- nanopb/encode (= 2.30908.0)
|
- nanopb/encode (= 2.30908.0)
|
||||||
|
|
@ -111,15 +111,14 @@ PODS:
|
||||||
- TOCropViewController (2.6.1)
|
- TOCropViewController (2.6.1)
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- video_player_avfoundation (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- wakelock (0.0.1):
|
- wakelock (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- webview_flutter_wkwebview (0.0.1):
|
- webview_flutter_wkwebview (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
- assets_audio_player (from `.symlinks/plugins/assets_audio_player/ios`)
|
||||||
|
- assets_audio_player_web (from `.symlinks/plugins/assets_audio_player_web/ios`)
|
||||||
- better_player (from `.symlinks/plugins/better_player/ios`)
|
- better_player (from `.symlinks/plugins/better_player/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
|
|
@ -128,13 +127,11 @@ DEPENDENCIES:
|
||||||
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
|
- flutter_vibrate (from `.symlinks/plugins/flutter_vibrate/ios`)
|
||||||
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
|
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
|
||||||
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
||||||
- just_audio (from `.symlinks/plugins/just_audio/ios`)
|
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- record (from `.symlinks/plugins/record/ios`)
|
- record (from `.symlinks/plugins/record/ios`)
|
||||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
|
|
||||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
|
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
|
||||||
|
|
||||||
|
|
@ -158,8 +155,10 @@ SPEC REPOS:
|
||||||
- TOCropViewController
|
- TOCropViewController
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
audio_session:
|
assets_audio_player:
|
||||||
:path: ".symlinks/plugins/audio_session/ios"
|
:path: ".symlinks/plugins/assets_audio_player/ios"
|
||||||
|
assets_audio_player_web:
|
||||||
|
:path: ".symlinks/plugins/assets_audio_player_web/ios"
|
||||||
better_player:
|
better_player:
|
||||||
:path: ".symlinks/plugins/better_player/ios"
|
:path: ".symlinks/plugins/better_player/ios"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
|
|
@ -176,8 +175,6 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/image_cropper/ios"
|
:path: ".symlinks/plugins/image_cropper/ios"
|
||||||
image_picker:
|
image_picker:
|
||||||
:path: ".symlinks/plugins/image_picker/ios"
|
:path: ".symlinks/plugins/image_picker/ios"
|
||||||
just_audio:
|
|
||||||
:path: ".symlinks/plugins/just_audio/ios"
|
|
||||||
path_provider_ios:
|
path_provider_ios:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
|
|
@ -188,15 +185,14 @@ EXTERNAL SOURCES:
|
||||||
:path: ".symlinks/plugins/sqflite/ios"
|
:path: ".symlinks/plugins/sqflite/ios"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
video_player_avfoundation:
|
|
||||||
:path: ".symlinks/plugins/video_player_avfoundation/ios"
|
|
||||||
wakelock:
|
wakelock:
|
||||||
:path: ".symlinks/plugins/wakelock/ios"
|
:path: ".symlinks/plugins/wakelock/ios"
|
||||||
webview_flutter_wkwebview:
|
webview_flutter_wkwebview:
|
||||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
|
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
|
assets_audio_player: edee322b9cb625571b830b35872ead1a295fd917
|
||||||
|
assets_audio_player_web: 19826380c44375761aa0b9053665c1e3fbc3b86b
|
||||||
better_player: 2406bfe8175203c7a46fa15f9d778d73b12e1646
|
better_player: 2406bfe8175203c7a46fa15f9d778d73b12e1646
|
||||||
Cache: 4ca7e00363fca5455f26534e5607634c820ffc2d
|
Cache: 4ca7e00363fca5455f26534e5607634c820ffc2d
|
||||||
Firebase: 7e8fe528c161b9271d365217a74c16aaf834578e
|
Firebase: 7e8fe528c161b9271d365217a74c16aaf834578e
|
||||||
|
|
@ -216,7 +212,6 @@ SPEC CHECKSUMS:
|
||||||
HLSCachingReverseProxyServer: 59935e1e0244ad7f3375d75b5ef46e8eb26ab181
|
HLSCachingReverseProxyServer: 59935e1e0244ad7f3375d75b5ef46e8eb26ab181
|
||||||
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
||||||
image_picker: 541dcbb3b9cf32d87eacbd957845d8651d6c62c3
|
image_picker: 541dcbb3b9cf32d87eacbd957845d8651d6c62c3
|
||||||
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
|
|
||||||
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||||
|
|
@ -227,7 +222,6 @@ SPEC CHECKSUMS:
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
||||||
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
|
|
||||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||||
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
|
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@
|
||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>audio</string>
|
||||||
|
</array>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>We need to access to the microphone to record audio file</string>
|
<string>We need to access to the microphone to record audio file</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:didvan/models/settings_data.dart';
|
import 'package:didvan/models/settings_data.dart';
|
||||||
import 'package:didvan/services/media/media.dart';
|
|
||||||
import 'package:didvan/services/storage/storage.dart';
|
import 'package:didvan/services/storage/storage.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
|
|
@ -15,7 +14,6 @@ class AppInitializer {
|
||||||
StorageService.appDocsDir =
|
StorageService.appDocsDir =
|
||||||
(await getApplicationDocumentsDirectory()).path;
|
(await getApplicationDocumentsDirectory()).path;
|
||||||
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
StorageService.appTempsDir = (await getTemporaryDirectory()).path;
|
||||||
MediaService.init();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,15 @@ import 'package:didvan/services/network/request_helper.dart';
|
||||||
import 'package:didvan/services/storage/storage.dart';
|
import 'package:didvan/services/storage/storage.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:just_audio/just_audio.dart';
|
import 'package:assets_audio_player/assets_audio_player.dart';
|
||||||
|
|
||||||
class MediaService {
|
class MediaService {
|
||||||
static final AudioPlayer audioPlayer = AudioPlayer();
|
static final audioPlayer = AssetsAudioPlayer();
|
||||||
static String? audioPlayerTag;
|
static String? audioPlayerTag;
|
||||||
static StudioDetailsData? currentPodcast;
|
static StudioDetailsData? currentPodcast;
|
||||||
static StudioRequestArgs? podcastPlaylistArgs;
|
static StudioRequestArgs? podcastPlaylistArgs;
|
||||||
|
|
||||||
static void init() {
|
static Duration? get duration => audioPlayer.current.value?.audio.duration;
|
||||||
audioPlayer.positionStream.listen((event) {
|
|
||||||
if (audioPlayer.duration != null && audioPlayer.duration! < event) {
|
|
||||||
audioPlayer.stop();
|
|
||||||
audioPlayer.seek(const Duration(seconds: 0));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<void> handleAudioPlayback({
|
static Future<void> handleAudioPlayback({
|
||||||
required dynamic audioSource,
|
required dynamic audioSource,
|
||||||
|
|
@ -37,31 +30,32 @@ class MediaService {
|
||||||
isNetworkAudio = false;
|
isNetworkAudio = false;
|
||||||
}
|
}
|
||||||
if (audioPlayerTag == tag) {
|
if (audioPlayerTag == tag) {
|
||||||
if (audioPlayer.playing) {
|
await audioPlayer.playOrPause();
|
||||||
await audioPlayer.pause();
|
return;
|
||||||
} else {
|
}
|
||||||
await audioPlayer.play();
|
await audioPlayer.stop();
|
||||||
}
|
audioPlayerTag = tag;
|
||||||
} else {
|
if (isNetworkAudio) {
|
||||||
await audioPlayer.stop();
|
await audioPlayer.open(
|
||||||
audioPlayerTag = tag;
|
Audio.network(
|
||||||
if (isNetworkAudio) {
|
|
||||||
await audioPlayer.setUrl(
|
|
||||||
isVoiceMessage
|
isVoiceMessage
|
||||||
? (RequestHelper.baseUrl +
|
? (RequestHelper.baseUrl +
|
||||||
audioSource +
|
audioSource +
|
||||||
'?accessToken=${RequestService.token}')
|
'?accessToken=${RequestService.token}')
|
||||||
: audioSource,
|
: audioSource,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (kIsWeb) {
|
||||||
|
await audioPlayer.open(
|
||||||
|
Audio.network(audioSource!.replaceAll('%3A', ':')),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (kIsWeb) {
|
await audioPlayer.open(Audio.file(audioSource));
|
||||||
await audioPlayer.setUrl(audioSource!.replaceAll('%3A', ':'));
|
|
||||||
} else {
|
|
||||||
await audioPlayer.setFilePath(audioSource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
audioPlayer.play();
|
|
||||||
}
|
}
|
||||||
|
audioPlayer.play();
|
||||||
|
audioPlayer.updateCurrentAudioNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> resetAudioPlayer() async {
|
static Future<void> resetAudioPlayer() async {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class AudioWidget extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<bool>(
|
return StreamBuilder<bool>(
|
||||||
stream: MediaService.audioPlayer.playingStream,
|
stream: MediaService.audioPlayer.isPlaying,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
@ -56,7 +56,7 @@ class _AudioControllerButton extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DidvanIconButton(
|
return DidvanIconButton(
|
||||||
icon: MediaService.audioPlayer.playing == true && _nowPlaying
|
icon: MediaService.audioPlayer.isPlaying.value && _nowPlaying
|
||||||
? DidvanIcons.pause_circle_solid
|
? DidvanIcons.pause_circle_solid
|
||||||
: DidvanIcons.play_circle_solid,
|
: DidvanIcons.play_circle_solid,
|
||||||
color: Theme.of(context).colorScheme.focusedBorder,
|
color: Theme.of(context).colorScheme.focusedBorder,
|
||||||
|
|
|
||||||
|
|
@ -117,12 +117,12 @@ class StudioDetailsState extends CoreProvier {
|
||||||
);
|
);
|
||||||
if (nextStudio != null && !_positionListenerActivated) {
|
if (nextStudio != null && !_positionListenerActivated) {
|
||||||
_positionListenerActivated = true;
|
_positionListenerActivated = true;
|
||||||
MediaService.audioPlayer.positionStream.listen((event) {
|
MediaService.audioPlayer.currentPosition.listen((event) {
|
||||||
if (MediaService.audioPlayerTag?.contains('message') == true) {
|
if (MediaService.audioPlayerTag?.contains('message') == true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final duration = MediaService.audioPlayer.duration ??
|
final duration =
|
||||||
Duration(seconds: studio.duration);
|
MediaService.duration ?? Duration(seconds: studio.duration);
|
||||||
if (event.compareTo(duration) > 0 && nextStudio != null) {
|
if (event.compareTo(duration) > 0 && nextStudio != null) {
|
||||||
if (stopOnPodcastEnds) {
|
if (stopOnPodcastEnds) {
|
||||||
MediaService.resetAudioPlayer();
|
MediaService.resetAudioPlayer();
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,9 @@ class AudioPlayerWidget extends StatelessWidget {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
MediaService.audioPlayer.seek(
|
MediaService.audioPlayer.seek(
|
||||||
Duration(
|
Duration(
|
||||||
seconds:
|
seconds: MediaService.audioPlayer.currentPosition
|
||||||
MediaService.audioPlayer.position.inSeconds +
|
.value.inSeconds +
|
||||||
30,
|
30,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -126,7 +126,7 @@ class AudioPlayerWidget extends StatelessWidget {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: StreamBuilder<bool>(
|
child: StreamBuilder<bool>(
|
||||||
stream: MediaService.audioPlayer.playingStream,
|
stream: MediaService.audioPlayer.isPlaying,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return _PlayPouseAnimatedIcon(
|
return _PlayPouseAnimatedIcon(
|
||||||
audioSource: podcast.link,
|
audioSource: podcast.link,
|
||||||
|
|
@ -149,7 +149,8 @@ class AudioPlayerWidget extends StatelessWidget {
|
||||||
Duration(
|
Duration(
|
||||||
seconds: max(
|
seconds: max(
|
||||||
0,
|
0,
|
||||||
MediaService.audioPlayer.position.inSeconds -
|
MediaService.audioPlayer.currentPosition.value
|
||||||
|
.inSeconds -
|
||||||
10,
|
10,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -254,16 +255,15 @@ class AudioPlayerWidget extends StatelessWidget {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 64),
|
padding: const EdgeInsets.symmetric(horizontal: 64),
|
||||||
child: DidvanButton(
|
child: DidvanButton(
|
||||||
style: state.timerValue ==
|
style: state.timerValue == MediaService.duration?.inMinutes &&
|
||||||
MediaService.audioPlayer.duration?.inMinutes &&
|
|
||||||
state.stopOnPodcastEnds
|
state.stopOnPodcastEnds
|
||||||
? ButtonStyleMode.primary
|
? ButtonStyleMode.primary
|
||||||
: ButtonStyleMode.flat,
|
: ButtonStyleMode.flat,
|
||||||
title: 'پایان پادکست',
|
title: 'پایان پادکست',
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
state.timerValue =
|
state.timerValue = MediaService.duration!.inMinutes -
|
||||||
MediaService.audioPlayer.duration!.inMinutes -
|
MediaService
|
||||||
MediaService.audioPlayer.position.inMinutes;
|
.audioPlayer.currentPosition.value.inMinutes;
|
||||||
await controller.animateTo(
|
await controller.animateTo(
|
||||||
state.timerValue * 10,
|
state.timerValue * 10,
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
|
|
@ -337,7 +337,7 @@ class __PlayPouseAnimatedIconState extends State<_PlayPouseAnimatedIcon>
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleAnimation() {
|
void _handleAnimation() {
|
||||||
if (MediaService.audioPlayer.playing) {
|
if (MediaService.audioPlayer.isPlaying.value) {
|
||||||
_animationController.forward();
|
_animationController.forward();
|
||||||
} else {
|
} else {
|
||||||
_animationController.reverse();
|
_animationController.reverse();
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,10 @@ class AudioSlider extends StatelessWidget {
|
||||||
child: Directionality(
|
child: Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
child: StreamBuilder<Duration>(
|
child: StreamBuilder<Duration>(
|
||||||
stream: _isPlaying ? MediaService.audioPlayer.positionStream : null,
|
stream:
|
||||||
|
_isPlaying && MediaService.audioPlayer.currentPosition.hasValue
|
||||||
|
? MediaService.audioPlayer.currentPosition
|
||||||
|
: null,
|
||||||
builder: (context, snapshot) => ProgressBar(
|
builder: (context, snapshot) => ProgressBar(
|
||||||
thumbColor: Theme.of(context).colorScheme.title,
|
thumbColor: Theme.of(context).colorScheme.title,
|
||||||
progressBarColor: DesignConfig.isDark
|
progressBarColor: DesignConfig.isDark
|
||||||
|
|
@ -34,12 +37,8 @@ class AudioSlider extends StatelessWidget {
|
||||||
: Theme.of(context).colorScheme.primary,
|
: Theme.of(context).colorScheme.primary,
|
||||||
baseBarColor: Theme.of(context).colorScheme.border,
|
baseBarColor: Theme.of(context).colorScheme.border,
|
||||||
bufferedBarColor: Theme.of(context).colorScheme.splash,
|
bufferedBarColor: Theme.of(context).colorScheme.splash,
|
||||||
total: MediaService.audioPlayer.duration ??
|
total: MediaService.duration ?? Duration(seconds: duration ?? 0),
|
||||||
Duration(seconds: duration ?? 0),
|
|
||||||
progress: snapshot.data ?? Duration.zero,
|
progress: snapshot.data ?? Duration.zero,
|
||||||
buffered: _isPlaying
|
|
||||||
? MediaService.audioPlayer.bufferedPosition
|
|
||||||
: Duration.zero,
|
|
||||||
thumbRadius: disableThumb ? 0 : 6,
|
thumbRadius: disableThumb ? 0 : 6,
|
||||||
barHeight: 3,
|
barHeight: 3,
|
||||||
timeLabelTextStyle: TextStyle(
|
timeLabelTextStyle: TextStyle(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:assets_audio_player/assets_audio_player.dart';
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
import 'package:didvan/config/theme_data.dart';
|
import 'package:didvan/config/theme_data.dart';
|
||||||
import 'package:didvan/constants/app_icons.dart';
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
|
|
@ -14,7 +15,6 @@ import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
|
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||||
import 'package:just_audio/just_audio.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class DidvanBNB extends StatelessWidget {
|
class DidvanBNB extends StatelessWidget {
|
||||||
|
|
@ -106,7 +106,7 @@ class _PlayerNavBar extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<bool>(
|
return StreamBuilder<bool>(
|
||||||
stream: MediaService.audioPlayer.playingStream,
|
stream: MediaService.audioPlayer.isPlaying,
|
||||||
builder: (context, snapshot) => GestureDetector(
|
builder: (context, snapshot) => GestureDetector(
|
||||||
onTap: () => MediaService.currentPodcast == null
|
onTap: () => MediaService.currentPodcast == null
|
||||||
? null
|
? null
|
||||||
|
|
@ -195,12 +195,10 @@ class _PlayerNavBar extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
StreamBuilder<PlayerState>(
|
StreamBuilder<PlayingAudio?>(
|
||||||
stream: MediaService.audioPlayer.playerStateStream,
|
stream: MediaService.audioPlayer.onReadyToPlay,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final playerState = MediaService
|
if (snapshot.data == null ||
|
||||||
.audioPlayer.playerState.processingState;
|
|
||||||
if (playerState == ProcessingState.loading ||
|
|
||||||
state.appState == AppState.busy) {
|
state.appState == AppState.busy) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
|
@ -224,8 +222,7 @@ class _PlayerNavBar extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (state.appState != AppState.busy &&
|
if (state.appState != AppState.busy &&
|
||||||
MediaService.audioPlayer.playerState.processingState !=
|
snapshot.data != null)
|
||||||
ProcessingState.loading)
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 12,
|
left: 12,
|
||||||
|
|
|
||||||
42
pubspec.lock
42
pubspec.lock
|
|
@ -1,6 +1,20 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
assets_audio_player:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: assets_audio_player
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.4+1"
|
||||||
|
assets_audio_player_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: assets_audio_player_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.4+1"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -8,13 +22,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.2"
|
version: "2.8.2"
|
||||||
audio_session:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: audio_session
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.6+1"
|
|
||||||
audio_video_progress_bar:
|
audio_video_progress_bar:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -406,27 +413,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.3"
|
version: "0.6.3"
|
||||||
just_audio:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: just_audio
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.9.20"
|
|
||||||
just_audio_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: just_audio_platform_interface
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.0"
|
|
||||||
just_audio_web:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: just_audio_web
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.4.7"
|
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ dependencies:
|
||||||
flutter_vibrate: ^1.3.0
|
flutter_vibrate: ^1.3.0
|
||||||
universal_html: ^2.0.8
|
universal_html: ^2.0.8
|
||||||
record: ^3.0.2
|
record: ^3.0.2
|
||||||
just_audio: ^0.9.18
|
|
||||||
record_web: ^0.2.1
|
record_web: ^0.2.1
|
||||||
persian_datetime_picker: ^2.4.0
|
persian_datetime_picker: ^2.4.0
|
||||||
persian_number_utility: ^1.1.1
|
persian_number_utility: ^1.1.1
|
||||||
|
|
@ -66,6 +65,7 @@ dependencies:
|
||||||
expandable_bottom_sheet: ^1.1.1+1
|
expandable_bottom_sheet: ^1.1.1+1
|
||||||
permission_handler: ^9.2.0
|
permission_handler: ^9.2.0
|
||||||
better_player: ^0.0.81
|
better_player: ^0.0.81
|
||||||
|
assets_audio_player: ^3.0.4+1
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue