首页 home_page
import 'package:fchatapp/src/pages/group/group_page.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextEditingController nameController = TextEditingController();
final formKey = GlobalKey<FormState>();
var uuid = Uuid();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('Group Chat App'),
),
body: Center(
child: TextButton(
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text('请输入你的昵称'),
content: Form(
key: formKey,
child: TextFormField(
controller: nameController,
validator: (value) {
if (value == null || value.length < 3) {
return 'User must provide name(at least 3 char)';
}
return null;
},
),
),
actions: [
TextButton(
onPressed: () {
nameController.clear();
Navigator.pop(context);
},
child: Text(
'取消',
style: TextStyle(
fontSize: 16,
color: Colors.green,
),
),
),
TextButton(
onPressed: () {
if (!formKey.currentState!.validate()) {
return;
}
String name = nameController.text;
nameController.clear();
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GroupPage(
name: name,
userId: uuid.v1(),
),
),
);
},
child: Text(
'进入',
style: TextStyle(
fontSize: 16,
color: Colors.blue,
),
),
),
],
),
),
child: Text(
'进入聊天室',
style: TextStyle(
color: Colors.teal,
fontSize: 16,
),
),
),
),
);
}
}
依赖(socketio 2.0 对应 node 的 socketio 服务器 3.x 和 4.x)
import 'package:flutter/material.dart';
class OtherMsgWidget extends StatelessWidget {
final String sender;
final String msg;
const OtherMsgWidget({Key? key, required this.msg, required this.sender})
: super(key: key);
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomLeft,
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 60,
),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
sender,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(
height: 3,
),
Text(
msg,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
],
),
),
),
),
);
}
}
import 'package:flutter/material.dart';
class OwnMsgWidget extends StatelessWidget {
final String sender;
final String msg;
const OwnMsgWidget({Key? key, required this.msg, required this.sender})
: super(key: key);
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomRight,
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 60,
),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.teal,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
sender,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.yellow,
),
),
const SizedBox(
height: 3,
),
Text(
msg,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
),
),
),
);
}
}
group_page.dart
import 'package:fchatapp/src/foundation/msg_widget/other_msg_widget.dart';
import 'package:fchatapp/src/foundation/msg_widget/own_msg_widget.dart';
import 'package:fchatapp/src/pages/group/msg_model.dart';
import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
class GroupPage extends StatefulWidget {
final String name;
final String userId;
const GroupPage({Key? key, required this.name, required this.userId})
: super(key: key);
@override
State<GroupPage> createState() => _GroupPageState();
}
class _GroupPageState extends State<GroupPage> {
IO.Socket? socket;
List<MsgMoel> msgList = [];
TextEditingController _msgController = TextEditingController();
@override
void initState() {
connect();
}
void connect() {
socket = IO.io("http://192.168.2.228:3000", <String, dynamic>{
'transports': ['websocket'],
'autoConnect': false,
});
socket!.connect();
print("we're here");
socket!.onConnect((_) {
print("connect");
socket!.on("broadcastMsg", (model) {
print(model);
setState(() {
if (model['userId'] != widget.userId) {
setState(() {
msgList.add(
MsgMoel(
msg: model['msg'],
type: model["type"],
sender: model['senderName'],
),
);
});
}
});
});
});
}
void sendMsg(String msg, String senderName) {
MsgMoel ownMsg = MsgMoel(msg: msg, type: "ownMsg", sender: senderName);
msgList.add(ownMsg);
setState(() {
msgList;
});
socket!.emit(
'sendMsg',
{
"type": "ownMsg",
"msg": msg,
"senderName": senderName,
"userId": widget.userId,
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Anomynous Group'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: msgList.length,
itemBuilder: (context, index) {
if (msgList[index].type == "ownMsg") {
return OwnMsgWidget(
msg: msgList[index].msg, sender: msgList[index].sender);
} else {
return OtherMsgWidget(
msg: msgList[index].msg, sender: msgList[index].sender);
}
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
child: Row(
children: <Widget>[
Expanded(
child: TextFormField(
controller: _msgController,
decoration: const InputDecoration(
hintText: "在这里输入内容...",
border: OutlineInputBorder(
borderSide: BorderSide(
width: 2,
),
),
),
),
),
IconButton(
onPressed: () {
String msg = _msgController.text;
_msgController.clear();
if (msg.isEmpty) {
return;
}
sendMsg(msg, widget.name);
},
icon: const Icon(
Icons.send,
color: Colors.teal,
))
],
),
),
],
),
);
}
}
msg_model.dart
class MsgMoel {
String type;
String msg;
String sender;
MsgMoel({required this.msg, required this.type, required this.sender});
}