didvan-app/lib/views/ai_section/ai_section_page.dart

389 lines
13 KiB
Dart

import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/models/ai/bots_model.dart';
import 'package:didvan/views/ai/ai_chat_page.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/hoshan_home_app_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/ai_state.dart';
class AiSectionPage extends StatefulWidget {
const AiSectionPage({super.key});
@override
State<AiSectionPage> createState() => _AiSectionPageState();
}
class _AiSectionGridItem {
final String title;
final String description;
final String iconPath;
final void Function(BuildContext context) onTap;
_AiSectionGridItem({
required this.title,
required this.description,
required this.iconPath,
required this.onTap,
});
}
class _AiSectionPageState extends State<AiSectionPage>
with TickerProviderStateMixin {
late final List<_AiSectionGridItem> _gridItems;
late AnimationController _fadeController;
late AnimationController _slideController;
late Animation<double> _fadeAnimation;
late Animation<Offset> _slideAnimation;
@override
void initState() {
super.initState();
_fadeController = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
);
_fadeAnimation = CurvedAnimation(
parent: _fadeController,
curve: Curves.easeIn,
);
_slideController = AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
_slideAnimation = Tween<Offset>(
begin: const Offset(0, 0.3),
end: Offset.zero,
).animate(CurvedAnimation(
parent: _slideController,
curve: Curves.easeOutCubic,
));
_fadeController.forward();
_slideController.forward();
WidgetsBinding.instance.addPostFrameCallback((_) {
final historyAiChatState = context.read<HistoryAiChatState>();
if (historyAiChatState.bots.isEmpty) {
historyAiChatState.getBots();
}
final aiState = context.read<AiState>();
final aiChatState = context.read<AiChatState>();
aiState.onClearChatCallback = () async {
await aiChatState.clearChat();
};
aiState.endChat();
if (aiState.tools == null) {
aiState.getTools();
}
});
_gridItems = [
_AiSectionGridItem(
title: 'ساخت عکس',
description: 'ایجاد تصاویر خلاقانه با هوش مصنوعی',
iconPath: 'lib/assets/icons/Image.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
if (aiState.tools != null && aiState.tools!.isNotEmpty) {
try {
final tool = aiState.tools![0];
if (tool.bots != null && tool.bots!.isNotEmpty) {
aiState.startChat(AiChatArgs(bot: tool.bots!.first));
}
} catch (e) {
debugPrint('خطا در یافتن ابزار تصویرساز: $e');
}
}
},
),
_AiSectionGridItem(
title: 'ترجمه',
description: 'ترجمه متون به زبان‌های مختلف',
iconPath: 'lib/assets/icons/Translate2.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
if (aiState.tools != null && aiState.tools!.length > 2) {
try {
final tool = aiState.tools![2];
if (tool.bots != null && tool.bots!.isNotEmpty) {
aiState.startChat(AiChatArgs(bot: tool.bots!.first));
}
} catch (e) {
debugPrint('خطا در یافتن ابزار ترجمه: $e');
}
}
},
),
_AiSectionGridItem(
title: 'خلاصه‌ساز',
description: 'خلاصه‌سازی متن با هوش مصنوعی',
iconPath: 'lib/assets/icons/Summary2.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
final aisummeryBot = BotsModel(
id: 100,
name: 'Aisummery',
responseType: 'text',
attachmentType: ['pdf', 'image', 'audio'],
attachment: 1,
);
aiState.startChat(AiChatArgs(bot: aisummeryBot));
},
),
_AiSectionGridItem(
title: 'متن به صوت',
description: 'تبدیل متن به فایل صوتی',
iconPath: 'lib/assets/icons/TTS.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
final textToSpeechBot = BotsModel(
id: 101,
name: 'aiaudio',
responseType: 'audio',
attachmentType: [],
attachment: 0,
);
aiState.startChat(AiChatArgs(bot: textToSpeechBot));
},
),
_AiSectionGridItem(
title: 'تحلیل نمودار',
description: 'ساخت نمودار با تحلیل هوشمند',
iconPath: 'lib/assets/icons/Nemoudar.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
final chartAnalysisBot = BotsModel(
id: 27,
name: 'chart-analysis',
responseType: 'text',
attachmentType: ['image', 'pdf'],
attachment: 1,
);
aiState.startChat(AiChatArgs(bot: chartAnalysisBot));
},
),
_AiSectionGridItem(
title: 'ساخت ویدیو',
description: 'تولید ویدیو با هوش مصنوعی',
iconPath: 'lib/assets/icons/VideoGen.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
final aiVideoBot = BotsModel(
id: 102,
name: 'aivideo',
responseType: 'video',
attachmentType: [],
attachment: 0,
);
aiState.startChat(AiChatArgs(bot: aiVideoBot));
},
),
_AiSectionGridItem(
title: 'اینفوگرافی',
description: 'تبدیل محتوا به اینفوگرافی',
iconPath: 'lib/assets/icons/Info.svg',
onTap: (context) {
final aiState = context.read<AiState>();
aiState.endChat();
final infoAiBot = BotsModel(
id: 103,
name: 'infoai',
responseType: 'image',
attachmentType: ['audio', 'pdf', 'image'],
attachment: 2,
);
aiState.startChat(AiChatArgs(bot: infoAiBot));
},
),
];
}
@override
void dispose() {
_fadeController.dispose();
_slideController.dispose();
super.dispose();
}
Widget _buildAiCategoryItem(
_AiSectionGridItem item, bool isDark, ThemeData theme) {
return Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: GestureDetector(
onTap: () => item.onTap(context),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.zero,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Colors.transparent,
width: 2,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
spreadRadius: 1,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SvgPicture.asset(
item.iconPath,
width: 70,
height: 70,
),
),
),
const SizedBox(height: 3),
Text(
item.title,
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.bodySmall?.copyWith(
color: const Color.fromARGB(255, 27, 60, 89),
fontWeight: FontWeight.bold,
fontSize: 13,
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
final aiState = context.watch<AiState>();
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Column(
children: [
if (!aiState.isChatting) const HoshanHomeAppBar(),
Expanded(
child: aiState.isChatting
? AiChatPage(args: aiState.currentChatArgs!)
: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FadeTransition(
opacity: _fadeAnimation,
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
SvgPicture.asset(
'lib/assets/icons/clarity_tools-line.svg'),
const SizedBox(
width: 8,
),
DidvanText(
'جعبه ابزار هوشان',
style: Theme.of(context).textTheme.titleMedium,
color: Theme.of(context).colorScheme.title,
),
],
),
),
),
SlideTransition(
position: _slideAnimation,
child: FadeTransition(
opacity: _fadeAnimation,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
child: Column(
children: [
if (_gridItems.length >= 3)
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: _gridItems
.sublist(0, 3)
.map((item) => _buildAiCategoryItem(
item, isDark, theme))
.toList(),
),
const SizedBox(height: 20),
// Second Row (Items 3-6)
if (_gridItems.length >= 6)
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: _gridItems
.sublist(3, 6)
.map((item) => _buildAiCategoryItem(
item, isDark, theme))
.toList(),
),
const SizedBox(height: 20),
// Third Row (Items 6+)
if (_gridItems.length > 6)
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
..._gridItems.sublist(6).map((item) =>
_buildAiCategoryItem(
item, isDark, theme)),
if ((_gridItems.length - 6) < 3)
...List.generate(
3 - (_gridItems.length - 6),
(index) =>
const Expanded(child: SizedBox()),
),
],
),
],
),
),
),
),
],
),
),
),
],
);
}
}