608 lines
20 KiB
Dart
608 lines
20 KiB
Dart
// ignore_for_file: unnecessary_import
|
|
|
|
import 'package:didvan/config/design_config.dart';
|
|
import 'package:didvan/config/theme_data.dart';
|
|
import 'package:didvan/models/home_page_content/content.dart';
|
|
import 'package:didvan/models/home_page_content/home_page_list.dart';
|
|
import 'package:didvan/models/home_page_content/swot.dart';
|
|
import 'package:didvan/services/app_initalizer.dart';
|
|
import 'package:didvan/services/network/request.dart';
|
|
import 'package:didvan/views/home/explore/explore.dart';
|
|
import 'package:didvan/views/home/main/main_page_state.dart';
|
|
import 'package:didvan/views/home/main/widgets/main_content.dart';
|
|
import 'package:didvan/views/home/main/widgets/story_section.dart';
|
|
import 'package:didvan/views/home/main/widgets/simple_explore_card.dart';
|
|
import 'package:didvan/views/home/main/widgets/didvan_plus_section.dart';
|
|
import 'package:didvan/views/home/main/widgets/didvan_voice_section.dart';
|
|
import 'package:didvan/views/home/new_statistic/new_statistics_state.dart';
|
|
import 'package:didvan/views/widgets/didvan/text.dart';
|
|
import 'package:didvan/views/widgets/state_handlers/state_handler.dart';
|
|
import 'package:didvan/views/widgets/carousel_3d.dart';
|
|
import 'package:didvan/views/home/home_state.dart';
|
|
import 'package:didvan/views/widgets/text_divider.dart';
|
|
import 'package:didvan/views/widgets/home_app_bar.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:flutter_animate/flutter_animate.dart';
|
|
import 'package:url_launcher/url_launcher_string.dart';
|
|
|
|
import 'package:flutter/foundation.dart' show kIsWeb, defaultTargetPlatform;
|
|
|
|
import 'package:universal_html/html.dart' as html;
|
|
|
|
bool isAnyMobile() {
|
|
if (kIsWeb) {
|
|
final userAgent = html.window.navigator.userAgent.toLowerCase();
|
|
return userAgent.contains('mobile') ||
|
|
userAgent.contains('android') ||
|
|
userAgent.contains('ios');
|
|
}
|
|
|
|
return defaultTargetPlatform == TargetPlatform.android ||
|
|
defaultTargetPlatform == TargetPlatform.iOS;
|
|
}
|
|
|
|
class MainPage extends StatefulWidget {
|
|
const MainPage({
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<MainPage> createState() => _MainPageState();
|
|
}
|
|
|
|
class _MainPageState extends State<MainPage> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
context.read<MainPageState>().init();
|
|
context.read<NewStatisticState>().init();
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return StateHandler<MainPageState>(
|
|
onRetry: () => context.read<MainPageState>().init(),
|
|
state: context.watch<MainPageState>(),
|
|
builder: (context, state) {
|
|
debugPrint(
|
|
'🏠 MainPage build - didvanPlus: ${state.didvanPlus != null}');
|
|
debugPrint(
|
|
'🏠 MainPage build - didvanVoice: ${state.didvanVoice != null}');
|
|
return Column(
|
|
children: [
|
|
const HomeAppBar(
|
|
showBackButton: false,
|
|
showSearchField: true,
|
|
),
|
|
Expanded(
|
|
child: ListView(
|
|
padding: const EdgeInsets.only(top: 0, bottom: 16),
|
|
children: [
|
|
if (state.stories.isNotEmpty) ...[
|
|
const TextDivider(text: 'دیدهبان')
|
|
.animate()
|
|
.fadeIn(delay: 400.ms, duration: 500.ms),
|
|
const _DidvanSignalsTitle()
|
|
.animate()
|
|
.fadeIn(delay: 500.ms, duration: 500.ms),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
child: StorySection(stories: state.stories),
|
|
).animate().fadeIn(delay: 600.ms, duration: 500.ms),
|
|
],
|
|
if (state.didvanPlus != null) ...[
|
|
const SizedBox(height: 16),
|
|
DidvanPlusSection(didvanPlus: state.didvanPlus!)
|
|
.animate()
|
|
.fadeIn(delay: 650.ms, duration: 500.ms),
|
|
],
|
|
const SizedBox(height: 12),
|
|
const TextDivider(text: 'پیشخوان استراتژیک')
|
|
.animate()
|
|
.fadeIn(delay: 700.ms, duration: 500.ms),
|
|
const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
|
child: MainPageMainContent(),
|
|
).animate().fadeIn(delay: 800.ms, duration: 500.ms),
|
|
if (state.content != null &&
|
|
state.content!.lists.isNotEmpty) ...[
|
|
const _ExploreLatestTitle()
|
|
.animate()
|
|
.fadeIn(delay: 900.ms, duration: 500.ms),
|
|
_ExploreLatestSlider(
|
|
lists: state.content!.lists,
|
|
swotItems: state.swotItems,
|
|
).animate().fadeIn(delay: 1000.ms, duration: 500.ms),
|
|
],
|
|
if (state.swotItems.isNotEmpty)
|
|
SwotSection(swotItems: state.swotItems,headerSize: 13,moreSize: 12,)
|
|
.animate()
|
|
.fadeIn(delay: 1100.ms, duration: 500.ms),
|
|
if (state.didvanVoice != null) ...[
|
|
const SizedBox(height: 16),
|
|
const _DidvanVoiceTitle()
|
|
.animate()
|
|
.fadeIn(delay: 1150.ms, duration: 500.ms),
|
|
const SizedBox(height: 12),
|
|
DidvanVoiceSection(didvanVoice: state.didvanVoice!)
|
|
.animate()
|
|
.fadeIn(delay: 1200.ms, duration: 500.ms),
|
|
],
|
|
// const _IndustryPulseTitle()
|
|
// .animate()
|
|
// .fadeIn(delay: 1100.ms, duration: 500.ms),
|
|
// const _IndustryPulseCards()
|
|
// .animate()
|
|
// .fadeIn(delay: 1200.ms, duration: 500.ms),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class _DidvanSignalsTitle extends StatelessWidget {
|
|
const _DidvanSignalsTitle();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
bottom: 16,
|
|
top: 0,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
'lib/assets/icons/Signal.svg',
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
const SizedBox(width: 5),
|
|
DidvanText(
|
|
"سیگنالهای دیدوان",
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
color: const Color.fromARGB(255, 0, 89, 119),
|
|
fontSize: 13,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _DidvanVoiceTitle extends StatelessWidget {
|
|
const _DidvanVoiceTitle();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
'lib/assets/icons/akar-icons_sound-on.svg',
|
|
width: 25,
|
|
height: 25,
|
|
),
|
|
const SizedBox(width: 5),
|
|
DidvanText(
|
|
"صدای دیدوان ",
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
color: const Color.fromARGB(255, 0, 89, 119),
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
DidvanText(
|
|
"(خلاصه تازهترین پویش افق)",
|
|
style: Theme.of(context).textTheme.bodySmall,
|
|
color: const Color.fromARGB(255, 0, 89, 119),
|
|
fontSize: 11,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ExploreLatestTitle extends StatelessWidget {
|
|
const _ExploreLatestTitle();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
bottom: 16,
|
|
top: 0,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
SvgPicture.asset(
|
|
'lib/assets/icons/discover.svg',
|
|
width: 25,
|
|
height: 25,
|
|
color: const Color.fromARGB(255, 0, 126, 167),
|
|
),
|
|
const SizedBox(width: 5),
|
|
DidvanText(
|
|
"تازهترینهای کاوش",
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
color: DesignConfig.isDark
|
|
? const Color.fromARGB(255, 0, 125, 166)
|
|
: const Color.fromARGB(255, 0, 89, 119),
|
|
fontSize: 13,
|
|
),
|
|
],
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
context.read<HomeState>().tabController.animateTo(3);
|
|
},
|
|
child: const Row(
|
|
children: [
|
|
DidvanText(
|
|
"مشاهده همه",
|
|
color: Color.fromARGB(255, 0, 126, 167),
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 12,
|
|
),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ExploreLatestSlider extends StatelessWidget {
|
|
final List<MainPageList> lists;
|
|
final List<SwotItem> swotItems;
|
|
|
|
const _ExploreLatestSlider({required this.lists, required this.swotItems});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final List<Widget> items = [];
|
|
final List<
|
|
({String type, MainPageContentType? content, SwotItem? swotItem})>
|
|
itemsData = [];
|
|
|
|
for (var list in lists) {
|
|
if (list.type == 'video' ||
|
|
list.type == 'podcast' ||
|
|
list.type == 'news' ||
|
|
list.type == 'radar') {
|
|
continue;
|
|
}
|
|
if (list.contents.isNotEmpty) {
|
|
final newestContent = list.contents.first;
|
|
items.add(
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
|
child: SimpleExploreCard(
|
|
content: newestContent,
|
|
type: list.type,
|
|
),
|
|
),
|
|
);
|
|
itemsData
|
|
.add((type: list.type, content: newestContent, swotItem: null));
|
|
}
|
|
}
|
|
|
|
if (swotItems.isNotEmpty) {
|
|
items.add(
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
|
child: SimpleExploreCard(
|
|
swotItem: swotItems.first,
|
|
),
|
|
),
|
|
);
|
|
itemsData.add((type: 'swot', content: null, swotItem: swotItems.first));
|
|
}
|
|
|
|
if (items.isEmpty) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
return Carousel3D(
|
|
items: items,
|
|
height: 220,
|
|
autoPlayDuration: const Duration(seconds: 5),
|
|
showControls: true,
|
|
onItemChanged: (index) {
|
|
// Optional: Handle item change if needed
|
|
},
|
|
onItemTap: (index) {
|
|
final data = itemsData[index];
|
|
if (data.swotItem != null) {
|
|
AppInitializer.openWebLink(
|
|
context,
|
|
'http://opportunity-threat.didvan.com/posts/${data.swotItem!.id}/?accessToken=${RequestService.token}',
|
|
mode: LaunchMode.inAppWebView,
|
|
);
|
|
} else if (data.content != null) {
|
|
context.read<MainPageState>().navigationHandler(
|
|
data.type,
|
|
data.content!.id,
|
|
data.content!.link,
|
|
description: data.content!.title,
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
// class _IndustryPulseTitle extends StatelessWidget {
|
|
// const _IndustryPulseTitle();
|
|
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return Padding(
|
|
// padding: const EdgeInsets.only(
|
|
// left: 16,
|
|
// right: 16,
|
|
// bottom: 16,
|
|
// top: 16,
|
|
// ),
|
|
// child: Row(
|
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
// children: [
|
|
// Row(
|
|
// children: [
|
|
// SvgPicture.asset(
|
|
// 'lib/assets/icons/chart 2.svg',
|
|
// color: Theme.of(context).colorScheme.title,
|
|
// width: 30,
|
|
// height: 30,
|
|
// ),
|
|
// const SizedBox(width: 5),
|
|
// DidvanText(
|
|
// "نبض صنعت",
|
|
// style: Theme.of(context).textTheme.titleMedium,
|
|
// color: const Color.fromARGB(255, 0, 89, 119),
|
|
// fontSize: 13,
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// GestureDetector(
|
|
// onTap: () {
|
|
// context.read<HomeState>().tabController.animateTo(2);
|
|
// },
|
|
// child: const Row(
|
|
// children: [
|
|
// DidvanText(
|
|
// "مشاهده همه",
|
|
// color: Color.fromARGB(255, 0, 126, 167),
|
|
// fontWeight: FontWeight.normal,
|
|
// fontSize: 12,
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// )
|
|
// ],
|
|
// ),
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
// class _IndustryPulseCards extends StatefulWidget {
|
|
// const _IndustryPulseCards();
|
|
|
|
// @override
|
|
// State<_IndustryPulseCards> createState() => _IndustryPulseCardsState();
|
|
// }
|
|
|
|
// class _IndustryPulseCardsState extends State<_IndustryPulseCards> {
|
|
// late PageController _pageController;
|
|
|
|
// @override
|
|
// void initState() {
|
|
// super.initState();
|
|
// _pageController = PageController(viewportFraction: 0.45);
|
|
// }
|
|
|
|
// @override
|
|
// void dispose() {
|
|
// _pageController.dispose();
|
|
// super.dispose();
|
|
// }
|
|
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// return StateHandler<NewStatisticState>(
|
|
// state: context.watch<NewStatisticState>(),
|
|
// placeholder: const Center(child: CircularProgressIndicator()),
|
|
// onRetry: () => context.read<NewStatisticState>().init(),
|
|
// builder: (context, statisticState) {
|
|
// if (statisticState.contents.isEmpty) {
|
|
// return const SizedBox.shrink();
|
|
// }
|
|
|
|
// final List<Content> allItems = [];
|
|
// statisticState.contents.forEach((category) {
|
|
// allItems.addAll(category.contents);
|
|
// });
|
|
|
|
// final List<String> desiredTitles = [
|
|
// 'دلار',
|
|
// 'بیت کوین',
|
|
// 'نیکل',
|
|
// 'نفت خام'
|
|
// ];
|
|
// final List<Content> itemsToShow = allItems
|
|
// .where((item) => desiredTitles.contains(item.title))
|
|
// .toList();
|
|
|
|
// if (itemsToShow.isEmpty) {
|
|
// return const SizedBox.shrink();
|
|
// }
|
|
|
|
// return Padding(
|
|
// padding: const EdgeInsets.only(left: 16.0),
|
|
// child: Align(
|
|
// alignment: Alignment.centerLeft,
|
|
// child: SizedBox(
|
|
// height: 165,
|
|
// child: PageView.builder(
|
|
// padEnds: false,
|
|
// controller: _pageController,
|
|
// itemCount: itemsToShow.length,
|
|
// itemBuilder: (context, index) {
|
|
// return Padding(
|
|
// padding: const EdgeInsets.only(right: 8.0),
|
|
// child: AspectRatio(
|
|
// aspectRatio: 1,
|
|
// child: _IndustryPulseCard(statistic: itemsToShow[index]),
|
|
// ),
|
|
// )
|
|
// .animate()
|
|
// .fadeIn(delay: (200 * index).ms, duration: 500.ms)
|
|
// .slideX(
|
|
// begin: -0.5, duration: 500.ms, curve: Curves.easeOut);
|
|
// },
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// );
|
|
// },
|
|
// );
|
|
// }
|
|
// }
|
|
|
|
// class _IndustryPulseCard extends StatelessWidget {
|
|
// final Content statistic;
|
|
|
|
// const _IndustryPulseCard({required this.statistic});
|
|
|
|
// Color _diffColor(BuildContext context) => statistic.data.dt == 'high'
|
|
// ? Theme.of(context).colorScheme.success
|
|
// : Theme.of(context).colorScheme.error;
|
|
|
|
// bool get _hasDiff => statistic.data.dp != 0;
|
|
|
|
// @override
|
|
// Widget build(BuildContext context) {
|
|
// final state = context.read<NewStatisticState>();
|
|
// return GestureDetector(
|
|
// onTap: () =>
|
|
// Navigator.of(context).pushNamed(Routes.statisticDetails, arguments: {
|
|
// 'onMarkChanged': (value) => onMarkChanged(statistic.id, value),
|
|
// 'label': statistic.label,
|
|
// 'title': statistic.title,
|
|
// 'marked': statistic.marked,
|
|
// }).then(
|
|
// (value) => state.getStatistic(),
|
|
// ),
|
|
// child: DidvanCard(
|
|
// padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 9),
|
|
// child: Column(
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
// crossAxisAlignment: CrossAxisAlignment.center,
|
|
// children: [
|
|
// Padding(
|
|
// padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
// child: Row(
|
|
// children: [
|
|
// Expanded(
|
|
// child: MiniChart(
|
|
// label: statistic.label,
|
|
// width: double.infinity,
|
|
// height: 38,
|
|
// lineColor: _hasDiff
|
|
// ? _diffColor(context)
|
|
// : Theme.of(context).colorScheme.primary,
|
|
// changePercent: statistic.data.dp.toDouble(),
|
|
// trend: statistic.data.dt,
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// const SizedBox(height: 20),
|
|
// Row(
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
// children: [
|
|
// if (statistic.marked)
|
|
// Icon(
|
|
// Icons.star,
|
|
// color: Theme.of(context).colorScheme.yellow,
|
|
// size: 16,
|
|
// ),
|
|
// if (statistic.marked) const SizedBox(width: 4),
|
|
// DidvanText(
|
|
// statistic.title,
|
|
// style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
// fontWeight: FontWeight.w600,
|
|
// ),
|
|
// maxLines: 1,
|
|
// overflow: TextOverflow.ellipsis,
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// const SizedBox(height: 6),
|
|
// DidvanText(
|
|
// statistic.data.p,
|
|
// style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
|
// fontWeight: FontWeight.w500,
|
|
// ),
|
|
// ),
|
|
// if (_hasDiff) const SizedBox(height: 6),
|
|
// if (_hasDiff)
|
|
// Container(
|
|
// padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
|
// decoration: BoxDecoration(
|
|
// color: statistic.data.dt == 'high'
|
|
// ? const Color.fromRGBO(245, 255, 252, 1)
|
|
// : const Color.fromRGBO(255, 248, 248, 1),
|
|
// borderRadius: BorderRadius.circular(4),
|
|
// ),
|
|
// child: Row(
|
|
// mainAxisSize: MainAxisSize.min,
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
// children: [
|
|
// Icon(
|
|
// statistic.data.dt == 'high'
|
|
// ? DidvanIcons.angle_up_regular
|
|
// : DidvanIcons.angle_down_regular,
|
|
// size: 16,
|
|
// color: _diffColor(context),
|
|
// ),
|
|
// const SizedBox(width: 4),
|
|
// DidvanText(
|
|
// '${statistic.data.dp}%',
|
|
// style: Theme.of(context).textTheme.bodySmall,
|
|
// color: _diffColor(context),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// );
|
|
// }
|
|
|
|
// void onMarkChanged(int id, bool value) {
|
|
// UserProvider.changeStatisticMark(id, value);
|
|
// }
|
|
// }
|