import 'dart:math'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/studio_details_data.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/details_tab_bar.dart'; import 'package:didvan/views/widgets/overview/multitype.dart'; import 'package:didvan/views/widgets/tag_item.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:didvan/views/widgets/state_handlers/state_handler.dart'; import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; class StudioDetailsWidget extends StatelessWidget { final void Function(int id, bool value) onMarkChanged; const StudioDetailsWidget({ Key? key, required this.onMarkChanged, }) : super(key: key); @override Widget build(BuildContext context) { final ds = MediaQuery.of(context).size; return SafeArea( bottom: true, child: Consumer( builder: (context, state, child) { bool isVideo = state.studio.iframe != null; return Container( height: max( ds.height - ds.width * 9 / 16 - 72 - MediaQuery.of(context).padding.top, 0), color: Theme.of(context).colorScheme.surface, child: Stack( children: [ Positioned( top: 72, left: 0, right: 0, bottom: 0, child: StateHandler( onRetry: () {}, state: state, builder: (context, state) { if (state.selectedDetailsIndex == 0) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Html( key: ValueKey(state.studio.id), data: state.studio.description, onAnchorTap: (href, _, __) => launchUrl(Uri.parse(href!)), style: { '*': Style( direction: TextDirection.rtl, textAlign: TextAlign.right, lineHeight: LineHeight.percent(135), margin: const Margins(), padding: HtmlPaddings.zero, ), }, ), if (state.studio.tags.isNotEmpty) const SizedBox(height: 20), Wrap( spacing: 8, runSpacing: 8, children: [ for (var i = 0; i < state.studio.tags.length; i++) TagItem( tag: state.studio.tags[i], onMarkChanged: (id, value) => _onMarkChanged(id, value, state), type: isVideo ? '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(), ], ), ], ), ); } if (state.selectedDetailsIndex == 1) { return ChangeNotifierProvider( create: (context) => CommentsState(), child: SizedBox( height: ds.height - ds.width * 9 / 16 - 172 - MediaQuery.of(context).padding.top, child: Comments( pageData: { 'id': state.studio.id, 'type': 'studio', 'title': state.studio.title, 'onCommentsChanged': state.onCommentsChanged, 'isPage': false, }, ), ), ); } return Column( children: [ if (state.studio.relatedContents.isEmpty && !state.studio.relatedContentsIsEmpty) for (var i = 0; i < 3; i++) Padding( padding: const EdgeInsets.only( bottom: 8, left: 16, right: 16, ), child: MultitypeOverview.placeholder, ), for (var i = 0; i < state.studio.relatedContents.length; i++) Padding( padding: const EdgeInsets.only( bottom: 8, left: 16, right: 16, ), child: MultitypeOverview( item: state.studio.relatedContents[i], onMarkChanged: (id, value) {}, ), ), ], ); }, ), ), DetailsTabBar( isVideo: isVideo, ), ], ), ); }, ), ); } void _onMarkChanged(id, value, state) { onMarkChanged(id, value); if (state.studio.id == id) { state.studio.marked = value; } else if (state.nextStudio?.id == id) { state.nextStudio!.marked = value; } else if (state.prevStudio?.id == id) { state.prevStudio!.marked = value; } } } class _StudioPreview extends StatelessWidget { final bool isNext; final StudioDetailsData studio; const _StudioPreview({ Key? key, required this.isNext, required this.studio, }) : super(key: key); String get _previewTitle { if (studio.type == 'video') { return 'ویدیو ${isNext ? 'بعدی' : 'قبلی'} '; } return 'پادکست ${isNext ? 'بعدی' : 'قبلی'} '; } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { final state = context.read(); state.getStudioDetails( isNext ? state.nextStudio!.id : state.prevStudio!.id, args: state.args, isForward: isNext, ); }, child: Container( width: 88, height: 216, color: Colors.transparent, child: Column( children: [ SkeletonImage( imageUrl: studio.image, aspectRatio: 1 / 1, ), const SizedBox(height: 8), Icon( isNext ? DidvanIcons.angle_right_regular : DidvanIcons.angle_left_regular, ), const SizedBox(height: 8), DidvanText( _previewTitle, style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), const SizedBox(height: 8), DidvanText( studio.title, maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: Theme.of(context).textTheme.labelSmall, color: Theme.of(context).colorScheme.caption, ), ], ), ), ); } static Widget get placeHolder => const SizedBox( width: 88, height: 216, child: Column( children: [ ShimmerPlaceholder(width: 88, height: 88), SizedBox(height: 8), ShimmerPlaceholder(height: 20, width: 20), SizedBox(height: 16), ShimmerPlaceholder(height: 14, width: 60), SizedBox(height: 16), ShimmerPlaceholder(height: 12, width: double.infinity), SizedBox(height: 8), ShimmerPlaceholder(height: 12, width: 40), ], ), ); }