973 lines
39 KiB
Dart
973 lines
39 KiB
Dart
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
|
|
|
|
import 'package:chewie/chewie.dart';
|
|
import 'package:didvan/config/design_config.dart';
|
|
|
|
import 'package:didvan/config/theme_data.dart';
|
|
import 'package:didvan/constants/assets.dart';
|
|
import 'package:didvan/models/enums.dart';
|
|
import 'package:didvan/models/studio_details_data.dart';
|
|
import 'package:didvan/providers/user.dart';
|
|
import 'package:didvan/routes/routes.dart';
|
|
import 'package:didvan/services/media/media.dart';
|
|
import 'package:didvan/views/comments/comments.dart';
|
|
import 'package:didvan/views/comments/comments_state.dart';
|
|
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
|
|
import 'package:didvan/views/podcasts/studio_details/widgets/studio_details_widget.dart';
|
|
import 'package:didvan/views/widgets/bookmark_button.dart';
|
|
import 'package:didvan/views/widgets/audio/audio_player_widget.dart';
|
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
|
import 'package:didvan/views/widgets/overview/multitype.dart';
|
|
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
|
import 'package:didvan/views/widgets/tag_item.dart';
|
|
import 'package:didvan/views/widgets/video/primary_controls.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_html/flutter_html.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:url_launcher/url_launcher_string.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
class StudioDetails extends StatefulWidget {
|
|
final Map<String, dynamic> pageData;
|
|
|
|
const StudioDetails({Key? key, required this.pageData}) : super(key: key);
|
|
|
|
@override
|
|
State<StudioDetails> createState() => _StudioDetailsState();
|
|
}
|
|
|
|
class _StudioDetailsState extends State<StudioDetails>
|
|
with TickerProviderStateMixin, WidgetsBindingObserver {
|
|
int _currentlyPlayingId = 0;
|
|
VideoPlayerController? _videoPlayerController;
|
|
ChewieController? _chewieController;
|
|
bool _isDescriptionExpanded = false;
|
|
final _focusNode = FocusNode();
|
|
|
|
late AnimationController _mainAnimationController;
|
|
late Animation<double> _fadeAnimation;
|
|
late Animation<Offset> _slideAnimation;
|
|
|
|
late AnimationController _playerAnimationController;
|
|
late Animation<double> _playerScaleAnimation;
|
|
late Animation<double> _playerFadeAnimation;
|
|
|
|
late AnimationController _titleAnimationController;
|
|
late Animation<Offset> _titleSlideAnimation;
|
|
late Animation<double> _titleFadeAnimation;
|
|
|
|
late AnimationController _tagsAnimationController;
|
|
late Animation<double> _tagsFadeAnimation;
|
|
|
|
late AnimationController _bookmarkAnimationController;
|
|
late Animation<double> _bookmarkScaleAnimation;
|
|
late Animation<double> _bookmarkRotationAnimation;
|
|
|
|
final GlobalKey<AnimatedListState> _relatedContentKey =
|
|
GlobalKey<AnimatedListState>();
|
|
final GlobalKey<AnimatedListState> _commentsKey =
|
|
GlobalKey<AnimatedListState>();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_mainAnimationController = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 800),
|
|
);
|
|
|
|
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _mainAnimationController,
|
|
curve: const Interval(0.0, 0.5, curve: Curves.easeIn),
|
|
),
|
|
);
|
|
|
|
_slideAnimation =
|
|
Tween<Offset>(begin: const Offset(0, 0.3), end: Offset.zero).animate(
|
|
CurvedAnimation(
|
|
parent: _mainAnimationController,
|
|
curve: const Interval(0.0, 0.6, curve: Curves.easeOutCubic),
|
|
),
|
|
);
|
|
|
|
_playerAnimationController = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 1000),
|
|
);
|
|
|
|
_playerScaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _playerAnimationController,
|
|
curve: Curves.elasticOut,
|
|
),
|
|
);
|
|
|
|
_playerFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _playerAnimationController,
|
|
curve: const Interval(0.0, 0.5, curve: Curves.easeIn),
|
|
),
|
|
);
|
|
|
|
_titleAnimationController = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 800),
|
|
);
|
|
|
|
_titleSlideAnimation =
|
|
Tween<Offset>(begin: const Offset(-0.3, 0), end: Offset.zero).animate(
|
|
CurvedAnimation(
|
|
parent: _titleAnimationController,
|
|
curve: Curves.easeOutBack,
|
|
),
|
|
);
|
|
|
|
_titleFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _titleAnimationController,
|
|
curve: Curves.easeIn,
|
|
),
|
|
);
|
|
|
|
_tagsAnimationController = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 600),
|
|
);
|
|
|
|
_tagsFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _tagsAnimationController,
|
|
curve: Curves.easeIn,
|
|
),
|
|
);
|
|
|
|
_bookmarkAnimationController = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 600),
|
|
);
|
|
|
|
_bookmarkScaleAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
|
CurvedAnimation(
|
|
parent: _bookmarkAnimationController,
|
|
curve: Curves.elasticOut,
|
|
),
|
|
);
|
|
|
|
_bookmarkRotationAnimation = Tween<double>(begin: -0.5, end: 0.0).animate(
|
|
CurvedAnimation(
|
|
parent: _bookmarkAnimationController,
|
|
curve: Curves.easeOut,
|
|
),
|
|
);
|
|
|
|
final state = context.read<StudioDetailsState>();
|
|
state.args = widget.pageData['args'];
|
|
|
|
Future.delayed(
|
|
Duration.zero,
|
|
() => state.getStudioDetails(widget.pageData['id']).then((_) {
|
|
if (mounted) {
|
|
_initializePlayer(state.studio);
|
|
Future.delayed(const Duration(milliseconds: 300), () {
|
|
if (mounted) {
|
|
state.getRelatedContents();
|
|
_mainAnimationController.forward();
|
|
Future.delayed(const Duration(milliseconds: 200), () {
|
|
if (mounted) {
|
|
_playerAnimationController.forward();
|
|
}
|
|
});
|
|
Future.delayed(const Duration(milliseconds: 400), () {
|
|
if (mounted) {
|
|
_titleAnimationController.forward();
|
|
}
|
|
});
|
|
Future.delayed(const Duration(milliseconds: 600), () {
|
|
if (mounted) {
|
|
_tagsAnimationController.forward();
|
|
}
|
|
});
|
|
Future.delayed(const Duration(milliseconds: 800), () {
|
|
if (mounted) {
|
|
_bookmarkAnimationController.forward();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
WidgetsBinding.instance.addObserver(this);
|
|
}
|
|
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
super.didChangeAppLifecycleState(state);
|
|
if (state == AppLifecycleState.paused ||
|
|
state == AppLifecycleState.inactive) {
|
|
_stopPodcast();
|
|
}
|
|
}
|
|
|
|
void _stopPodcast() {
|
|
if (MediaService.audioPlayer.playing) {
|
|
MediaService.audioPlayer.stop();
|
|
}
|
|
MediaService.currentPodcast = null;
|
|
MediaService.audioPlayerTag = null;
|
|
}
|
|
|
|
Future<void> _initializePlayer(StudioDetailsData studio) async {
|
|
if (studio.type == 'video') {
|
|
_videoPlayerController?.dispose();
|
|
_chewieController?.dispose();
|
|
|
|
debugPrint("Playing video from URL: ${studio.link}");
|
|
_videoPlayerController = VideoPlayerController.network(studio.link);
|
|
|
|
try {
|
|
await _videoPlayerController!.initialize();
|
|
if (mounted) {
|
|
setState(() {
|
|
_chewieController = ChewieController(
|
|
videoPlayerController: _videoPlayerController!,
|
|
customControls: const PrimaryControls(),
|
|
autoPlay: true,
|
|
looping: true,
|
|
aspectRatio: 16 / 9,
|
|
materialProgressColors: ChewieProgressColors(
|
|
playedColor: Theme.of(context).colorScheme.title,
|
|
handleColor: Theme.of(context).colorScheme.title,
|
|
),
|
|
);
|
|
_currentlyPlayingId = studio.id;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
debugPrint("Error initializing video player: $e");
|
|
}
|
|
} else if (studio.type == 'podcast') {
|
|
await MediaService.handleAudioPlayback(
|
|
audioSource: studio.link,
|
|
id: studio.id,
|
|
isVoiceMessage: false,
|
|
);
|
|
if (mounted) {
|
|
setState(() {
|
|
_currentlyPlayingId = studio.id;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Consumer<StudioDetailsState>(
|
|
builder: (context, state, child) {
|
|
if (state.isStudioLoaded && _currentlyPlayingId != state.studio.id) {
|
|
Future.microtask(() => _initializePlayer(state.studio));
|
|
}
|
|
|
|
return StateHandler<StudioDetailsState>(
|
|
state: state,
|
|
onRetry: () {
|
|
try {
|
|
state.getStudioDetails(state.studio.id);
|
|
} catch (e) {
|
|
state.getStudioDetails(widget.pageData['id']);
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
if (!state.isStudioLoaded) {
|
|
return Scaffold(
|
|
body: Center(
|
|
child: Image.asset(
|
|
Assets.loadingAnimation,
|
|
width: 100,
|
|
height: 100,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return WillPopScope(
|
|
onWillPop: () async {
|
|
if (MediaService.currentPodcast != null) {
|
|
state.studio = MediaService.currentPodcast!;
|
|
}
|
|
state.handleTracking(id: state.studio.id);
|
|
return true;
|
|
},
|
|
child: Scaffold(
|
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
appBar: PreferredSize(
|
|
preferredSize: const Size.fromHeight(90.0),
|
|
child: AppBar(
|
|
scrolledUnderElevation: 0,
|
|
surfaceTintColor: Colors.transparent,
|
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
elevation: 0,
|
|
automaticallyImplyLeading: false,
|
|
flexibleSpace: SafeArea(
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16.0, vertical: 8.0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Center(
|
|
child: SvgPicture.asset(
|
|
'lib/assets/images/logos/logo-horizontal-light.svg',
|
|
color: DesignConfig.isDark
|
|
? Theme.of(context).colorScheme.caption
|
|
: null,
|
|
height: 55,
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: SvgPicture.asset(
|
|
'lib/assets/icons/arrow-left.svg',
|
|
color: Theme.of(context).colorScheme.caption,
|
|
height: 24,
|
|
),
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
)),
|
|
body: SingleChildScrollView(
|
|
child: FadeTransition(
|
|
opacity: _fadeAnimation,
|
|
child: SlideTransition(
|
|
position: _slideAnimation,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Hero(
|
|
tag: 'media-${state.studio.id}',
|
|
child: FadeTransition(
|
|
opacity: _playerFadeAnimation,
|
|
child: ScaleTransition(
|
|
scale: _playerScaleAnimation,
|
|
child: Stack(
|
|
children: [
|
|
if (state.studio.type == 'video')
|
|
AspectRatio(
|
|
aspectRatio: 16 / 9,
|
|
child: (_chewieController != null &&
|
|
_chewieController!
|
|
.videoPlayerController
|
|
.value
|
|
.isInitialized)
|
|
? Chewie(
|
|
controller: _chewieController!)
|
|
: Center(
|
|
child: Image.asset(
|
|
Assets.loadingAnimation,
|
|
width: 100,
|
|
height: 100,
|
|
),
|
|
),
|
|
),
|
|
if (state.studio.type == 'podcast')
|
|
AudioPlayerWidget(podcast: state.studio),
|
|
Positioned(
|
|
top: 1,
|
|
left: 1,
|
|
child: ScaleTransition(
|
|
scale: _bookmarkScaleAnimation,
|
|
child: RotationTransition(
|
|
turns: _bookmarkRotationAnimation,
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
height: 36,
|
|
decoration: BoxDecoration(
|
|
color: Colors.black
|
|
.withOpacity(0.6),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: IconButton(
|
|
icon: SvgPicture.asset(
|
|
'lib/assets/icons/fluent_mention-32-regular.svg',
|
|
width: 28,
|
|
height: 28,
|
|
),
|
|
onPressed: () =>
|
|
Navigator.of(context)
|
|
.pushNamed(
|
|
Routes.mentions,
|
|
arguments: {
|
|
'id': state.studio.id,
|
|
'type': 'studio',
|
|
'title':
|
|
state.studio.title,
|
|
},
|
|
),
|
|
),
|
|
),
|
|
BookmarkButton(
|
|
value: state.studio.marked,
|
|
onMarkChanged: (value) {
|
|
if (widget.pageData[
|
|
'onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData[
|
|
'onMarkChanged'](
|
|
state.studio.id,
|
|
value,
|
|
true);
|
|
}
|
|
},
|
|
gestureSize: 35,
|
|
type:
|
|
state.studio.type == 'video'
|
|
? 'video'
|
|
: 'podcast',
|
|
itemId: state.studio.id,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
_buildDescriptionSection(state),
|
|
_buildRelatedContentSection(state),
|
|
_buildCommentsSection(state),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _buildDescriptionSection(StudioDetailsState state) {
|
|
return AnimatedSwitcher(
|
|
duration: const Duration(milliseconds: 500),
|
|
child: KeyedSubtree(
|
|
key: ValueKey('description-${state.studio.id}'),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SlideTransition(
|
|
position: _titleSlideAnimation,
|
|
child: FadeTransition(
|
|
opacity: _titleFadeAnimation,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(
|
|
state.studio.title,
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.bold,
|
|
color: DesignConfig.isDark
|
|
? const Color.fromARGB(255, 0, 90, 119)
|
|
: const Color.fromARGB(255, 0, 53, 70)),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.vertical(
|
|
bottom:
|
|
Radius.circular(_isDescriptionExpanded ? 0 : 16.0),
|
|
),
|
|
boxShadow: _isDescriptionExpanded
|
|
? null
|
|
: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: 8.0,
|
|
spreadRadius: -2.0,
|
|
offset: const Offset(0, 6),
|
|
),
|
|
],
|
|
),
|
|
child: Stack(
|
|
alignment: Alignment.bottomCenter,
|
|
children: [
|
|
AnimatedSize(
|
|
duration: const Duration(milliseconds: 300),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.vertical(
|
|
bottom: Radius.circular(
|
|
_isDescriptionExpanded ? 0 : 16.0),
|
|
top: Radius.circular(
|
|
_isDescriptionExpanded ? 0 : 16.0),
|
|
),
|
|
child: Container(
|
|
color: Theme.of(context).colorScheme.surface,
|
|
child: ConstrainedBox(
|
|
constraints: BoxConstraints(
|
|
maxHeight: _isDescriptionExpanded
|
|
? double.infinity
|
|
: 140.0,
|
|
),
|
|
child: Html(
|
|
key: ValueKey(state.studio.id),
|
|
data: state.studio.description,
|
|
onAnchorTap: (href, _, __) =>
|
|
launchUrlString(href!),
|
|
style: {
|
|
'*': Style(
|
|
direction: TextDirection.rtl,
|
|
textAlign: TextAlign.right,
|
|
lineHeight: LineHeight.percent(135),
|
|
margin: const Margins(),
|
|
padding: HtmlPaddings.zero,
|
|
color: const Color.fromARGB(
|
|
255, 102, 102, 102),
|
|
fontWeight: FontWeight.normal,
|
|
),
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
child: AnimatedOpacity(
|
|
duration: const Duration(milliseconds: 300),
|
|
opacity: _isDescriptionExpanded ? 0.0 : 1.0,
|
|
child: Container(
|
|
height: 50,
|
|
decoration: BoxDecoration(
|
|
borderRadius: const BorderRadius.vertical(
|
|
bottom: Radius.circular(16.0),
|
|
top: Radius.circular(16.0),
|
|
),
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.surface
|
|
.withOpacity(0.5),
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.surface
|
|
.withOpacity(0.9),
|
|
],
|
|
stops: const [0.0, 0.5],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Transform.translate(
|
|
offset: const Offset(0, -14.0),
|
|
child: InkWell(
|
|
onTap: () {
|
|
setState(() {
|
|
_isDescriptionExpanded = !_isDescriptionExpanded;
|
|
});
|
|
},
|
|
child: Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(5.0),
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).colorScheme.focused,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: SvgPicture.asset(
|
|
_isDescriptionExpanded
|
|
? 'lib/assets/icons/arrow-up2.svg'
|
|
: 'lib/assets/icons/arrow-down.svg',
|
|
color: Theme.of(context).primaryColor,
|
|
height: 25,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (state.studio.tags.isNotEmpty) const SizedBox(height: 16),
|
|
if (state.studio.tags.isNotEmpty)
|
|
FadeTransition(
|
|
opacity: _tagsFadeAnimation,
|
|
child: Wrap(
|
|
spacing: 8,
|
|
runSpacing: 8,
|
|
children: [
|
|
for (var i = 0; i < state.studio.tags.length; i++)
|
|
TweenAnimationBuilder<double>(
|
|
tween: Tween(begin: 0.0, end: 1.0),
|
|
duration: Duration(milliseconds: 400 + (i * 100)),
|
|
curve: Curves.easeOutBack,
|
|
builder: (context, value, child) {
|
|
return Transform.scale(
|
|
scale: value,
|
|
child: Opacity(
|
|
opacity: value,
|
|
child: child,
|
|
),
|
|
);
|
|
},
|
|
child: TagItem(
|
|
tag: state.studio.tags[i],
|
|
onMarkChanged: (id, value) {
|
|
if (widget.pageData['onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData['onMarkChanged'](
|
|
id, value, true);
|
|
}
|
|
},
|
|
type: state.studio.type == 'video'
|
|
? 'video'
|
|
: 'podcast',
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
const SizedBox(),
|
|
if (state.nextStudio != null &&
|
|
state.alongSideState == AppState.idle)
|
|
StudioPreview(
|
|
isNext: true,
|
|
studio: state.nextStudio!,
|
|
),
|
|
if (state.alongSideState == AppState.busy)
|
|
StudioPreview.placeHolder,
|
|
if (state.prevStudio != null &&
|
|
state.alongSideState == AppState.idle)
|
|
StudioPreview(
|
|
isNext: false,
|
|
studio: state.prevStudio!,
|
|
),
|
|
if (state.alongSideState == AppState.busy)
|
|
StudioPreview.placeHolder,
|
|
const SizedBox(),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildCommentsSection(StudioDetailsState state) {
|
|
return ChangeNotifierProvider<CommentsState>(
|
|
create: (context) => CommentsState()
|
|
..itemId = state.studio.id
|
|
..type = 'studio'
|
|
..onCommentsChanged = state.onCommentsChanged
|
|
..getComments(),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Container(
|
|
width: double.infinity,
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Consumer<UserProvider>(
|
|
builder: (context, userProvider, child) {
|
|
final user = userProvider.user;
|
|
final hasProfileImage =
|
|
user.photo != null && user.photo!.isNotEmpty;
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// CircleAvatar(
|
|
// radius: 20,
|
|
// backgroundColor: DesignConfig.isDark
|
|
// ? Colors.transparent
|
|
// : Colors.white,
|
|
// backgroundImage:
|
|
// hasProfileImage ? NetworkImage(user.photo!) : null,
|
|
// child: !hasProfileImage
|
|
// ? Icon(
|
|
// DidvanIcons.avatar_light,
|
|
// size: 50,
|
|
// color: DesignConfig.isDark
|
|
// ? Colors.white
|
|
// : Colors.black,
|
|
// )
|
|
// : null,
|
|
// ),
|
|
// const SizedBox(width: 8),
|
|
Expanded(
|
|
child: CommentMessageBox(focusNode: _focusNode),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
SizedBox(height: state.studio.comments == 0 ? 0 : 16),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: state.studio.comments == 0
|
|
? const SizedBox(
|
|
height: 0,
|
|
)
|
|
: DidvanText(
|
|
'نظرات کاربران:',
|
|
style: TextStyle(
|
|
color: DesignConfig.isDark
|
|
? const Color.fromARGB(255, 0, 90, 119)
|
|
: const Color.fromARGB(255, 0, 53, 70),
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
state.studio.comments == 0
|
|
? const Padding(
|
|
padding: EdgeInsets.all(32.0),
|
|
child: SizedBox(
|
|
height: 5,
|
|
))
|
|
: SizedBox(
|
|
height: 500,
|
|
child: Comments(
|
|
key: _commentsKey,
|
|
pageData: const {'isPage': false},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildRelatedContentSection(StudioDetailsState state) {
|
|
debugPrint("تعداد مطالب مرتبط: ${state.studio.relatedContents.length}");
|
|
debugPrint(
|
|
"آیا لیست مطالب مرتبط خالی است؟ ${state.studio.relatedContentsIsEmpty}");
|
|
debugPrint("تعداد tags: ${state.studio.tags.length}");
|
|
|
|
return Container(
|
|
width: double.infinity,
|
|
margin: const EdgeInsets.all(8),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(
|
|
"مطالب مرتبط:",
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
color: DesignConfig.isDark
|
|
? const Color.fromARGB(255, 0, 90, 119)
|
|
: const Color.fromARGB(255, 0, 53, 70),
|
|
fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Builder(
|
|
builder: (context) {
|
|
if (state.studio.relatedContents.isNotEmpty) {
|
|
return AnimatedList(
|
|
key: _relatedContentKey,
|
|
initialItemCount: state.studio.relatedContents.length,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemBuilder: (context, index, animation) {
|
|
final item = state.studio.relatedContents[index];
|
|
return FadeTransition(
|
|
opacity: animation,
|
|
child: SlideTransition(
|
|
position: Tween<Offset>(
|
|
begin: const Offset(0, 0.2),
|
|
end: Offset.zero,
|
|
).animate(animation),
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: InkWell(
|
|
borderRadius: BorderRadius.circular(12),
|
|
onTap: () {
|
|
_stopPodcast();
|
|
|
|
String routeName;
|
|
Map<String, dynamic> arguments;
|
|
|
|
if (item.type == 'video') {
|
|
routeName = Routes.videoDetails;
|
|
arguments = {
|
|
'id': item.id,
|
|
'type': item.type,
|
|
'onMarkChanged': (int id, bool value) {
|
|
if (widget.pageData['onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData['onMarkChanged'](
|
|
id, value, true);
|
|
}
|
|
},
|
|
};
|
|
} else if (item.type == 'podcast') {
|
|
routeName = Routes.studioDetails;
|
|
arguments = {
|
|
'id': item.id,
|
|
'type': item.type,
|
|
'onMarkChanged': (int id, bool value,
|
|
[bool shouldUpdate = true]) {
|
|
if (widget.pageData['onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData['onMarkChanged'](
|
|
id, value, shouldUpdate);
|
|
}
|
|
},
|
|
};
|
|
} else if (item.type == 'news') {
|
|
routeName = Routes.newsDetails;
|
|
arguments = {
|
|
'id': item.id,
|
|
};
|
|
} else if (item.type == 'radar') {
|
|
routeName = Routes.radarDetails;
|
|
arguments = {
|
|
'id': item.id,
|
|
};
|
|
} else {
|
|
routeName = Routes.studioDetails;
|
|
arguments = {
|
|
'id': item.id,
|
|
'type': item.type,
|
|
'onMarkChanged': (int id, bool value,
|
|
[bool shouldUpdate = true]) {
|
|
if (widget.pageData['onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData['onMarkChanged'](
|
|
id, value, shouldUpdate);
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
Navigator.pushNamed(
|
|
context,
|
|
routeName,
|
|
arguments: arguments,
|
|
);
|
|
},
|
|
child: MultitypeOverview(
|
|
item: item,
|
|
onMarkChanged: (id, value) {
|
|
if (widget.pageData['onMarkChanged'] !=
|
|
null) {
|
|
widget.pageData['onMarkChanged'](
|
|
id, value, true);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
} else if (state.studio.relatedContentsIsEmpty) {
|
|
return const Padding(
|
|
padding: EdgeInsets.all(32.0),
|
|
child: Center(
|
|
child: DidvanText(
|
|
'مطالب مرتبطی یافت نشد',
|
|
style: TextStyle(
|
|
color: Colors.grey,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
} else {
|
|
return Column(
|
|
children: [
|
|
const Padding(
|
|
padding: EdgeInsets.all(8.0),
|
|
child: Text(
|
|
'در حال بارگذاری مطالب مرتبط...',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
),
|
|
...List.generate(
|
|
3,
|
|
(index) => Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: MultitypeOverview.placeholder,
|
|
)),
|
|
],
|
|
);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
|
|
_stopPodcast();
|
|
|
|
_mainAnimationController.dispose();
|
|
_playerAnimationController.dispose();
|
|
_titleAnimationController.dispose();
|
|
_tagsAnimationController.dispose();
|
|
_bookmarkAnimationController.dispose();
|
|
|
|
_videoPlayerController?.dispose();
|
|
_chewieController?.dispose();
|
|
_focusNode.dispose();
|
|
super.dispose();
|
|
}
|
|
}
|