complate videocast tab

This commit is contained in:
mohamadmahdi jebeli 2025-10-13 09:48:00 +03:30
parent 37767c912d
commit fe87fac33d
4 changed files with 159 additions and 19 deletions

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 7H21" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M6 12H18" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
<path d="M10 17H14" stroke="#292D32" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 343 B

View File

@ -84,9 +84,10 @@ class _MediaPageState extends State<MediaPage> {
});
},
children: [
const PodcastTabPage(),
const VideoCastTabPage(),
const PodcastTabPage(key: ValueKey('PodcastTabPage')),
const VideoCastTabPage(key: ValueKey('VideoCastTabPage')),
const SingleChildScrollView(
key: ValueKey('MainPageBanner'),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0, vertical: 16.0),
@ -94,6 +95,7 @@ class _MediaPageState extends State<MediaPage> {
),
),
Center(
key: const ValueKey('InfographyPage'),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/home/media/widgets/featured_video_card.dart';
import 'package:didvan/views/home/media/widgets/videocast_grid_card.dart';
@ -5,7 +6,9 @@ import 'package:didvan/views/podcasts/podcasts_state.dart';
import 'package:didvan/views/widgets/overview/podcast.dart';
import 'package:didvan/views/widgets/state_handlers/empty_result.dart';
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
import 'package:didvan/views/widgets/item_title.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
class VideoCastTabPage extends StatefulWidget {
@ -16,6 +19,9 @@ class VideoCastTabPage extends StatefulWidget {
}
class _VideoCastTabPageState extends State<VideoCastTabPage> {
int _currentFeaturedIndex = 0;
Timer? _rotationTimer;
@override
void initState() {
super.initState();
@ -25,6 +31,75 @@ class _VideoCastTabPageState extends State<VideoCastTabPage> {
});
}
void _startRotation() {
_rotationTimer?.cancel();
_rotationTimer = Timer.periodic(const Duration(seconds: 5), (timer) {
final state = context.read<PodcastsState>();
if (state.studios.isNotEmpty && mounted) {
setState(() {
_currentFeaturedIndex =
(_currentFeaturedIndex + 1) % state.studios.length;
});
}
});
}
void _showSortDialog() {
final state = context.read<PodcastsState>();
showModalBottomSheet(
backgroundColor: Colors.white,
context: context,
builder: (context) {
return Container(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: const Text('تازه‌ترین‌ها'),
onTap: () {
state.selectedSortTypeIndex = 0;
state.getStudios(page: 1);
Navigator.pop(context);
},
),
ListTile(
title: const Text('قدیمی‌ترین‌ها'),
onTap: () {
state.selectedSortTypeIndex = 1;
state.getStudios(page: 1);
Navigator.pop(context);
},
),
ListTile(
title: const Text('پربازدیدترین‌ها'),
onTap: () {
state.selectedSortTypeIndex = 2;
state.getStudios(page: 1);
Navigator.pop(context);
},
),
ListTile(
title: const Text('پربحث‌ترین‌ها'),
onTap: () {
state.selectedSortTypeIndex = 3;
state.getStudios(page: 1);
Navigator.pop(context);
},
),
],
),
);
},
);
}
@override
void dispose() {
_rotationTimer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final state = context.watch<PodcastsState>();
@ -41,22 +116,66 @@ class _VideoCastTabPageState extends State<VideoCastTabPage> {
return const SizedBox.shrink();
}
if (_rotationTimer == null || !_rotationTimer!.isActive) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_startRotation();
});
}
return SingleChildScrollView(
child: Column(
children: [
FeaturedVideoCard(
videocast: state.studios.first,
AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (Widget child, Animation<double> animation) {
return FadeTransition(opacity: animation, child: child);
},
child: FeaturedVideoCard(
key: ValueKey<int?>(state.studios[_currentFeaturedIndex].id),
videocast: state.studios[_currentFeaturedIndex],
onTap: () {
Navigator.pushNamed(
context,
Routes.studioDetails,
arguments: {
'id': state.studios.first.id,
'type': state.studios.first.type,
'id': state.studios[_currentFeaturedIndex].id,
'type': state.studios[_currentFeaturedIndex].type,
},
);
},
),
),
if (state.studios.length > 1)
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const ItemTitle(
title: 'همه ویدیوکست‌ها',
color: Color.fromARGB(255, 0, 53, 70),
style: TextStyle(fontWeight: FontWeight.bold,fontSize: 18),
),
Row(
children: [
GestureDetector(
onTap: _showSortDialog,
child: Text(
state.orderString,
style: const TextStyle(
color: Color.fromARGB(255, 0, 53, 70)),
)),
IconButton(
onPressed: _showSortDialog,
icon: SvgPicture.asset(
'lib/assets/icons/sort2.svg')),
],
),
],
),
),
if (state.studios.length > 1)
Padding(
@ -64,15 +183,16 @@ class _VideoCastTabPageState extends State<VideoCastTabPage> {
child: GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
childAspectRatio: 0.75,
),
itemCount: state.studios.length - 1,
itemCount: state.studios.length,
itemBuilder: (context, index) {
final videocast = state.studios[index + 1];
final videocast = state.studios[index];
return VideocastGridCard(
videocast: videocast,
onTap: () {

View File

@ -58,12 +58,25 @@ class FeaturedVideoCard extends StatelessWidget {
),
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.6),
Colors.transparent,
],
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 200,
height: 450,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
@ -137,7 +150,7 @@ class FeaturedVideoCard extends StatelessWidget {
_formatDuration(videocast.duration).toPersianDigit(),
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.white,
fontWeight: FontWeight.w600,
fontWeight: FontWeight.normal,
),
),
],