flutter_chatgpt_api 1.0.0 flutter_chatgpt_api: ^1.0.0 copied to clipboard
Flutter/Dart API around ChatGPT.
import 'package:example/session_token.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chatgpt_api/flutter_chatgpt_api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter ChatGPT API Example by justecdev',
home: ChatPage(),
debugShowCheckedModeBanner: false,
);
}
}
const backgroundColor = Color(0xff343541);
const botBackgroundColor = Color(0xff444654);
class ChatPage extends StatefulWidget {
const ChatPage({super.key});
@override
State<ChatPage> createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
final _textController = TextEditingController();
final _scrollController = ScrollController();
final List<ChatMessage> _messages = [];
late ChatGPTApi _api;
String? _parentMessageId;
String? _conversationId;
late bool isLoading;
@override
void initState() {
super.initState();
_api = ChatGPTApi(sessionToken: SESSION_TOKEN);
isLoading = false;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 100,
title: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Flutter ChatGPT API Example @coskuncay',
maxLines: 2,
textAlign: TextAlign.center,
),
),
backgroundColor: botBackgroundColor,
),
backgroundColor: backgroundColor,
body: SafeArea(
child: Column(
children: [
Expanded(
child: _buildList(),
),
Visibility(
visible: isLoading,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(
color: Colors.white,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
_buildInput(),
_buildSubmit(),
],
),
),
],
),
),
);
}
Widget _buildSubmit() {
return Visibility(
visible: !isLoading,
child: Container(
color: botBackgroundColor,
child: IconButton(
icon: const Icon(
Icons.send_rounded,
color: Color.fromRGBO(142, 142, 160, 1),
),
onPressed: () async {
setState(
() {
_messages.add(
ChatMessage(
text: _textController.text,
chatMessageType: ChatMessageType.user,
),
);
isLoading = true;
},
);
// Save the input and clearing the text field.
var input = _textController.text;
_textController.clear();
// Needs a delay or the scroll won't always work.
Future.delayed(const Duration(milliseconds: 50))
.then((_) => _scrollDown());
// Send the message to the API, use conversationId and parentMessageId
// to keep the thread context.
var newMessage = await _api.sendMessage(
input,
conversationId: _conversationId,
parentMessageId: _parentMessageId,
);
setState(() {
_conversationId = newMessage.conversationId;
_parentMessageId = newMessage.messageId;
isLoading = false;
_messages.add(
ChatMessage(
text: newMessage.message,
chatMessageType: ChatMessageType.bot,
),
);
});
_textController.clear();
// Needs a delay or the scroll won't always work.
Future.delayed(const Duration(milliseconds: 50))
.then((_) => _scrollDown());
},
),
),
);
}
Expanded _buildInput() {
return Expanded(
child: TextField(
textCapitalization: TextCapitalization.sentences,
style: const TextStyle(color: Colors.white),
controller: _textController,
decoration: const InputDecoration(
fillColor: botBackgroundColor,
filled: true,
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
),
);
}
ListView _buildList() {
return ListView.builder(
controller: _scrollController,
itemCount: _messages.length,
itemBuilder: (context, index) {
var message = _messages[index];
return ChatMessageWidget(
text: message.text,
chatMessageType: message.chatMessageType,
);
},
);
}
void _scrollDown() {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
);
}
}
class ChatMessageWidget extends StatelessWidget {
const ChatMessageWidget(
{super.key, required this.text, required this.chatMessageType});
final String text;
final ChatMessageType chatMessageType;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
padding: const EdgeInsets.all(16),
color: chatMessageType == ChatMessageType.bot
? botBackgroundColor
: backgroundColor,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
chatMessageType == ChatMessageType.bot
? Container(
margin: const EdgeInsets.only(right: 16.0),
child: CircleAvatar(
backgroundColor: const Color.fromRGBO(16, 163, 127, 1),
child: Image.asset(
'assets/bot.png',
color: Colors.white,
scale: 1.5,
),
),
)
: Container(
margin: const EdgeInsets.only(right: 16.0),
child: const CircleAvatar(
child: Icon(
Icons.person,
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
child: Text(
text,
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(color: Colors.white),
),
),
],
),
),
],
),
);
}
}