389 lines
13 KiB
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()),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|