Houshan-Basa/lib/ui/screens/chat/cubit/receive_message_cubit.dart

204 lines
7.9 KiB
Dart

import 'dart:convert';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hoshan/core/utils/strings.dart';
import 'package:hoshan/data/model/ai/ai_response_model.dart';
import 'package:hoshan/data/model/ai/messages_model.dart';
import 'package:hoshan/data/model/ai/send_message_model.dart';
import 'package:hoshan/data/repository/chatbot_repository.dart';
import 'package:string_validator/string_validator.dart';
part 'receive_message_state.dart';
class ReceiveMessageCubit extends Cubit<ReceiveMessageState> {
ReceiveMessageCubit() : super(ReceiveMessageInitial());
static ScrollController scrollController = ScrollController();
static ValueNotifier<bool> onResponse = ValueNotifier(false);
static Future<void> scrollToEnd({final double? extra}) async {
try {
await scrollController.animateTo(
scrollController.position.minScrollExtent + (extra ?? 0),
duration: const Duration(milliseconds: 600),
curve: Curves.easeInOut,
);
} catch (e) {
if (kDebugMode) {
// print('Error in Scroll:$e');
}
}
}
static Future<void> scrollToStart({final double? extra}) async {
try {
await scrollController.animateTo(
scrollController.position.maxScrollExtent + (extra ?? 0),
duration: const Duration(milliseconds: 600),
curve: Curves.easeInOut,
);
} catch (e) {
if (kDebugMode) {
// print('Error in Scroll:$e');
}
}
}
void execute({required final SendMessageModel request}) async {
emit(ReceiveMessageLoading());
onResponse.value = true;
String result = '';
AiResponseModel aiResponseModel = AiResponseModel();
await scrollToEnd();
try {
// Call your streaming message function and yield states accordingly
await for (String message in request.tool!
? ChatbotRepository.sendMessageTool(request)
: ChatbotRepository.sendMessage(request)) {
Map<String, dynamic> jsonMap;
try {
jsonMap = jsonDecode(message);
} catch (e) {
if (kDebugMode) {
print('Error in Parse: $e');
}
jsonMap = {};
jsonMap['content'] = '';
try {
message = message.trim();
List<String> jsonStrings = message.split('}{').map((s) {
if (!s.startsWith('{')) s = '{$s';
if (!s.endsWith('}')) s = '$s}';
return s;
}).toList();
for (String json in jsonStrings) {
json = json.replaceAll(
RegExp(r'[{}"]'), ''); // Remove braces and quotes
List<String> pairs = json.split(', ');
for (String pair in pairs) {
if (pair.contains('chat_id:')) {
jsonMap['chat_id'] =
int.tryParse(pair.replaceAll('chat_id: ', ''));
} else if (pair.contains('chat_title:')) {
jsonMap['chat_title'] = pair.replaceAll('chat_title: ', '');
} else if (pair.contains('ai_message_id:')) {
jsonMap['ai_message_id'] =
pair.replaceAll('ai_message_id: ', '');
} else if (pair.contains('human_message_id:')) {
jsonMap['human_message_id'] =
pair.replaceAll('human_message_id: ', '');
} else if (pair.contains('credit:')) {
jsonMap['credit'] = pair.replaceAll('credit: ', '');
} else if (pair.contains('credit:')) {
jsonMap['credit'] = pair.replaceAll('credit: ', '');
} else if (pair.contains('free:')) {
jsonMap['free'] = pair.replaceAll('free: ', '');
} else if (pair.contains('human_message_created_at:')) {
jsonMap['human_message_created_at'] =
pair.replaceAll('human_message_created_at: ', '');
} else if (pair.contains('ai_message_created_at:')) {
jsonMap['ai_message_created_at'] =
pair.replaceAll('ai_message_created_at: ', '');
} else {
jsonMap['content'] += pair
.replaceAll('content: ', '')
.replaceAll('\\n', '\n\n');
}
}
}
} catch (e) {
if (kDebugMode) {
print('Error in Manul Parse: $e');
}
jsonMap = {};
}
}
final res = AiResponseModel.fromJson(jsonMap);
if (res.content != null) {
result += res.content ?? ''; // Add each content to the list
if (!(res.content!.startsWith('http'))) {
emit(ReceiveMessageOnResponsing(text: result));
}
}
aiResponseModel = aiResponseModel.copyWith(
error: res.error,
credit: res.credit,
detail: res.detail,
statusCode: res.statusCode,
aiMessageId: res.aiMessageId,
chatId: res.chatId,
chatTitle: res.chatTitle,
content: result.isEmpty ? res.content : result,
freeCredit: res.freeCredit,
humanMessageId: res.humanMessageId);
// Yield the received message line by line
}
await scrollToEnd();
if (aiResponseModel.error ?? true) {
emit(ReceiveMessageOnFail(
oldHumanMessageId: request.messageId ?? '',
detail: 'خطا از سمت سرور لطفا لحظاتی دیگر دوباره تلاش کنید',
statusCode: aiResponseModel.statusCode ?? 500));
} else {
final message = Messages(
id: aiResponseModel.aiMessageId,
query: request.query,
role: 'ai',
content: [
if (aiResponseModel.content != null)
Content(
audioUrl: aiResponseModel.content!.isURL() &&
aiResponseModel.content!.isAudio()
? FileUrl(url: aiResponseModel.content)
: null,
pdfUrl: aiResponseModel.content!.isURL() &&
aiResponseModel.content!.isDocument()
? FileUrl(url: aiResponseModel.content)
: null,
type: aiResponseModel.content!.isURL()
? aiResponseModel.content!.isAudio()
? 'audio'
: aiResponseModel.content!.isImage()
? 'image'
: aiResponseModel.content!.isDocument()
? 'doc'
: 'text'
: 'text',
text: aiResponseModel.content!.isURL()
? null
: aiResponseModel.content,
imageUrl: aiResponseModel.content!.isURL() &&
aiResponseModel.content!.isImage()
? FileUrl(url: aiResponseModel.content)
: null)
]);
emit(ReceiveMessageDone(
model: aiResponseModel,
message: message,
oldHumanMessageId: request.messageId!));
}
} catch (e) {
// if (e.response?.statusCode == 403) {
// emit(const SendMessageError('موجودی شماکافی نمیباشد'));
// } else {
// emit(SendMessageError('Error: $e'));
// }
emit(ReceiveMessageOnFail(
detail: 'خطا از سمت سرور لطفا لحظاتی دیگر دوباره تلاش کنید',
statusCode: 500,
oldHumanMessageId: request.messageId ?? ''));
}
onResponse.value = false;
await Future.delayed(const Duration(milliseconds: 300));
await scrollToEnd();
}
}