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 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class ChatScreen extends StatefulWidget { class ChatScreen extends StatefulWidget {
const ChatScreen({super.key}); const ChatScreen({super.key});
@@ -21,9 +23,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
bool _isTyping = false; bool _isTyping = false;
void _handleSubmitted(String text) { Future<void> _handleSubmitted(String text) async {
if (text.trim().isEmpty) return; if (text.trim().isEmpty) return;
_textController.clear(); _textController.clear();
setState(() { setState(() {
@@ -31,18 +33,54 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
_isTyping = true; _isTyping = true;
}); });
// Simulate EPVChat! typing delay try {
Future.delayed(const Duration(milliseconds: 1500), () { // 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) { if (mounted) {
setState(() { setState(() {
_isTyping = false; _isTyping = false;
_messages.insert(0, ChatMessage( _messages.insert(
text: "This is a simulated modern response to: \"$text\"", 0,
isAssistant: true, 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) { Widget _buildMessage(ChatMessage message) {
@@ -50,7 +88,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
child: Row( child: Row(
mainAxisAlignment: isAssistant ? MainAxisAlignment.start : MainAxisAlignment.end, mainAxisAlignment: isAssistant
? MainAxisAlignment.start
: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
if (isAssistant) if (isAssistant)
@@ -79,19 +119,28 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
), ),
Flexible( Flexible(
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 14.0), padding: const EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 14.0,
),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: isAssistant gradient: isAssistant
? const LinearGradient( ? const LinearGradient(
colors: [Color(0xFFF1F5F9), Color(0xFFE2E8F0)], // Light bubbles colors: [
begin: Alignment.topLeft, Color(0xFFF1F5F9),
end: Alignment.bottomRight, Color(0xFFE2E8F0),
) ], // Light bubbles
: const LinearGradient( begin: Alignment.topLeft,
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue bubbles end: Alignment.bottomRight,
begin: Alignment.centerLeft, )
end: Alignment.centerRight, : const LinearGradient(
), colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Mint & Blue bubbles
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.only( borderRadius: BorderRadius.only(
topLeft: const Radius.circular(20), topLeft: const Radius.circular(20),
topRight: const Radius.circular(20), topRight: const Radius.circular(20),
@@ -106,9 +155,11 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
), ),
], ],
border: Border.all( border: Border.all(
color: isAssistant ? Colors.black.withOpacity(0.05) : Colors.transparent, color: isAssistant
? Colors.black.withOpacity(0.05)
: Colors.transparent,
width: 1, width: 1,
) ),
), ),
child: Text( child: Text(
message.text, message.text,
@@ -126,7 +177,10 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: const LinearGradient( gradient: const LinearGradient(
colors: [Color(0xFF57a7ed), Color(0xFF3A8BD1)], // User avatar gradient colors: [
Color(0xFF57a7ed),
Color(0xFF3A8BD1),
], // User avatar gradient
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
@@ -172,9 +226,14 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
), ),
), ),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 12.0,
),
decoration: BoxDecoration( 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( borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20), topLeft: Radius.circular(20),
topRight: Radius.circular(20), topRight: Radius.circular(20),
@@ -240,7 +299,9 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
Expanded( Expanded(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFF1F5F9), // Light input box background color: const Color(
0xFFF1F5F9,
), // Light input box background
borderRadius: BorderRadius.circular(30.0), borderRadius: BorderRadius.circular(30.0),
border: Border.all(color: Colors.black.withOpacity(0.05)), border: Border.all(color: Colors.black.withOpacity(0.05)),
boxShadow: [ boxShadow: [
@@ -257,9 +318,14 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
style: const TextStyle(color: Colors.black87), style: const TextStyle(color: Colors.black87),
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Message EPVChat!...", hintText: "Message EPVChat!...",
hintStyle: TextStyle(color: Colors.black.withOpacity(0.4)), hintStyle: TextStyle(
color: Colors.black.withOpacity(0.4),
),
border: InputBorder.none, 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( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: const LinearGradient( gradient: const LinearGradient(
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Mint & Blue send button colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Mint & Blue send button
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
), ),
@@ -282,7 +351,11 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
], ],
), ),
child: IconButton( 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), onPressed: () => _handleSubmitted(_textController.text),
), ),
), ),
@@ -306,7 +379,10 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
child: AppBar( child: AppBar(
title: ShaderMask( title: ShaderMask(
shaderCallback: (bounds) => const LinearGradient( shaderCallback: (bounds) => const LinearGradient(
colors: [Color(0xFF8ad5c9), Color(0xFF57a7ed)], // Text gradient header colors: [
Color(0xFF8ad5c9),
Color(0xFF57a7ed),
], // Text gradient header
begin: Alignment.topLeft, begin: Alignment.topLeft,
end: Alignment.bottomRight, end: Alignment.bottomRight,
).createShader(bounds), ).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, elevation: 0,
centerTitle: true, centerTitle: true,
bottom: PreferredSize( bottom: PreferredSize(
@@ -342,7 +420,7 @@ class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
Colors.white, Colors.white,
Color(0xFFF8FAFC), // Slate 50 Color(0xFFF8FAFC), // Slate 50
], ],
) ),
), ),
child: SafeArea( child: SafeArea(
bottom: false, bottom: false,

View File

@@ -75,6 +75,22 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" 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: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -192,6 +208,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.10" 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: vector_math:
dependency: transitive dependency: transitive
description: description:
@@ -208,6 +232,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "15.0.2" version: "15.0.2"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
sdks: sdks:
dart: ">=3.11.1 <4.0.0" dart: ">=3.11.1 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54" 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. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
http: ^1.6.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: