offline podcasts + code cleaning + bug fixes
This commit is contained in:
parent
658d74b9ed
commit
9369dffc03
|
|
@ -23,15 +23,13 @@ class MediaService {
|
|||
|
||||
static Future<void> handleAudioPlayback({
|
||||
required dynamic audioSource,
|
||||
required int id,
|
||||
bool? isNetworkAudio,
|
||||
bool isVoiceMessage = true,
|
||||
}) async {
|
||||
bool isNetworkAudio = audioSource.runtimeType == String;
|
||||
String tag;
|
||||
if (isNetworkAudio) {
|
||||
tag = audioSource;
|
||||
} else {
|
||||
tag = audioSource.path;
|
||||
}
|
||||
tag = '${isVoiceMessage ? 'message' : 'podcast'}-$id';
|
||||
isNetworkAudio ??= audioSource.runtimeType == String;
|
||||
if (audioPlayerTag == tag) {
|
||||
if (audioPlayer.playing) {
|
||||
await audioPlayer.pause();
|
||||
|
|
@ -51,10 +49,9 @@ class MediaService {
|
|||
);
|
||||
} else {
|
||||
if (kIsWeb) {
|
||||
await audioPlayer
|
||||
.setUrl(audioSource!.uri.path.replaceAll('%3A', ':'));
|
||||
await audioPlayer.setUrl(audioSource!.replaceAll('%3A', ':'));
|
||||
} else {
|
||||
await audioPlayer.setFilePath(audioSource.path);
|
||||
await audioPlayer.setFilePath(audioSource);
|
||||
}
|
||||
}
|
||||
audioPlayer.play();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:didvan/services/storage/storage.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http_parser/http_parser.dart' as parser;
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
|
@ -164,11 +164,14 @@ class RequestService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> download() async {
|
||||
Permission.manageExternalStorage.request();
|
||||
Future<void> download(String fileName, String subDirectory) async {
|
||||
Permission.storage.request();
|
||||
final response = await http.get(Uri.parse(url));
|
||||
final file = await File('/storage/emulated/0/Download/file.mp3').create();
|
||||
await file.writeAsBytes(response.bodyBytes);
|
||||
StorageService.createFile(
|
||||
bytes: response.bodyBytes,
|
||||
subDirectory: subDirectory,
|
||||
name: fileName,
|
||||
);
|
||||
}
|
||||
|
||||
void _handleResponse(http.Response? response) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
import 'dart:typed_data';
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:universal_html/html.dart';
|
||||
|
||||
|
|
@ -6,6 +9,21 @@ class StorageService {
|
|||
static late String appTempsDir;
|
||||
static const FlutterSecureStorage _storage = FlutterSecureStorage();
|
||||
|
||||
static Future<void> createFile({
|
||||
required Uint8List bytes,
|
||||
required String subDirectory,
|
||||
required String name,
|
||||
}) async {
|
||||
final dir = io.Directory(appDocsDir + '/$subDirectory');
|
||||
if (!await dir.exists()) {
|
||||
await dir.create(recursive: true);
|
||||
}
|
||||
final file = await io.File(
|
||||
appDocsDir + '/$subDirectory/podcast-$name.mp3',
|
||||
).create(recursive: true);
|
||||
await file.writeAsBytes(bytes);
|
||||
}
|
||||
|
||||
static Future<void> setValue({
|
||||
required String key,
|
||||
required dynamic value,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ class _CommentsState extends State<Comments> {
|
|||
child: Stack(
|
||||
children: [
|
||||
DidvanScaffold(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
appBarData: _isPage
|
||||
? AppBarData(
|
||||
|
|
@ -77,6 +78,7 @@ class _CommentsState extends State<Comments> {
|
|||
itemPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||
childCount: state.comments.length,
|
||||
placeholder: const _CommentPlaceholder(),
|
||||
centerEmptyState: _isPage,
|
||||
enableEmptyState: state.comments.isEmpty,
|
||||
emptyState: EmptyState(
|
||||
asset: Assets.emptyChat,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:didvan/models/enums.dart';
|
|||
import 'package:didvan/models/message_data/message_data.dart';
|
||||
import 'package:didvan/models/message_data/radar_attachment.dart';
|
||||
import 'package:didvan/providers/core_provider.dart';
|
||||
import 'package:didvan/services/media/media.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -46,6 +47,7 @@ class DirectState extends CoreProvier {
|
|||
}
|
||||
|
||||
Future<void> startRecording() async {
|
||||
text = null;
|
||||
await _recorder.hasPermission();
|
||||
if (!kIsWeb) {
|
||||
Vibrate.feedback(FeedbackType.medium);
|
||||
|
|
@ -88,6 +90,7 @@ class DirectState extends CoreProvier {
|
|||
|
||||
Future<void> sendMessage() async {
|
||||
if ((text == null || text!.isEmpty) && recordedFile == null) return;
|
||||
MediaService.audioPlayer.stop();
|
||||
messages.insert(
|
||||
0,
|
||||
MessageData(
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/services/media/media.dart';
|
||||
import 'package:didvan/views/home/widgets/audio/audio_slider.dart';
|
||||
import 'package:didvan/views/home/widgets/player_controller_button.dart';
|
||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AudioWidget extends StatelessWidget {
|
||||
final String? audioUrl;
|
||||
final File? audioFile;
|
||||
const AudioWidget({Key? key, this.audioUrl, this.audioFile})
|
||||
: super(key: key);
|
||||
final int id;
|
||||
const AudioWidget({
|
||||
Key? key,
|
||||
this.audioUrl,
|
||||
this.audioFile,
|
||||
required this.id,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -20,12 +27,13 @@ class AudioWidget extends StatelessWidget {
|
|||
children: [
|
||||
Expanded(
|
||||
child: AudioSlider(
|
||||
tag: audioUrl ?? audioFile!.path,
|
||||
tag: 'message-$id',
|
||||
),
|
||||
),
|
||||
AudioControllerButton(
|
||||
_AudioControllerButton(
|
||||
audioFile: audioFile,
|
||||
audioUrl: audioUrl,
|
||||
id: id,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -33,3 +41,33 @@ class AudioWidget extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AudioControllerButton extends StatelessWidget {
|
||||
final String? audioUrl;
|
||||
final File? audioFile;
|
||||
final int id;
|
||||
|
||||
const _AudioControllerButton(
|
||||
{Key? key, this.audioUrl, this.audioFile, required this.id})
|
||||
: super(key: key);
|
||||
|
||||
bool get _nowPlaying => MediaService.audioPlayerTag == 'message-$id';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanIconButton(
|
||||
icon: MediaService.audioPlayer.playing == true && _nowPlaying
|
||||
? DidvanIcons.pause_circle_solid
|
||||
: DidvanIcons.play_circle_solid,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
onPressed: () {
|
||||
MediaService.handleAudioPlayback(
|
||||
audioSource: audioFile?.path ?? audioUrl,
|
||||
id: id,
|
||||
isNetworkAudio: audioFile == null,
|
||||
isVoiceMessage: true,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class Message extends StatelessWidget {
|
|||
AudioWidget(
|
||||
audioFile: message.audioFile,
|
||||
audioUrl: message.audio,
|
||||
id: message.id,
|
||||
),
|
||||
if (message.radar != null) const DidvanDivider(),
|
||||
if (message.radar != null) const SizedBox(height: 4),
|
||||
|
|
|
|||
|
|
@ -211,7 +211,10 @@ class _RecordChecking extends StatelessWidget {
|
|||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: AudioWidget(audioFile: state.recordedFile!),
|
||||
child: AudioWidget(
|
||||
audioFile: state.recordedFile!,
|
||||
id: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
DidvanIconButton(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import 'package:didvan/views/home/studio/studio_details/widgets/studio_details_w
|
|||
import 'package:didvan/views/home/widgets/bookmark_button.dart';
|
||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:io';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/overview_data.dart';
|
||||
|
|
@ -8,6 +9,7 @@ import 'package:didvan/providers/core_provider.dart';
|
|||
import 'package:didvan/services/media/media.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'package:didvan/services/storage/storage.dart';
|
||||
|
||||
class StudioDetailsState extends CoreProvier {
|
||||
late StudioDetailsData studio;
|
||||
|
|
@ -17,6 +19,7 @@ class StudioDetailsState extends CoreProvier {
|
|||
late StudioRequestArgs args;
|
||||
final List<int> relatedQueue = [];
|
||||
bool _positionListenerActivated = false;
|
||||
final List<int> downloadedFileIds = [];
|
||||
|
||||
int _selectedDetailsIndex = 0;
|
||||
Timer? timer;
|
||||
|
|
@ -42,6 +45,7 @@ class StudioDetailsState extends CoreProvier {
|
|||
if (MediaService.currentPodcast?.id == id && this.args.type == 'podcast') {
|
||||
return;
|
||||
}
|
||||
_getDownloadsList();
|
||||
_selectedDetailsIndex = 0;
|
||||
if (isForward != null) {
|
||||
if (isForward) {
|
||||
|
|
@ -87,9 +91,14 @@ class StudioDetailsState extends CoreProvier {
|
|||
if (args.type == 'podcast') {
|
||||
MediaService.currentPodcast = studio;
|
||||
MediaService.podcastPlaylistArgs = args;
|
||||
final downloaded = downloadedFileIds.contains(studio.id);
|
||||
await MediaService.handleAudioPlayback(
|
||||
audioSource: studio.media,
|
||||
audioSource: downloaded
|
||||
? StorageService.appDocsDir + '/podcasts/podcast-${studio.id}.mp3'
|
||||
: studio.media,
|
||||
id: studio.id,
|
||||
isVoiceMessage: false,
|
||||
isNetworkAudio: !downloaded,
|
||||
);
|
||||
if (nextStudio != null && !_positionListenerActivated) {
|
||||
_positionListenerActivated = true;
|
||||
|
|
@ -104,6 +113,25 @@ class StudioDetailsState extends CoreProvier {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _getDownloadsList() async {
|
||||
downloadedFileIds.clear();
|
||||
final dir = Directory(
|
||||
StorageService.appDocsDir + ('/${args.type}s'),
|
||||
);
|
||||
if (!await dir.exists()) {
|
||||
await dir.create();
|
||||
}
|
||||
dir.list(recursive: false).listen(
|
||||
(event) {
|
||||
downloadedFileIds.add(
|
||||
int.parse(
|
||||
event.path.split('/').last.split('-').last.split('.').first,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> getRelatedContents() async {
|
||||
if (studio.relatedContents.isNotEmpty) return;
|
||||
relatedQueue.add(studio.id);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class StudioDetailsWidget extends StatelessWidget {
|
|||
isVideo: _isVideo,
|
||||
onCommentsTabSelected: onCommentsTabSelected ?? () {},
|
||||
),
|
||||
if (state.selectedDetailsIndex != 1) const SizedBox(height: 16),
|
||||
const SizedBox(height: 16),
|
||||
StateHandler<StudioDetailsState>(
|
||||
onRetry: () {},
|
||||
state: state,
|
||||
|
|
@ -93,7 +93,7 @@ class StudioDetailsWidget extends StatelessWidget {
|
|||
child: SizedBox(
|
||||
height: ds.height -
|
||||
ds.width * 9 / 16 -
|
||||
128 -
|
||||
144 -
|
||||
MediaQuery.of(context).padding.top,
|
||||
child: Comments(
|
||||
pageData: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/overview_data.dart';
|
||||
|
|
@ -8,10 +9,12 @@ import 'package:didvan/providers/core_provider.dart';
|
|||
import 'package:didvan/providers/user_provider.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
import 'package:didvan/services/storage/storage.dart';
|
||||
|
||||
class StudioState extends CoreProvier {
|
||||
final List<OverviewData> studios = [];
|
||||
final List<SliderData> sliders = [];
|
||||
final List<int> downloadedFileIds = [];
|
||||
|
||||
String search = '';
|
||||
String lastSearch = '';
|
||||
|
|
@ -29,10 +32,31 @@ class StudioState extends CoreProvier {
|
|||
set videosSelected(bool value) {
|
||||
if (_videosSelected == value) return;
|
||||
_videosSelected = value;
|
||||
selectedSortTypeIndex = 0;
|
||||
_getSliders();
|
||||
getDownloadsList();
|
||||
getStudios(page: page);
|
||||
}
|
||||
|
||||
Future<void> getDownloadsList() async {
|
||||
downloadedFileIds.clear();
|
||||
final dir = Directory(
|
||||
StorageService.appDocsDir + (videosSelected ? '/videos' : '/podcasts'),
|
||||
);
|
||||
if (!await dir.exists()) {
|
||||
await dir.create();
|
||||
}
|
||||
dir.list(recursive: false).listen(
|
||||
(event) {
|
||||
downloadedFileIds.add(
|
||||
int.parse(
|
||||
event.path.split('/').last.split('-').last.split('.').first,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String get order {
|
||||
if (selectedSortTypeIndex == 0 || selectedSortTypeIndex == 1) return 'date';
|
||||
if (selectedSortTypeIndex == 2) return 'view';
|
||||
|
|
@ -56,6 +80,7 @@ class StudioState extends CoreProvier {
|
|||
lastSearch = '';
|
||||
_videosSelected = true;
|
||||
selectedSortTypeIndex = 0;
|
||||
getDownloadsList();
|
||||
Future.delayed(Duration.zero, () {
|
||||
_getSliders();
|
||||
getStudios(page: 1);
|
||||
|
|
@ -94,7 +119,6 @@ class StudioState extends CoreProvier {
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
if (page == 1) {
|
||||
|
|
@ -122,8 +146,9 @@ class StudioState extends CoreProvier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
void download(String url) {
|
||||
Future<void> download(String url, String fileName) async {
|
||||
final service = RequestService(url);
|
||||
service.download();
|
||||
await service.download(fileName, videosSelected ? 'videos' : 'podcasts');
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class AudioPlayerWidget extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: AudioSlider(
|
||||
tag: podcast.media,
|
||||
tag: 'podcast-${podcast.id}',
|
||||
showTimer: true,
|
||||
duration: podcast.duration,
|
||||
),
|
||||
|
|
@ -117,6 +117,7 @@ class AudioPlayerWidget extends StatelessWidget {
|
|||
builder: (context, snapshot) {
|
||||
return _PlayPouseAnimatedIcon(
|
||||
audioSource: podcast.media,
|
||||
id: podcast.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
@ -239,7 +240,9 @@ class AudioPlayerWidget extends StatelessWidget {
|
|||
|
||||
class _PlayPouseAnimatedIcon extends StatefulWidget {
|
||||
final String audioSource;
|
||||
const _PlayPouseAnimatedIcon({Key? key, required this.audioSource})
|
||||
final int id;
|
||||
const _PlayPouseAnimatedIcon(
|
||||
{Key? key, required this.audioSource, required this.id})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -281,6 +284,11 @@ class __PlayPouseAnimatedIconState extends State<_PlayPouseAnimatedIcon>
|
|||
MediaService.handleAudioPlayback(
|
||||
audioSource: widget.audioSource,
|
||||
isVoiceMessage: false,
|
||||
id: widget.id,
|
||||
isNetworkAudio: !context
|
||||
.read<StudioDetailsState>()
|
||||
.downloadedFileIds
|
||||
.contains(widget.id),
|
||||
);
|
||||
_handleAnimation();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class AudioSlider extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IgnorePointer(
|
||||
ignoring: MediaService.audioPlayerTag != tag,
|
||||
ignoring: !_isPlaying,
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: StreamBuilder<Duration>(
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/overview_data.dart';
|
||||
import 'package:didvan/models/requests/studio.dart';
|
||||
import 'package:didvan/utils/date_time.dart';
|
||||
import 'package:didvan/views/home/studio/studio_details/studio_details_state.dart';
|
||||
import 'package:didvan/views/home/studio/studio_state.dart';
|
||||
import 'package:didvan/views/home/widgets/bookmark_button.dart';
|
||||
import 'package:didvan/views/home/widgets/duration_widget.dart';
|
||||
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
|
@ -28,6 +32,7 @@ class PodcastOverview extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = context.read<StudioState>();
|
||||
return DidvanCard(
|
||||
onTap: () {
|
||||
context
|
||||
|
|
@ -75,13 +80,22 @@ class PodcastOverview extends StatelessWidget {
|
|||
children: [
|
||||
DurationWidget(duration: podcast.duration!),
|
||||
const Spacer(),
|
||||
// DidvanIconButton(
|
||||
// gestureSize: 28,
|
||||
// icon: DidvanIcons.download_regular,
|
||||
// onPressed: () =>
|
||||
// context.read<StudioState>().download(podcast.media!),
|
||||
// ),
|
||||
// const SizedBox(width: 16),
|
||||
if (!kIsWeb) ...[
|
||||
DidvanIconButton(
|
||||
gestureSize: 28,
|
||||
color: _isDownloaded(state)
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: null,
|
||||
icon: _isDownloaded(state)
|
||||
? DidvanIcons.download_solid
|
||||
: DidvanIcons.download_regular,
|
||||
onPressed: _isDownloaded(state)
|
||||
? () {}
|
||||
: () =>
|
||||
state.download(podcast.media!, podcast.id.toString()),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
BookmarkButton(
|
||||
askForConfirmation: hasUnmarkConfirmation,
|
||||
gestureSize: 32,
|
||||
|
|
@ -95,6 +109,10 @@ class PodcastOverview extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
bool _isDownloaded(state) {
|
||||
return state.downloadedFileIds.contains(podcast.id);
|
||||
}
|
||||
|
||||
static Widget get placeholder => DidvanCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/services/media/media.dart';
|
||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AudioControllerButton extends StatelessWidget {
|
||||
final String? audioUrl;
|
||||
final File? audioFile;
|
||||
|
||||
const AudioControllerButton({Key? key, this.audioUrl, this.audioFile})
|
||||
: super(key: key);
|
||||
|
||||
bool get _nowPlaying =>
|
||||
MediaService.audioPlayerTag == audioUrl ||
|
||||
audioFile != null && MediaService.audioPlayerTag == audioFile!.path;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanIconButton(
|
||||
icon: MediaService.audioPlayer.playing == true && _nowPlaying
|
||||
? DidvanIcons.pause_circle_solid
|
||||
: DidvanIcons.play_circle_solid,
|
||||
color: Theme.of(context).colorScheme.focusedBorder,
|
||||
onPressed: () {
|
||||
MediaService.handleAudioPlayback(
|
||||
audioSource: audioFile ?? audioUrl,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,10 +24,11 @@ class DidvanBNB extends StatelessWidget {
|
|||
: super(key: key);
|
||||
|
||||
bool get _enablePlayerController =>
|
||||
MediaService.currentPodcast != null || MediaService.audioPlayer.playing;
|
||||
MediaService.currentPodcast != null && MediaService.audioPlayer.playing;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = context.read<StudioDetailsState>();
|
||||
return StreamBuilder<bool>(
|
||||
stream: MediaService.audioPlayer.playingStream,
|
||||
builder: (context, snapshot) {
|
||||
|
|
@ -108,7 +109,8 @@ class DidvanBNB extends StatelessWidget {
|
|||
: DidvanIcons.play_solid,
|
||||
onPressed: () {
|
||||
MediaService.handleAudioPlayback(
|
||||
audioSource: MediaService.audioPlayerTag,
|
||||
audioSource: state.studio.media,
|
||||
id: state.studio.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class DidvanScaffold extends StatefulWidget {
|
|||
final EdgeInsets padding;
|
||||
final Color? backgroundColor;
|
||||
final bool reverse;
|
||||
final ScrollPhysics? physics;
|
||||
final ScrollController? scrollController;
|
||||
final bool showSliversFirst;
|
||||
|
||||
|
|
@ -17,6 +18,7 @@ class DidvanScaffold extends StatefulWidget {
|
|||
this.slivers,
|
||||
required this.appBarData,
|
||||
this.children,
|
||||
this.physics,
|
||||
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
||||
this.backgroundColor,
|
||||
this.reverse = false,
|
||||
|
|
@ -49,6 +51,7 @@ class _DidvanScaffoldState extends State<DidvanScaffold> {
|
|||
child: Stack(
|
||||
children: [
|
||||
CustomScrollView(
|
||||
physics: widget.physics,
|
||||
controller: _scrollController,
|
||||
reverse: widget.reverse,
|
||||
slivers: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue