Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
YuJuncen committed Jul 24, 2023
2 parents 9c5052c + 3af7a4b commit 3894e8b
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 989 deletions.
224 changes: 113 additions & 111 deletions lib/components/chat.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:moyubie/components/markdown.dart';
import 'package:moyubie/components/prompts.dart';
import 'package:moyubie/controller/chat_room.dart';
import 'package:moyubie/controller/message.dart';
import 'package:moyubie/controller/prompt.dart';
import 'package:moyubie/controller/chat_room.dart' as comp;
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:uuid/uuid.dart';
import 'dart:math';

import '../repository/chat_room.dart';

var uuid = const Uuid();

class ChatWindow extends StatefulWidget {
const ChatWindow({super.key});

Expand All @@ -27,110 +22,88 @@ class _ChatWindowState extends State<ChatWindow> {
final _formKey = GlobalKey<FormState>();
final _scrollController = ScrollController();

final uuid = const Uuid();

@override
Widget build(BuildContext context) {
return GetX<comp.ChatRoomController>(builder: (controller) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Expanded(
child: GetX<MessageController>(
builder: (controller) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToNewMessage();
});
if (controller.messageList.isNotEmpty) {
return ListView.builder(
controller: _scrollController,
itemCount: controller.messageList.length,
itemBuilder: (context, index) {
return _buildMessageCard(controller.messageList[index]);
},
);
} else {
return GetX<PromptController>(builder: ((controller) {
if (controller.prompts.isEmpty) {
return const Center(
child: Center(child: Text("正在加载prompts...")),
);
} else if (controller.prompts.isNotEmpty) {
return PromptsView(controller.prompts, (value) {
_controller.text = value;
});
} else {
return const Center(child: Text("加载prompts列表失败,请检查网络"));
}
}));
}
},
),
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Expanded(
child: GetX<MessageController>(
builder: (controller) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToNewMessage();
});
if (controller.messageList.isNotEmpty) {
return ListView.builder(
controller: _scrollController,
itemCount: controller.messageList.length,
itemBuilder: (context, index) {
return _buildMessageCard(controller.messageList[index]);
},
);
} else {
return const Center(
child: Center(child: Text("Empty")),
);
}
},
),
const SizedBox(height: 16),
Form(
key: _formKey, // 将 GlobalKey 赋值给 Form 组件的 key 属性
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: _handleKeyEvent,
child: Row(
children: [
Expanded(
child: TextFormField(
style: const TextStyle(fontSize: 13),
controller: _controller,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
hintText:
"Send to ".tr + _currentRoomName(controller),
floatingLabelBehavior: FloatingLabelBehavior.auto,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
),
filled: true,
),
const SizedBox(height: 16),
Form(
key: _formKey, // 将 GlobalKey 赋值给 Form 组件的 key 属性
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: _handleKeyEvent,
child: Row(
children: [
Expanded(
child: TextFormField(
style: const TextStyle(fontSize: 16),
controller: _controller,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
hintText: "@ai talk to AI",
floatingLabelBehavior: FloatingLabelBehavior.auto,
contentPadding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
),
autovalidateMode: AutovalidateMode.always,
maxLines: null,
filled: true,
),
autovalidateMode: AutovalidateMode.always,
maxLines: null,
),
const SizedBox(width: 16),
SizedBox(
height: 48,
child: ElevatedButton(
onPressed: () {
FocusManager.instance.primaryFocus?.unfocus();
_sendMessage();
},
style: ElevatedButton.styleFrom(
backgroundColor:
const Color.fromARGB(255, 250, 94, 83),
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(8))),
padding: EdgeInsets.zero,
),
child: const Icon(Icons.send),
),
const SizedBox(width: 16),
SizedBox(
height: 48,
child: ElevatedButton(
onPressed: () {
_sendMessage();
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color.fromARGB(255, 250, 94, 83),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8))),
padding: EdgeInsets.zero,
),
child: const Icon(Icons.send),
),
],
),
),
],
),
),
const SizedBox(height: 25),
],
),
);
});
}

String _currentRoomName(comp.ChatRoomController controller) {
var idx = controller.currentRoomIndex.value.value;
if (idx == -1) {
return "";
}
return controller.roomList[idx].name;
),
const SizedBox(height: 25),
],
),
);
}

void _sendMessage() {
Expand All @@ -151,7 +124,7 @@ class _ChatWindowState extends State<ChatWindow> {
final newMessage = Message(
uuid: uuid.v1(),
userName: 'User',
createTime: DateTime.now(),
createTime: DateTime.now().toUtc(),
message: message,
source: MessageSource.user,
ask_ai: ask_ai,
Expand All @@ -163,32 +136,57 @@ class _ChatWindowState extends State<ChatWindow> {
Widget _buildMessageCard(Message message) {
IconData icon = FontAwesomeIcons.question;
String name = "?";
String timeStr = message.createTime.toLocal().toString().substring(0, 19);
Color? color;
Widget? text_box;
Widget? msg_box;

final isDark = Theme.of(context).brightness == Brightness.dark;
switch (message.source) {
case MessageSource.user:
icon = FontAwesomeIcons.fish;
name = "User";
color = Color.fromARGB(255, 156, 225, 111);
text_box = Padding(
color = const Color.fromARGB(255, 156, 225, 111);
msg_box = Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText(
message.message,
style: TextStyle(color: Color.fromARGB(255, 0, 0, 0)),
style: const TextStyle(
fontSize: 16,
color: Color.fromARGB(255, 0, 0, 0),
),
),
);
break;
case MessageSource.bot:
icon = FontAwesomeIcons.robot;
name = "bot";
name = "Bot";
color = isDark
? Color.fromARGB(255, 92, 89, 89)
: Color.fromARGB(255, 255, 255, 255);
text_box = Markdown(text: message.message);
? const Color.fromARGB(255, 92, 89, 89)
: const Color.fromARGB(255, 255, 255, 255);
msg_box = Markdown(text: message.message);
break;
default:
}

Widget? nameBox = Text(
name,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
),
);

Widget? timeBox = Container(
padding: const EdgeInsets.fromLTRB(0, 2, 0, 0),
alignment: Alignment.bottomLeft,
child: Text(
timeStr,
style: const TextStyle(
fontSize: 10,
),
),
);

return Column(
children: [
Row(
Expand All @@ -201,17 +199,21 @@ class _ChatWindowState extends State<ChatWindow> {
const SizedBox(
width: 5,
),
Text(name),
nameBox,
const SizedBox(
width: 5,
),
timeBox,
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
Flexible(
child: Card(
color: color,
margin: const EdgeInsets.all(8),
child: text_box,
child: msg_box,
),
),
],
Expand Down
31 changes: 17 additions & 14 deletions lib/components/chat_room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,24 @@ class DetailsPane extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetX<comp.ChatRoomController>(builder: (controller) {
return Scaffold(
appBar: AppBar(
foregroundColor: Colors.white,
backgroundColor: Color.fromARGB(255, 70, 70, 70),
toolbarHeight: 40,
automaticallyImplyLeading: false,
leading: onClose == null
? null
: IconButton(icon: const Icon(Icons.close), onPressed: onClose),
title: Text(
_currentRoomName(controller),
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold(
appBar: AppBar(
foregroundColor: Colors.white,
backgroundColor: Color.fromARGB(255, 70, 70, 70),
toolbarHeight: 40,
automaticallyImplyLeading: false,
leading: onClose == null
? null
: IconButton(icon: const Icon(Icons.close), onPressed: onClose),
title: Text(
_currentRoomName(controller),
),
actions: const [ChatDetailButton()],
),
actions: const [ChatDetailButton()],
body: const ChatWindow(),
),
body: const ChatWindow(),
);
});
}
Expand Down Expand Up @@ -203,7 +206,7 @@ class NewChatButton extends StatelessWidget {
_addNewChatRoom(BuildContext context) {
final comp.ChatRoomController chatRoomController = Get.find();
const uuid = Uuid();
var createTime = DateTime.now();
var createTime = DateTime.now().toUtc();
repo.ChatRoom chatRoom = repo.ChatRoom(
uuid: uuid.v1(),
name: "New Chat Room",
Expand Down
Loading

0 comments on commit 3894e8b

Please sign in to comment.