AI a funcionar

This commit is contained in:
2026-03-13 17:47:25 +00:00
parent 39c67599d1
commit 16da3cc164
3 changed files with 146 additions and 35 deletions

View File

@@ -1,5 +1,7 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class ChatScreen extends StatefulWidget {
const ChatScreen({super.key});
@@ -21,9 +23,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final ScrollController _scrollController = ScrollController();
bool _isTyping = false;
void _handleSubmitted(String text) {
Future<void> _handleSubmitted(String text) async {
if (text.trim().isEmpty) return;
_textController.clear();
setState(() {
@@ -31,18 +33,54 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
_isTyping = true;
});
// Simulate EPVChat! typing delay
Future.delayed(const Duration(milliseconds: 1500), () {
try {
// Faz o pedido para o IP usando o formato compatível com OpenAI
final response = await http
.post(
Uri.parse('http://192.168.60.134:11434/v1/chat/completions'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'model': 'qwen3:4b', // Um modelo disponível no servidor
'messages': [
{'role': 'user', 'content': text},
],
'stream': false,
}),
)
.timeout(const Duration(seconds: 30));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final reply =
data['choices'][0]['message']['content'] ??
'Sem resposta do modelo.';
if (mounted) {
setState(() {
_isTyping = false;
_messages.insert(0, ChatMessage(text: reply, isAssistant: true));
});
}
} else {
throw Exception(
'Erro no servidor: HTTP ${response.statusCode} - ${response.body}',
);
}
} catch (e) {
if (mounted) {
setState(() {
_isTyping = false;
_messages.insert(0, ChatMessage(
text: "This is a simulated modern response to: \"$text\"",
isAssistant: true,
));
_messages.insert(
0,
ChatMessage(
text:
"Não foi possível comunicar com o modelo.\nVerifique se o IP está acessível.\nDetalhes: $e",
isAssistant: true,
),
);
});
}
});
}
}
Widget _buildMessage(ChatMessage message) {
@@ -50,7 +88,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
child: Row(
mainAxisAlignment: isAssistant ? MainAxisAlignment.start : MainAxisAlignment.end,
mainAxisAlignment: isAssistant
? MainAxisAlignment.start
: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (isAssistant)
@@ -79,19 +119,28 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
),
Flexible(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 14.0),
padding: const EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 14.0,
),
decoration: BoxDecoration(
gradient: isAssistant
? const LinearGradient(
colors: [Color(0xFFF1F5F9), Color(0xFFE2E8F0)], // Light bubbles
begin: Alignment.topLeft,
end: Alignment.bottomRight,
)
: const LinearGradient(
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue bubbles
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
gradient: isAssistant
? const LinearGradient(
colors: [
Color(0xFFF1F5F9),
Color(0xFFE2E8F0),
], // Light bubbles
begin: Alignment.topLeft,
end: Alignment.bottomRight,
)
: const LinearGradient(
colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Mint & Blue bubbles
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(20),
topRight: const Radius.circular(20),
@@ -106,9 +155,11 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
),
],
border: Border.all(
color: isAssistant ? Colors.black.withOpacity(0.05) : Colors.transparent,
color: isAssistant
? Colors.black.withOpacity(0.05)
: Colors.transparent,
width: 1,
)
),
),
child: Text(
message.text,
@@ -126,7 +177,10 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: const LinearGradient(
colors: [Color(0xFF57a7ed), Color(0xFF3A8BD1)], // User avatar gradient
colors: [
Color(0xFF57a7ed),
Color(0xFF3A8BD1),
], // User avatar gradient
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
@@ -172,9 +226,14 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 12.0,
),
decoration: BoxDecoration(
color: const Color(0xFFF1F5F9), // Typing bubble matching assistant light bubble
color: const Color(
0xFFF1F5F9,
), // Typing bubble matching assistant light bubble
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
@@ -240,7 +299,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
Expanded(
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFF1F5F9), // Light input box background
color: const Color(
0xFFF1F5F9,
), // Light input box background
borderRadius: BorderRadius.circular(30.0),
border: Border.all(color: Colors.black.withOpacity(0.05)),
boxShadow: [
@@ -257,9 +318,14 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
style: const TextStyle(color: Colors.black87),
decoration: InputDecoration(
hintText: "Message EPVChat!...",
hintStyle: TextStyle(color: Colors.black.withOpacity(0.4)),
hintStyle: TextStyle(
color: Colors.black.withOpacity(0.4),
),
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 14.0),
contentPadding: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 14.0,
),
),
),
),
@@ -268,7 +334,10 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue send button
colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Mint & Blue send button
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
@@ -282,7 +351,11 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
],
),
child: IconButton(
icon: const Icon(Icons.send_rounded, color: Colors.white, size: 20),
icon: const Icon(
Icons.send_rounded,
color: Colors.white,
size: 20,
),
onPressed: () => _handleSubmitted(_textController.text),
),
),
@@ -306,7 +379,10 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
child: AppBar(
title: ShaderMask(
shaderCallback: (bounds) => const LinearGradient(
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Text gradient header
colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Text gradient header
begin: Alignment.topLeft,
end: Alignment.bottomRight,
).createShader(bounds),
@@ -319,7 +395,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
),
),
),
backgroundColor: Colors.white.withOpacity(0.7), // Light Header backgrop
backgroundColor: Colors.white.withOpacity(
0.7,
), // Light Header backgrop
elevation: 0,
centerTitle: true,
bottom: PreferredSize(
@@ -342,7 +420,7 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
Colors.white,
Color(0xFFF8FAFC), // Slate 50
],
)
),
),
child: SafeArea(
bottom: false,

View File

@@ -75,6 +75,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: "direct main"
description:
name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.dev"
source: hosted
version: "1.6.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
leak_tracker:
dependency: transitive
description:
@@ -192,6 +208,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.10"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vector_math:
dependency: transitive
description:
@@ -208,6 +232,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "15.0.2"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
sdks:
dart: ">=3.11.1 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"

View File

@@ -34,6 +34,7 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
http: ^1.6.0
dev_dependencies:
flutter_test: