import 'dart:convert'; import 'dart:io'; import 'package:didvan/models/ai/bots_model.dart'; import 'package:didvan/models/ai/chats_model.dart'; import 'package:didvan/models/ai/messages_model.dart'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/view/alert_data.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/services/ai/ai_api_service.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; class AiChatState extends CoreProvier { Stream messageOnstream = const Stream.empty(); List messages = []; bool onResponsing = false; bool loading = false; final ScrollController scrollController = ScrollController(); int? chatId; File? file; Future _scrolledEnd() async { WidgetsBinding.instance.addPostFrameCallback((_) async { await scrollController.animateTo( scrollController.position.minScrollExtent, duration: const Duration(milliseconds: 600), curve: Curves.easeInOut, ); }); } Future _onError(e) async { onResponsing = false; messages.last.prompts.removeLast(); messages.last.prompts.removeLast(); messageOnstream = const Stream.empty(); await ActionSheetUtils.showAlert(AlertData( message: 'خطا در برقراری ارتباط', aLertType: ALertType.error)); update(); } Future getChatId() async { final service = RequestService( RequestHelper.aiChatId(), ); await service.httpGet(); if (service.isSuccess) { final id = service.result['id']; chatId = id; } return service; } Future getAllMessages(int chatId) async { loading = true; onResponsing = true; final service = RequestService( RequestHelper.aiAChat(chatId), ); await service.httpGet(); if (service.isSuccess) { messages.clear(); final ChatsModel allMessages = ChatsModel.fromJson(service.result['chat']); for (var i = 0; i < allMessages.prompts!.length; i++) { final prompt = allMessages.prompts![i]; if (messages.isNotEmpty && DateTime.parse(messages.last.prompts.last.createdAt.toString()) .toPersianDateStr() .contains(DateTime.parse(prompt.createdAt.toString()) .toPersianDateStr())) { messages.last.prompts.add(prompt); } else { messages.add(MessageModel( dateTime: prompt.createdAt.toString(), prompts: [prompt])); } // chats.add("chats: $chats"); } appState = AppState.idle; loading = false; onResponsing = false; // Add this code to scroll to maxScrollExtent after the ListView is built update(); return; } appState = AppState.failed; loading = false; onResponsing = false; update(); } Future postMessage(BotsModel bot) async { onResponsing = true; update(); String message = messages.last.prompts.last.text!; messages.last.prompts.add(Prompts( finished: false, text: '...', role: 'bot', createdAt: DateTime.now() .subtract(const Duration(minutes: 210)) .toIso8601String())); update(); await _scrolledEnd(); final req = await AiApiService.initial( url: '/${bot.id}/${bot.name}'.toLowerCase(), message: message, chatId: chatId, file: file); final res = await AiApiService.getResponse(req).catchError((e) { _onError(e); throw e; }); String responseMessgae = ''; var r = res.listen((value) async { var str = utf8.decode(value); responseMessgae += str; messageOnstream = Stream.value(responseMessgae); update(); }); r.onDone(() async { if (chatId == null) { final service = await getChatId(); if (!service.isSuccess) { _onError(null); return; } } onResponsing = false; messages.last.prompts.last = messages.last.prompts.last.copyWith( finished: true, text: responseMessgae, ); messageOnstream = const Stream.empty(); update(); _scrolledEnd(); }); r.onError(_onError); } }