base rediesign single videocast
This commit is contained in:
parent
fe87fac33d
commit
2da6dc8993
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12 17.7298C11.3 17.7298 10.6 17.4598 10.07 16.9298L3.55002 10.4098C3.26002 10.1198 3.26002 9.63982 3.55002 9.34982C3.84002 9.05982 4.32002 9.05982 4.61002 9.34982L11.13 15.8698C11.61 16.3498 12.39 16.3498 12.87 15.8698L19.39 9.34982C19.68 9.05982 20.16 9.05982 20.45 9.34982C20.74 9.63982 20.74 10.1198 20.45 10.4098L13.93 16.9298C13.4 17.4598 12.7 17.7298 12 17.7298Z" fill="#2196F3"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 500 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M15 19.92L8.48 13.4C7.71 12.63 7.71 11.37 8.48 10.6L15 4.07996" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 284 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M19.9201 15.0499L13.4001 8.52989C12.6301 7.75989 11.3701 7.75989 10.6001 8.52989L4.08008 15.0499" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 318 B |
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="43" height="43" viewBox="0 0 43 43" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="42.5445" height="42.5445" rx="21.2723" fill="black" fill-opacity="0.6"/>
|
||||||
|
<path d="M26.0923 11.2725H16.4523C14.3223 11.2725 12.5923 13.0125 12.5923 15.1325V29.2225C12.5923 31.0225 13.8823 31.7825 15.4623 30.9125L20.3423 28.2025C20.8623 27.9125 21.7023 27.9125 22.2123 28.2025L27.0923 30.9125C28.6723 31.7925 29.9623 31.0325 29.9623 29.2225V15.1325C29.9523 13.0125 28.2223 11.2725 26.0923 11.2725Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 596 B |
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="43" height="43" viewBox="0 0 43 43" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="42.5445" height="42.5445" rx="21.2723" fill="black" fill-opacity="0.6"/>
|
||||||
|
<path d="M26.0987 11.269H16.4459C14.3243 11.269 12.5873 13.006 12.5873 15.1277V29.2222C12.5873 31.0212 13.8776 31.7905 15.4533 30.9095L20.3293 28.1924C20.8504 27.907 21.6941 27.907 22.2028 28.1924L27.0788 30.9095C28.6669 31.778 29.9573 31.0212 29.9573 29.2222V15.1277C29.9573 13.006 28.2203 11.269 26.0987 11.269Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 519 B |
|
|
@ -64,6 +64,7 @@ import 'package:didvan/views/home/statistic/statistic_state.dart';
|
||||||
import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
|
import 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
|
||||||
if (dart.library.io) 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
|
if (dart.library.io) 'package:didvan/views/podcasts/studio_details/studio_details.mobile.dart'
|
||||||
if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart';
|
if (dart.library.html) 'package:didvan/views/podcasts/studio_details/studio_details.web.dart';
|
||||||
|
import 'package:didvan/views/home/media/video_details_page.dart';
|
||||||
import 'package:didvan/views/splash/splash.dart';
|
import 'package:didvan/views/splash/splash.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/views/story_viewer/story_viewer_page.dart';
|
import 'package:didvan/views/story_viewer/story_viewer_page.dart';
|
||||||
|
|
@ -313,6 +314,20 @@ class RouteGenerator {
|
||||||
return _errorRoute(
|
return _errorRoute(
|
||||||
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||||
|
|
||||||
|
case Routes.videoDetails:
|
||||||
|
if (settings.arguments is Map<String, dynamic>) {
|
||||||
|
return _createRoute(
|
||||||
|
ChangeNotifierProvider<StudioDetailsState>(
|
||||||
|
create: (context) => StudioDetailsState(),
|
||||||
|
child: VideoDetailsPage(
|
||||||
|
pageData: settings.arguments as Map<String, dynamic>,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _errorRoute(
|
||||||
|
'Invalid arguments for ${settings.name}: Expected Map<String, dynamic>.');
|
||||||
|
|
||||||
case Routes.statisticDetails:
|
case Routes.statisticDetails:
|
||||||
if (settings.arguments is Map<String, dynamic>) {
|
if (settings.arguments is Map<String, dynamic>) {
|
||||||
return _createRoute(
|
return _createRoute(
|
||||||
|
|
|
||||||
|
|
@ -42,4 +42,5 @@ class Routes {
|
||||||
static const String web = '/web';
|
static const String web = '/web';
|
||||||
static const String storyViewer = '/story-viewer';
|
static const String storyViewer = '/story-viewer';
|
||||||
static const String media = '/media';
|
static const String media = '/media';
|
||||||
|
static const String videoDetails = '/video-details';
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,507 @@
|
||||||
|
// ignore_for_file: use_build_context_synchronously, deprecated_member_use
|
||||||
|
|
||||||
|
import 'package:chewie/chewie.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/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/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 VideoDetailsPage extends StatefulWidget {
|
||||||
|
final Map<String, dynamic> pageData;
|
||||||
|
|
||||||
|
const VideoDetailsPage({Key? key, required this.pageData}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<VideoDetailsPage> createState() => _VideoDetailsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _VideoDetailsPageState extends State<VideoDetailsPage> {
|
||||||
|
int _currentlyPlayingId = 0;
|
||||||
|
VideoPlayerController? _videoPlayerController;
|
||||||
|
ChewieController? _chewieController;
|
||||||
|
bool _isDescriptionExpanded = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
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: 500), () {
|
||||||
|
if (mounted) {
|
||||||
|
state.getRelatedContents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
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',
|
||||||
|
height: 55,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
'lib/assets/icons/arrow-left.svg',
|
||||||
|
color:
|
||||||
|
const Color.fromARGB(255, 102, 102, 102),
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
(_chewieController != null &&
|
||||||
|
_chewieController!.videoPlayerController
|
||||||
|
.value.isInitialized)
|
||||||
|
? Chewie(controller: _chewieController!)
|
||||||
|
: Center(
|
||||||
|
child: Image.asset(
|
||||||
|
Assets.loadingAnimation,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
top: 1,
|
||||||
|
left: 1,
|
||||||
|
child: BookmarkButton(
|
||||||
|
value: state.studio.marked,
|
||||||
|
onMarkChanged: (value) {
|
||||||
|
if (widget.pageData['onMarkChanged'] !=
|
||||||
|
null) {
|
||||||
|
widget.pageData['onMarkChanged'](
|
||||||
|
state.studio.id, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gestureSize: 35,
|
||||||
|
type: 'video',
|
||||||
|
itemId: state.studio.id,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildDescriptionSection(state),
|
||||||
|
_buildRelatedContentSection(state),
|
||||||
|
_buildCommentsSection(state),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDescriptionSection(StudioDetailsState state) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
state.studio.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Color.fromARGB(255, 0, 53, 70)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedSize(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxHeight: _isDescriptionExpanded ? double.infinity : 100.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,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_isDescriptionExpanded = !_isDescriptionExpanded;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
_isDescriptionExpanded
|
||||||
|
? 'lib/assets/icons/arrow-up2.svg'
|
||||||
|
: 'lib/assets/icons/arrow-down.svg',
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
_isDescriptionExpanded ? 'کمتر' : 'بیشتر',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (state.studio.tags.isNotEmpty) const SizedBox(height: 16),
|
||||||
|
if (state.studio.tags.isNotEmpty)
|
||||||
|
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) {
|
||||||
|
if (widget.pageData['onMarkChanged'] != null) {
|
||||||
|
widget.pageData['onMarkChanged'](id, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: 'video',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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 Container(
|
||||||
|
width: double.infinity,
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.05),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFF059669),
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(12),
|
||||||
|
topRight: Radius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: const DidvanText(
|
||||||
|
'نظرات',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 400,
|
||||||
|
child: ChangeNotifierProvider<CommentsState>(
|
||||||
|
create: (context) => CommentsState(),
|
||||||
|
child: Comments(
|
||||||
|
pageData: {
|
||||||
|
'id': state.studio.id,
|
||||||
|
'type': 'studio',
|
||||||
|
'title': state.studio.title,
|
||||||
|
'onCommentsChanged': state.onCommentsChanged,
|
||||||
|
'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: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
"مطالب مرتبط:",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Color.fromARGB(255, 0, 53, 70),
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
debugPrint("Building related content section:");
|
||||||
|
debugPrint(
|
||||||
|
" - relatedContents.length: ${state.studio.relatedContents.length}");
|
||||||
|
debugPrint(
|
||||||
|
" - relatedContentsIsEmpty: ${state.studio.relatedContentsIsEmpty}");
|
||||||
|
debugPrint(" - tags.length: ${state.studio.tags.length}");
|
||||||
|
|
||||||
|
if (state.studio.relatedContents.isNotEmpty) {
|
||||||
|
debugPrint(
|
||||||
|
" - Showing ${state.studio.relatedContents.length} related items");
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
...state.studio.relatedContents
|
||||||
|
.map((item) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
|
child: MultitypeOverview(
|
||||||
|
item: item,
|
||||||
|
onMarkChanged: (id, value) {
|
||||||
|
if (widget.pageData['onMarkChanged'] !=
|
||||||
|
null) {
|
||||||
|
widget.pageData['onMarkChanged'](
|
||||||
|
id, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else if (state.studio.relatedContentsIsEmpty) {
|
||||||
|
debugPrint(" - Showing empty message");
|
||||||
|
return const Padding(
|
||||||
|
padding: EdgeInsets.all(32.0),
|
||||||
|
child: Center(
|
||||||
|
child: DidvanText(
|
||||||
|
'مطالب مرتبطی یافت نشد',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
debugPrint(" - Showing placeholders (loading state)");
|
||||||
|
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() {
|
||||||
|
_videoPlayerController?.dispose();
|
||||||
|
_chewieController?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ class _VideoCastTabPageState extends State<VideoCastTabPage> {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pushNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.studioDetails,
|
Routes.videoDetails,
|
||||||
arguments: {
|
arguments: {
|
||||||
'id': state.studios[_currentFeaturedIndex].id,
|
'id': state.studios[_currentFeaturedIndex].id,
|
||||||
'type': state.studios[_currentFeaturedIndex].type,
|
'type': state.studios[_currentFeaturedIndex].type,
|
||||||
|
|
@ -198,7 +198,7 @@ class _VideoCastTabPageState extends State<VideoCastTabPage> {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pushNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.studioDetails,
|
Routes.videoDetails,
|
||||||
arguments: {
|
arguments: {
|
||||||
'id': videocast.id,
|
'id': videocast.id,
|
||||||
'type': videocast.type,
|
'type': videocast.type,
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class FeaturedVideoCard extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
height: MediaQuery.of(context).size.height * 0.40,
|
height: 380,
|
||||||
margin: const EdgeInsets.all(16),
|
margin: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
|
@ -112,6 +112,7 @@ class FeaturedVideoCard extends StatelessWidget {
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
color: const Color.fromARGB(255, 200, 224, 244),
|
color: const Color.fromARGB(255, 200, 224, 244),
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 18
|
||||||
),
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import 'dart:math';
|
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/enums.dart';
|
||||||
import 'package:didvan/models/studio_details_data.dart';
|
import 'package:didvan/models/studio_details_data.dart';
|
||||||
import 'package:didvan/views/comments/comments.dart';
|
import 'package:didvan/views/comments/comments.dart';
|
||||||
|
|
@ -16,6 +14,8 @@ 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';
|
||||||
import 'package:flutter_html/flutter_html.dart';
|
import 'package:flutter_html/flutter_html.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ class StudioDetailsWidget extends StatelessWidget {
|
||||||
bool isVideo = state.studio.iframe != null;
|
bool isVideo = state.studio.iframe != null;
|
||||||
double topOffset = isVideo
|
double topOffset = isVideo
|
||||||
? ds.width * 9 / 16
|
? ds.width * 9 / 16
|
||||||
: 400; // برای ویدیو aspect ratio، برای پادکست ارتفاع AudioPlayerWidget
|
: 400;
|
||||||
return Container(
|
return Container(
|
||||||
height: max(
|
height: max(
|
||||||
ds.height - topOffset - 72 - MediaQuery.of(context).padding.top,
|
ds.height - topOffset - 72 - MediaQuery.of(context).padding.top,
|
||||||
|
|
@ -101,20 +101,20 @@ class StudioDetailsWidget extends StatelessWidget {
|
||||||
const SizedBox(),
|
const SizedBox(),
|
||||||
if (state.nextStudio != null &&
|
if (state.nextStudio != null &&
|
||||||
state.alongSideState == AppState.idle)
|
state.alongSideState == AppState.idle)
|
||||||
_StudioPreview(
|
StudioPreview(
|
||||||
isNext: true,
|
isNext: true,
|
||||||
studio: state.nextStudio!,
|
studio: state.nextStudio!,
|
||||||
),
|
),
|
||||||
if (state.alongSideState == AppState.busy)
|
if (state.alongSideState == AppState.busy)
|
||||||
_StudioPreview.placeHolder,
|
StudioPreview.placeHolder,
|
||||||
if (state.prevStudio != null &&
|
if (state.prevStudio != null &&
|
||||||
state.alongSideState == AppState.idle)
|
state.alongSideState == AppState.idle)
|
||||||
_StudioPreview(
|
StudioPreview(
|
||||||
isNext: false,
|
isNext: false,
|
||||||
studio: state.prevStudio!,
|
studio: state.prevStudio!,
|
||||||
),
|
),
|
||||||
if (state.alongSideState == AppState.busy)
|
if (state.alongSideState == AppState.busy)
|
||||||
_StudioPreview.placeHolder,
|
StudioPreview.placeHolder,
|
||||||
const SizedBox(),
|
const SizedBox(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -200,10 +200,10 @@ class StudioDetailsWidget extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StudioPreview extends StatelessWidget {
|
class StudioPreview extends StatelessWidget {
|
||||||
final bool isNext;
|
final bool isNext;
|
||||||
final StudioDetailsData studio;
|
final StudioDetailsData studio;
|
||||||
const _StudioPreview({
|
const StudioPreview({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.isNext,
|
required this.isNext,
|
||||||
required this.studio,
|
required this.studio,
|
||||||
|
|
@ -211,11 +211,18 @@ class _StudioPreview extends StatelessWidget {
|
||||||
|
|
||||||
String get _previewTitle {
|
String get _previewTitle {
|
||||||
if (studio.type == 'video') {
|
if (studio.type == 'video') {
|
||||||
return 'ویدیوی ${isNext ? 'بعدی' : 'قبلی'} ';
|
return 'ویدیوکست ${isNext ? 'بعدی' : 'قبلی'} ';
|
||||||
}
|
}
|
||||||
return 'پادکست ${isNext ? 'بعدی' : 'قبلی'} ';
|
return 'پادکست ${isNext ? 'بعدی' : 'قبلی'} ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _formatDuration(int? duration) {
|
||||||
|
if (duration == null) return '';
|
||||||
|
final minutes = duration ~/ 60;
|
||||||
|
final seconds = duration % 60;
|
||||||
|
return '”${seconds.toString().padLeft(2, '0')}:’${minutes.toString().padLeft(2, '0')}';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
|
@ -227,39 +234,95 @@ class _StudioPreview extends StatelessWidget {
|
||||||
isForward: isNext,
|
isForward: isNext,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 88,
|
width: 170,
|
||||||
height: 216,
|
height: 235,
|
||||||
color: Colors.transparent,
|
decoration: BoxDecoration(
|
||||||
child: Column(
|
color: const Color.fromRGBO(235, 235, 235, 1),
|
||||||
children: [
|
borderRadius: BorderRadius.circular(20),
|
||||||
SkeletonImage(
|
boxShadow: [
|
||||||
imageUrl: studio.image,
|
BoxShadow(
|
||||||
aspectRatio: 1 / 1,
|
color: Colors.black.withOpacity(0.05),
|
||||||
),
|
blurRadius: 4,
|
||||||
const SizedBox(height: 8),
|
offset: const Offset(0, 2),
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(6.0),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 17 / 14,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
child: SkeletonImage(
|
||||||
|
imageUrl: studio.image,
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(12, 4, 8, 3),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
DidvanText(
|
||||||
|
_previewTitle,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: const Color.fromARGB(255, 102, 102, 102),
|
||||||
|
fontSize: 12
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
DidvanText(
|
||||||
|
studio.title,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
'lib/assets/icons/clock.svg',
|
||||||
|
color: const Color.fromARGB(255, 102, 102, 102),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
DidvanText(
|
||||||
|
_formatDuration(studio.duration).toPersianDigit(),
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
|
color: const Color.fromARGB(255, 102, 102, 102),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import 'package:didvan/constants/app_icons.dart';
|
||||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/utils/action_sheet.dart';
|
import 'package:didvan/utils/action_sheet.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:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
class BookmarkButton extends StatefulWidget {
|
class BookmarkButton extends StatefulWidget {
|
||||||
final bool value;
|
final bool value;
|
||||||
|
|
@ -15,6 +15,9 @@ class BookmarkButton extends StatefulWidget {
|
||||||
final double gestureSize;
|
final double gestureSize;
|
||||||
final String type;
|
final String type;
|
||||||
final int itemId;
|
final int itemId;
|
||||||
|
final String? svgIconOn;
|
||||||
|
final String? svgIconOff;
|
||||||
|
|
||||||
const BookmarkButton({
|
const BookmarkButton({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
|
@ -24,6 +27,8 @@ class BookmarkButton extends StatefulWidget {
|
||||||
required this.itemId,
|
required this.itemId,
|
||||||
this.askForConfirmation = false,
|
this.askForConfirmation = false,
|
||||||
this.color,
|
this.color,
|
||||||
|
this.svgIconOn,
|
||||||
|
this.svgIconOff,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -45,16 +50,7 @@ class _BookmarkButtonState extends State<BookmarkButton> {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
void _handleTap() async {
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return DidvanIconButton(
|
|
||||||
gestureSize: widget.gestureSize,
|
|
||||||
color: widget.color ??
|
|
||||||
(DesignConfig.isDark || !_value
|
|
||||||
? null
|
|
||||||
: Theme.of(context).colorScheme.primary),
|
|
||||||
icon: _value ? DidvanIcons.bookmark_solid : DidvanIcons.bookmark_regular,
|
|
||||||
onPressed: () async {
|
|
||||||
bool confirm = false;
|
bool confirm = false;
|
||||||
if (widget.askForConfirmation) {
|
if (widget.askForConfirmation) {
|
||||||
await ActionSheetUtils(context).openDialog(
|
await ActionSheetUtils(context).openDialog(
|
||||||
|
|
@ -76,7 +72,27 @@ class _BookmarkButtonState extends State<BookmarkButton> {
|
||||||
widget.onMarkChanged(_value);
|
widget.onMarkChanged(_value);
|
||||||
UserProvider.changeItemMark(widget.type, widget.itemId, _value);
|
UserProvider.changeItemMark(widget.type, widget.itemId, _value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
print("BookmarkButton build - value: $_value");
|
||||||
|
|
||||||
|
return IconButton(
|
||||||
|
iconSize: widget.gestureSize,
|
||||||
|
onPressed: _handleTap,
|
||||||
|
icon: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||||
|
return ScaleTransition(scale: animation, child: child);
|
||||||
},
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
_value ? 'lib/assets/icons/bookmark_on.svg' : 'lib/assets/icons/bookmark_off.svg',
|
||||||
|
key: ValueKey('bookmark_$_value'),
|
||||||
|
width: widget.gestureSize,
|
||||||
|
height: widget.gestureSize,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +35,7 @@ class DidvanIconButton extends StatelessWidget {
|
||||||
size: size,
|
size: size,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,7 @@ import 'package:didvan/models/requests/radar.dart';
|
||||||
import 'package:didvan/models/requests/studio.dart';
|
import 'package:didvan/models/requests/studio.dart';
|
||||||
import 'package:didvan/providers/user.dart';
|
import 'package:didvan/providers/user.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
import 'package:didvan/services/media/media.dart';
|
|
||||||
import 'package:didvan/services/network/request.dart';
|
|
||||||
import 'package:didvan/utils/date_time.dart';
|
import 'package:didvan/utils/date_time.dart';
|
||||||
import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart';
|
|
||||||
import 'package:didvan/views/widgets/bookmark_button.dart';
|
import 'package:didvan/views/widgets/bookmark_button.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/card.dart';
|
import 'package:didvan/views/widgets/didvan/card.dart';
|
||||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||||
|
|
@ -17,10 +14,8 @@ import 'package:didvan/views/widgets/didvan/text_field.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:flutter_svg/svg.dart';
|
||||||
import 'package:persian_number_utility/persian_number_utility.dart';
|
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:didvan/services/app_initalizer.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
class MultitypeOverview extends StatelessWidget {
|
class MultitypeOverview extends StatelessWidget {
|
||||||
final OverviewData item;
|
final OverviewData item;
|
||||||
|
|
@ -64,67 +59,29 @@ class MultitypeOverview extends StatelessWidget {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IconData get _icon {
|
String get _icon {
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'radar':
|
case 'radar':
|
||||||
return DidvanIcons.scanning_light;
|
return 'DidvanIcons.scanning_light';
|
||||||
case 'news':
|
case 'news':
|
||||||
return DidvanIcons.foolad_light;
|
return 'DidvanIcons.foolad_light';
|
||||||
case 'video':
|
case 'video':
|
||||||
return DidvanIcons.video_light;
|
return 'DidvanIcons.video_light';
|
||||||
case 'podcast':
|
case 'podcast':
|
||||||
return DidvanIcons.podcast_light;
|
return 'DidvanIcons.podcast_light';
|
||||||
case 'delphi':
|
case 'delphi':
|
||||||
case 'survey':
|
case 'survey':
|
||||||
return DidvanIcons.saha_light;
|
return 'DidvanIcons.saha_light';
|
||||||
case 'infography':
|
case 'infography':
|
||||||
return DidvanIcons.infography_regular;
|
return 'DidvanIcons.infography_regular';
|
||||||
default:
|
default:
|
||||||
return DidvanIcons.radar_light;
|
return 'DidvanIcons.radar_light';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DidvanCard(
|
return Column(
|
||||||
onTap: () async {
|
|
||||||
if (item.type == 'infography') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (item.type == 'podcast') {
|
|
||||||
final state = context.read<StudioDetailsState>();
|
|
||||||
await state.getStudioDetails(
|
|
||||||
item.id,
|
|
||||||
args: const StudioRequestArgs(page: 0, type: 'podcast'),
|
|
||||||
);
|
|
||||||
MediaService.currentPodcast = state.studio;
|
|
||||||
MediaService.handleAudioPlayback(
|
|
||||||
audioSource: item.link,
|
|
||||||
id: item.id,
|
|
||||||
isNetworkAudio: true,
|
|
||||||
isVoiceMessage: false,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_targetPageRouteName == null && item.link != null) {
|
|
||||||
AppInitializer.openWebLink(
|
|
||||||
context,
|
|
||||||
'${item.link!}?accessToken=${RequestService.token}',
|
|
||||||
mode: LaunchMode.inAppWebView,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
_targetPageRouteName!,
|
|
||||||
arguments: {
|
|
||||||
'onMarkChanged': onMarkChanged,
|
|
||||||
'id': item.id,
|
|
||||||
'args': _targetPageArgs,
|
|
||||||
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|
@ -138,13 +95,13 @@ class MultitypeOverview extends StatelessWidget {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
borderRadius: const BorderRadius.horizontal(
|
borderRadius: const BorderRadius.horizontal(
|
||||||
left: Radius.circular(10),
|
left: Radius.circular(20),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Icon(
|
child: SvgPicture.asset(
|
||||||
_icon,
|
_icon,
|
||||||
color: Theme.of(context).colorScheme.white,
|
color: Theme.of(context).colorScheme.white,
|
||||||
size: 18,
|
height: 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -283,8 +240,9 @@ class MultitypeOverview extends StatelessWidget {
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 10,),
|
||||||
|
Divider(color: Theme.of(context).colorScheme.border),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
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/constants/app_icons.dart';
|
||||||
import 'package:didvan/models/tag.dart';
|
import 'package:didvan/models/tag.dart';
|
||||||
import 'package:didvan/routes/routes.dart';
|
import 'package:didvan/routes/routes.dart';
|
||||||
|
|
@ -35,22 +34,25 @@ class TagItem extends StatelessWidget {
|
||||||
horizontal: 8,
|
horizontal: 8,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: DesignConfig.lowBorderRadius,
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(12),
|
||||||
|
),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Theme.of(context).colorScheme.focusedBorder,
|
color: const Color.fromARGB(255, 184, 184, 184),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
const Icon(
|
||||||
DidvanIcons.hashtag_regular,
|
DidvanIcons.hashtag_regular,
|
||||||
color: Theme.of(context).colorScheme.focusedBorder,
|
color: Color.fromARGB(255, 102, 102, 102),
|
||||||
|
size: 17,
|
||||||
),
|
),
|
||||||
DidvanText(
|
DidvanText(
|
||||||
tag.label,
|
tag.label,
|
||||||
color: Theme.of(context).colorScheme.focusedBorder,
|
color: const Color.fromARGB(255, 102, 102, 102),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue