D1APP-99 studio progress
This commit is contained in:
parent
5278238e19
commit
628ebbe271
|
|
@ -64,6 +64,9 @@ class RouteGenerator {
|
||||||
ChangeNotifierProvider<StudioState>(
|
ChangeNotifierProvider<StudioState>(
|
||||||
create: (context) => StudioState(),
|
create: (context) => StudioState(),
|
||||||
),
|
),
|
||||||
|
ChangeNotifierProvider<StudioDetailsState>(
|
||||||
|
create: (context) => StudioDetailsState(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: const Home(),
|
child: const Home(),
|
||||||
),
|
),
|
||||||
|
|
@ -103,8 +106,8 @@ class RouteGenerator {
|
||||||
);
|
);
|
||||||
case Routes.studioDetails:
|
case Routes.studioDetails:
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
ChangeNotifierProvider<StudioDetailsState>(
|
ChangeNotifierProvider<StudioDetailsState>.value(
|
||||||
create: (context) => StudioDetailsState(),
|
value: (settings.arguments as Map<String, dynamic>)['state'],
|
||||||
child: StudioDetails(
|
child: StudioDetails(
|
||||||
pageData: settings.arguments as Map<String, dynamic>,
|
pageData: settings.arguments as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:didvan/models/requests/studio.dart';
|
||||||
|
import 'package:didvan/models/studio_details_data.dart';
|
||||||
import 'package:didvan/services/network/request.dart';
|
import 'package:didvan/services/network/request.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
@ -7,8 +9,8 @@ import 'package:just_audio/just_audio.dart';
|
||||||
class MediaService {
|
class MediaService {
|
||||||
static final AudioPlayer audioPlayer = AudioPlayer();
|
static final AudioPlayer audioPlayer = AudioPlayer();
|
||||||
static String? audioPlayerTag;
|
static String? audioPlayerTag;
|
||||||
static String? audioPlayerTitle;
|
static StudioDetailsData? currentPodcast;
|
||||||
static String? audioPlayerCover;
|
static StudioRequestArgs? podcastPlaylistArgs;
|
||||||
|
|
||||||
static void init() {
|
static void init() {
|
||||||
audioPlayer.positionStream.listen((event) {
|
audioPlayer.positionStream.listen((event) {
|
||||||
|
|
@ -21,6 +23,7 @@ class MediaService {
|
||||||
|
|
||||||
static Future<void> handleAudioPlayback({
|
static Future<void> handleAudioPlayback({
|
||||||
required dynamic audioSource,
|
required dynamic audioSource,
|
||||||
|
bool isVoiceMessage = true,
|
||||||
}) async {
|
}) async {
|
||||||
bool isNetworkAudio = audioSource.runtimeType == String;
|
bool isNetworkAudio = audioSource.runtimeType == String;
|
||||||
String tag;
|
String tag;
|
||||||
|
|
@ -40,9 +43,11 @@ class MediaService {
|
||||||
audioPlayerTag = tag;
|
audioPlayerTag = tag;
|
||||||
if (isNetworkAudio) {
|
if (isNetworkAudio) {
|
||||||
await audioPlayer.setUrl(
|
await audioPlayer.setUrl(
|
||||||
RequestHelper.baseUrl +
|
isVoiceMessage
|
||||||
audioSource +
|
? (RequestHelper.baseUrl +
|
||||||
'?accessToken=${RequestService.token}',
|
audioSource +
|
||||||
|
'?accessToken=${RequestService.token}')
|
||||||
|
: audioSource,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
|
|
@ -58,6 +63,8 @@ class MediaService {
|
||||||
|
|
||||||
static Future<void> resetAudioPlayer() async {
|
static Future<void> resetAudioPlayer() async {
|
||||||
audioPlayerTag = null;
|
audioPlayerTag = null;
|
||||||
|
currentPodcast = null;
|
||||||
|
podcastPlaylistArgs = null;
|
||||||
MediaService.audioPlayer.stop();
|
MediaService.audioPlayer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class ActionSheetUtils {
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Container(
|
builder: (context) => Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: data.hasPadding ? const EdgeInsets.all(20) : EdgeInsets.zero,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: const BorderRadius.vertical(
|
borderRadius: const BorderRadius.vertical(
|
||||||
|
|
@ -91,6 +91,7 @@ class ActionSheetUtils {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
const SizedBox(height: 20),
|
||||||
Center(
|
Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 3,
|
height: 3,
|
||||||
|
|
@ -99,23 +100,24 @@ class ActionSheetUtils {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Row(
|
if (data.title != null)
|
||||||
children: [
|
Row(
|
||||||
if (data.titleIcon != null)
|
children: [
|
||||||
Icon(
|
if (data.titleIcon != null)
|
||||||
data.titleIcon,
|
Icon(
|
||||||
|
data.titleIcon,
|
||||||
|
color: data.titleColor ??
|
||||||
|
Theme.of(context).colorScheme.title,
|
||||||
|
),
|
||||||
|
if (data.titleIcon != null) const SizedBox(width: 8),
|
||||||
|
DidvanText(
|
||||||
|
data.title!,
|
||||||
|
style: Theme.of(context).textTheme.subtitle1,
|
||||||
color: data.titleColor ??
|
color: data.titleColor ??
|
||||||
Theme.of(context).colorScheme.title,
|
Theme.of(context).colorScheme.title,
|
||||||
),
|
)
|
||||||
if (data.titleIcon != null) const SizedBox(width: 8),
|
],
|
||||||
DidvanText(
|
),
|
||||||
data.title,
|
|
||||||
style: Theme.of(context).textTheme.subtitle1,
|
|
||||||
color:
|
|
||||||
data.titleColor ?? Theme.of(context).colorScheme.title,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 28),
|
const SizedBox(height: 28),
|
||||||
data.content,
|
data.content,
|
||||||
const SizedBox(height: 28),
|
const SizedBox(height: 28),
|
||||||
|
|
@ -169,30 +171,31 @@ class ActionSheetUtils {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
if (data.title != null)
|
||||||
mainAxisSize: MainAxisSize.min,
|
Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
GestureDetector(
|
children: [
|
||||||
onTap: () => Navigator.of(context).pop(),
|
GestureDetector(
|
||||||
child: Icon(
|
onTap: () => Navigator.of(context).pop(),
|
||||||
data.titleIcon,
|
child: Icon(
|
||||||
size: 20,
|
data.titleIcon,
|
||||||
color: data.titleColor,
|
size: 20,
|
||||||
|
color: data.titleColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
const SizedBox(
|
width: 8,
|
||||||
width: 8,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DidvanText(
|
|
||||||
data.title,
|
|
||||||
style: Theme.of(context).textTheme.headline3,
|
|
||||||
color: data.titleColor,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
],
|
child: DidvanText(
|
||||||
),
|
data.title!,
|
||||||
|
style: Theme.of(context).textTheme.headline3,
|
||||||
|
color: data.titleColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:didvan/services/media/media.dart';
|
import 'package:didvan/services/media/media.dart';
|
||||||
import 'package:didvan/views/home/widgets/audio_slider.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/home/widgets/player_controller_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:didvan/models/tag.dart';
|
import 'package:didvan/models/tag.dart';
|
||||||
import 'package:didvan/models/view/app_bar_data.dart';
|
import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
import 'package:didvan/views/home/hashtag/hashtag_state.dart';
|
import 'package:didvan/views/home/hashtag/hashtag_state.dart';
|
||||||
import 'package:didvan/views/home/widgets/news_overview.dart';
|
import 'package:didvan/views/home/widgets/overview/news.dart';
|
||||||
import 'package:didvan/views/home/widgets/radar_overview.dart';
|
import 'package:didvan/views/home/widgets/overview/radar.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||||
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
|
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ import 'package:didvan/views/home/studio/studio_state.dart';
|
||||||
import 'package:didvan/views/home/studio/widgets/slider.dart';
|
import 'package:didvan/views/home/studio/widgets/slider.dart';
|
||||||
import 'package:didvan/views/home/studio/widgets/tab_bar.dart';
|
import 'package:didvan/views/home/studio/widgets/tab_bar.dart';
|
||||||
import 'package:didvan/views/home/widgets/logo_app_bar.dart';
|
import 'package:didvan/views/home/widgets/logo_app_bar.dart';
|
||||||
import 'package:didvan/views/home/widgets/podcast_overview.dart';
|
import 'package:didvan/views/home/widgets/overview/podcast.dart';
|
||||||
|
import 'package:didvan/views/home/widgets/overview/video.dart';
|
||||||
import 'package:didvan/views/home/widgets/search_field.dart';
|
import 'package:didvan/views/home/widgets/search_field.dart';
|
||||||
import 'package:didvan/views/home/widgets/video_overview.dart';
|
|
||||||
import 'package:didvan/views/widgets/didvan/divider.dart';
|
import 'package:didvan/views/widgets/didvan/divider.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/radial_button.dart';
|
import 'package:didvan/views/widgets/didvan/radial_button.dart';
|
||||||
|
|
@ -25,7 +25,7 @@ class Studio extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StudioState extends State<Studio> {
|
class _StudioState extends State<Studio> {
|
||||||
final FocusNode _focusNode = FocusNode();
|
final _focusNode = FocusNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
@ -119,8 +119,6 @@ class _StudioState extends State<Studio> {
|
||||||
: PodcastOverview(
|
: PodcastOverview(
|
||||||
podcast: state.studios[index],
|
podcast: state.studios[index],
|
||||||
onMarkChanged: state.changeMark,
|
onMarkChanged: state.changeMark,
|
||||||
hasUnmarkConfirmation: false,
|
|
||||||
onCommentsChanged: state.onCommentsChanged,
|
|
||||||
studioRequestArgs: StudioRequestArgs(
|
studioRequestArgs: StudioRequestArgs(
|
||||||
page: state.page,
|
page: state.page,
|
||||||
order: state.order,
|
order: state.order,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:didvan/config/design_config.dart';
|
import 'package:didvan/config/design_config.dart';
|
||||||
|
import 'package:didvan/config/theme_data.dart';
|
||||||
|
import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/models/studio_details_data.dart';
|
import 'package:didvan/models/studio_details_data.dart';
|
||||||
import 'package:didvan/models/view/app_bar_data.dart';
|
import 'package:didvan/models/view/app_bar_data.dart';
|
||||||
|
import 'package:didvan/services/media/media.dart';
|
||||||
import 'package:didvan/views/home/studio/studio_details/studio_details_state.dart';
|
import 'package:didvan/views/home/studio/studio_details/studio_details_state.dart';
|
||||||
import 'package:didvan/views/home/widgets/audio_slider.dart';
|
import 'package:didvan/views/home/widgets/audio/audio_slider.dart';
|
||||||
|
import 'package:didvan/views/home/widgets/bookmark_button.dart';
|
||||||
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
import 'package:didvan/views/widgets/ink_wrapper.dart';
|
||||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -30,15 +36,15 @@ class _StudioDetailsState extends State<StudioDetails> {
|
||||||
double _dwInPortrait = 0;
|
double _dwInPortrait = 0;
|
||||||
double _scaleInPortrait = 1;
|
double _scaleInPortrait = 1;
|
||||||
|
|
||||||
bool get _isVideo => widget.pageData['isVideo'];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
final state = context.read<StudioDetailsState>();
|
final state = context.read<StudioDetailsState>();
|
||||||
|
|
||||||
Future.delayed(
|
Future.delayed(
|
||||||
Duration.zero,
|
Duration.zero,
|
||||||
() => state.getStudioDetails(widget.pageData['id']),
|
() => state.getStudioDetails(widget.pageData['id']),
|
||||||
);
|
);
|
||||||
|
|
||||||
state.args = widget.pageData['args'];
|
state.args = widget.pageData['args'];
|
||||||
if (Platform.isAndroid) WebView.platform = AndroidWebView();
|
if (Platform.isAndroid) WebView.platform = AndroidWebView();
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -96,6 +102,8 @@ class _StudioDetailsState extends State<StudioDetails> {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
child: DidvanScaffold(
|
child: DidvanScaffold(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
appBarData: _isFullScreen
|
appBarData: _isFullScreen
|
||||||
? null
|
? null
|
||||||
: AppBarData(
|
: AppBarData(
|
||||||
|
|
@ -103,15 +111,14 @@ class _StudioDetailsState extends State<StudioDetails> {
|
||||||
title: state.currentStudio.title,
|
title: state.currentStudio.title,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
if (_isVideo)
|
SizedBox(
|
||||||
SizedBox(
|
width: ds.width,
|
||||||
width: ds.width,
|
height: _isFullScreen ? ds.height : ds.width * 9 / 16,
|
||||||
height: _isFullScreen ? ds.height : ds.width * 9 / 16,
|
child: Stack(
|
||||||
child: Stack(
|
children: [
|
||||||
children: [
|
WebView(
|
||||||
WebView(
|
initialUrl: Uri.dataFromString(
|
||||||
initialUrl: Uri.dataFromString(
|
'''
|
||||||
'''
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta
|
<meta
|
||||||
|
|
@ -144,27 +151,25 @@ class _StudioDetailsState extends State<StudioDetails> {
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
''',
|
''',
|
||||||
mimeType: 'text/html',
|
mimeType: 'text/html',
|
||||||
).toString(),
|
).toString(),
|
||||||
javascriptMode: JavascriptMode.unrestricted,
|
javascriptMode: JavascriptMode.unrestricted,
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 42,
|
right: 42,
|
||||||
bottom: 8,
|
bottom: 8,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => _changeFullSceen(!_isFullScreen),
|
onTap: () => _changeFullSceen(!_isFullScreen),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 30,
|
height: 30,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
if (!_isVideo)
|
),
|
||||||
AudioPlayerWidget(podcast: state.currentStudio),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -172,39 +177,3 @@ class _StudioDetailsState extends State<StudioDetails> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AudioPlayerWidget extends StatelessWidget {
|
|
||||||
final StudioDetailsData podcast;
|
|
||||||
const AudioPlayerWidget({Key? key, required this.podcast}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
child: Hero(
|
|
||||||
tag: podcast.media,
|
|
||||||
child: SkeletonImage(
|
|
||||||
imageUrl: podcast.image,
|
|
||||||
aspectRatio: 1 / 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
DidvanText(
|
|
||||||
podcast.title,
|
|
||||||
style: Theme.of(context).textTheme.bodyText1,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: AudioSlider(
|
|
||||||
tag: podcast.media,
|
|
||||||
showTimer: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,14 @@ import 'package:didvan/models/overview_data.dart';
|
||||||
import 'package:didvan/models/requests/studio.dart';
|
import 'package:didvan/models/requests/studio.dart';
|
||||||
import 'package:didvan/models/studio_details_data.dart';
|
import 'package:didvan/models/studio_details_data.dart';
|
||||||
import 'package:didvan/providers/core_provider.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.dart';
|
||||||
import 'package:didvan/services/network/request_helper.dart';
|
import 'package:didvan/services/network/request_helper.dart';
|
||||||
|
|
||||||
class StudioDetailsState extends CoreProvier {
|
class StudioDetailsState extends CoreProvier {
|
||||||
final List<StudioDetailsData?> studios = [];
|
final List<StudioDetailsData?> studios = [];
|
||||||
late Timer _trackingTimer;
|
late int initialIndex;
|
||||||
int _trackingTimerCounter = 0;
|
late StudioRequestArgs args;
|
||||||
late final int initialIndex;
|
|
||||||
late final StudioRequestArgs args;
|
|
||||||
bool isFetchingNewItem = false;
|
bool isFetchingNewItem = false;
|
||||||
final List<int> relatedQueue = [];
|
final List<int> relatedQueue = [];
|
||||||
|
|
||||||
|
|
@ -29,25 +28,36 @@ class StudioDetailsState extends CoreProvier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getStudioDetails(int id, {bool? isForward}) async {
|
Future<void> getStudioDetails(int id,
|
||||||
|
{bool? isForward, StudioRequestArgs? args}) async {
|
||||||
|
if (args != null) {
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
if (isForward == null) {
|
if (isForward == null) {
|
||||||
appState = AppState.busy;
|
appState = AppState.busy;
|
||||||
} else {
|
} else {
|
||||||
isFetchingNewItem = true;
|
isFetchingNewItem = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
final service = RequestService(RequestHelper.studioDetails(id, args));
|
final service = RequestService(RequestHelper.studioDetails(id, this.args));
|
||||||
await service.httpGet();
|
await service.httpGet();
|
||||||
_handleTracking(sendRequest: isForward != null);
|
|
||||||
if (service.isSuccess) {
|
if (service.isSuccess) {
|
||||||
final result = service.result;
|
final result = service.result;
|
||||||
final studio = StudioDetailsData.fromJson(result['studio']);
|
final studio = StudioDetailsData.fromJson(result['studio']);
|
||||||
if (args.page == 0) {
|
if (this.args.page == 0) {
|
||||||
studios.add(studio);
|
studios.add(studio);
|
||||||
initialIndex = 0;
|
initialIndex = 0;
|
||||||
appState = AppState.idle;
|
appState = AppState.idle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.args.type == 'podcast') {
|
||||||
|
MediaService.currentPodcast = studio;
|
||||||
|
MediaService.podcastPlaylistArgs = args;
|
||||||
|
await MediaService.handleAudioPlayback(
|
||||||
|
audioSource: studio.media,
|
||||||
|
isVoiceMessage: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
StudioDetailsData? prevStudio;
|
StudioDetailsData? prevStudio;
|
||||||
if (result['prevStudio'].isNotEmpty) {
|
if (result['prevStudio'].isNotEmpty) {
|
||||||
|
|
@ -121,21 +131,4 @@ class StudioDetailsState extends CoreProvier {
|
||||||
count;
|
count;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleTracking({bool sendRequest = true}) async {
|
|
||||||
if (!sendRequest) {
|
|
||||||
_trackingTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
|
||||||
_trackingTimerCounter++;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//send request
|
|
||||||
_trackingTimerCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_trackingTimer.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
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';
|
||||||
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/services/media/media.dart';
|
import 'package:didvan/services/media/media.dart';
|
||||||
|
import 'package:didvan/utils/action_sheet.dart';
|
||||||
|
import 'package:didvan/views/home/studio/studio_details/studio_details.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/audio/audio_player_widget.dart';
|
||||||
|
import 'package:didvan/views/home/widgets/audio/audio_slider.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
import 'package:didvan/views/widgets/didvan/icon_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
|
import 'package:expandable_bottom_sheet/expandable_bottom_sheet.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class DidvanBNB extends StatelessWidget {
|
class DidvanBNB extends StatelessWidget {
|
||||||
final int currentTabIndex;
|
final int currentTabIndex;
|
||||||
|
|
@ -15,6 +25,9 @@ class DidvanBNB extends StatelessWidget {
|
||||||
{Key? key, required this.currentTabIndex, required this.onTabChanged})
|
{Key? key, required this.currentTabIndex, required this.onTabChanged})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
|
bool get _enablePlayerController =>
|
||||||
|
MediaService.currentPodcast != null || MediaService.audioPlayer.playing;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<bool>(
|
return StreamBuilder<bool>(
|
||||||
|
|
@ -22,29 +35,89 @@ class DidvanBNB extends StatelessWidget {
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
AnimatedContainer(
|
GestureDetector(
|
||||||
duration: DesignConfig.lowAnimationDuration,
|
onTap: () => _showPlayerBottomSheet(context),
|
||||||
height: snapshot.data == true ? 120 : 72,
|
child: AnimatedContainer(
|
||||||
decoration: BoxDecoration(
|
padding: const EdgeInsets.only(top: 12),
|
||||||
color: DesignConfig.isDark
|
duration: DesignConfig.lowAnimationDuration,
|
||||||
? Theme.of(context).colorScheme.focused
|
height: _enablePlayerController ? 120 : 72,
|
||||||
: Theme.of(context).colorScheme.navigation,
|
decoration: BoxDecoration(
|
||||||
borderRadius: const BorderRadius.vertical(
|
color: DesignConfig.isDark
|
||||||
top: Radius.circular(16),
|
? Theme.of(context).colorScheme.focused
|
||||||
),
|
: Theme.of(context).colorScheme.navigation,
|
||||||
),
|
borderRadius: const BorderRadius.vertical(
|
||||||
child: Row(
|
top: Radius.circular(16),
|
||||||
children: [
|
|
||||||
const DidvanIconButton(
|
|
||||||
icon: DidvanIcons.close_regular,
|
|
||||||
gestureSize: 24,
|
|
||||||
onPressed: MediaService.resetAudioPlayer,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
),
|
||||||
if (MediaService.audioPlayerCover != null)
|
child: !_enablePlayerController
|
||||||
SkeletonImage(imageUrl: MediaService.audioPlayerCover!),
|
? const SizedBox()
|
||||||
const SizedBox(width: 16),
|
: SizedBox(
|
||||||
],
|
height: 48,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
right: 12,
|
||||||
|
left: 16,
|
||||||
|
),
|
||||||
|
child: DidvanIconButton(
|
||||||
|
icon: DidvanIcons.close_regular,
|
||||||
|
color: DesignConfig.isDark
|
||||||
|
? null
|
||||||
|
: Theme.of(context).colorScheme.secondCTA,
|
||||||
|
gestureSize: 28,
|
||||||
|
onPressed: MediaService.resetAudioPlayer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SkeletonImage(
|
||||||
|
imageUrl: MediaService.currentPodcast!.image,
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
DidvanText(
|
||||||
|
MediaService.currentPodcast!.title,
|
||||||
|
color: DesignConfig.isDark
|
||||||
|
? null
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.secondCTA,
|
||||||
|
),
|
||||||
|
AudioSlider(
|
||||||
|
disableThumb: true,
|
||||||
|
tag: MediaService.audioPlayerTag!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 12,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
child: DidvanIconButton(
|
||||||
|
gestureSize: 28,
|
||||||
|
color: DesignConfig.isDark
|
||||||
|
? null
|
||||||
|
: Theme.of(context).colorScheme.secondCTA,
|
||||||
|
icon: snapshot.data!
|
||||||
|
? DidvanIcons.pause_solid
|
||||||
|
: DidvanIcons.play_solid,
|
||||||
|
onPressed: () {
|
||||||
|
MediaService.handleAudioPlayback(
|
||||||
|
audioSource: MediaService.audioPlayerTag,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|
@ -105,6 +178,31 @@ class DidvanBNB extends StatelessWidget {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showPlayerBottomSheet(BuildContext context) {
|
||||||
|
final detailsState = context.read<StudioDetailsState>();
|
||||||
|
showModalBottomSheet(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) => ChangeNotifierProvider<StudioDetailsState>.value(
|
||||||
|
value: detailsState,
|
||||||
|
child: ExpandableBottomSheet(
|
||||||
|
background: Container(),
|
||||||
|
persistentHeader: AudioPlayerWidget(
|
||||||
|
podcast: MediaService.currentPodcast!,
|
||||||
|
),
|
||||||
|
expandableContent: Container(
|
||||||
|
height: 300,
|
||||||
|
width: double.infinity,
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const DidvanText('!Under Construction'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NavBarItem extends StatelessWidget {
|
class _NavBarItem extends StatelessWidget {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import 'package:didvan/models/overview_data.dart';
|
||||||
import 'package:didvan/models/requests/studio.dart';
|
import 'package:didvan/models/requests/studio.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/utils/date_time.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/widgets/bookmark_button.dart';
|
import 'package:didvan/views/home/widgets/bookmark_button.dart';
|
||||||
import 'package:didvan/views/home/widgets/duration_widget.dart';
|
import 'package:didvan/views/home/widgets/duration_widget.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/card.dart';
|
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||||
|
|
@ -13,6 +14,7 @@ import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
|
||||||
import 'package:didvan/views/widgets/skeleton_image.dart';
|
import 'package:didvan/views/widgets/skeleton_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class VideoOverview extends StatelessWidget {
|
class VideoOverview extends StatelessWidget {
|
||||||
final OverviewData video;
|
final OverviewData video;
|
||||||
|
|
@ -41,6 +43,7 @@ class VideoOverview extends StatelessWidget {
|
||||||
'args': studioRequestArgs,
|
'args': studioRequestArgs,
|
||||||
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
||||||
'isVideo': true,
|
'isVideo': true,
|
||||||
|
'state': context.read<StudioDetailsState>(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4+1"
|
version: "1.0.4+1"
|
||||||
|
expandable_bottom_sheet:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: expandable_bottom_sheet
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1+1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ dependencies:
|
||||||
firebase_messaging: ^11.2.8
|
firebase_messaging: ^11.2.8
|
||||||
firebase_core: ^1.13.1
|
firebase_core: ^1.13.1
|
||||||
webview_flutter: ^3.0.1
|
webview_flutter: ^3.0.1
|
||||||
|
expandable_bottom_sheet: ^1.1.1+1
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue