diff options
author | ryo <ryo@nopwd.lol> | 2025-04-11 20:22:41 +0000 |
---|---|---|
committer | ryo <ryo@nopwd.lol> | 2025-04-11 20:22:41 +0000 |
commit | 8e12f4f68cc907668a0ad91b854a80f21b921071 (patch) | |
tree | f9f3dffba3fa0284fbef050367cdc6e4ffbc0f42 /main.dart |
Diffstat (limited to 'main.dart')
-rw-r--r-- | main.dart | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/main.dart b/main.dart new file mode 100644 index 0000000..266b670 --- /dev/null +++ b/main.dart @@ -0,0 +1,285 @@ +import 'package:flutter/material.dart'; +import 'dart:io'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + brightness: Brightness.light, + ), + darkTheme: ThemeData( + brightness: Brightness.dark, + ), + themeMode: ThemeMode.dark, + home: const MyHomePage(title: 'Socket Demo'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + final String title; + + @override + State<MyHomePage> createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State<MyHomePage> { + late Socket _socket; + final TextEditingController _inputController = TextEditingController(); + final List<String> _msgs = []; + String address = ""; + + @override + void initState() { + super.initState(); + _connect(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.purple, + title: Text(widget.title), + ), + body: Column(children: [ + Expanded( + child: ListView.builder( + padding: EdgeInsets.all(10.0), + itemCount: _msgs.length, + itemBuilder: (context, index) { + var msg = _msgs[index]; + String user = ""; + String data = ""; + int i; + for (i = 0; i < msg.length; i++) { + if (msg[i] == '=') { + i++; + break; + } + user += msg[i]; + } + for (; i < msg.length; i++) { + data += msg[i]; + } + + if (user == address) { + return BubbleSend(message: data, user: user); + } else { + return BubbleReceive(message: data, user: user); + } + }, + )), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Expanded( + child: TextField( + controller: _inputController, + onSubmitted: (value) { + _send(); + }, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Enter message', + ), + ), + ), + IconButton( + icon: Icon(Icons.send), + onPressed: () { + _send(); + }, + ), + ], + ), + ), + ]), + ); + } + + void _connect() async { + try { + _socket = await Socket.connect("127.0.0.1", 7654); + address = "${_socket.address.address}:${_socket.port}"; + print("my address: $address"); + toast("Connected to 127.0.0.1:7654", 0); + + _socket.listen( + (data) { + final message = String.fromCharCodes(data).trim(); + print('received: $message'); + if (message[0] == '!') { + String name = ""; + for (int i = 1; i < message.length; i++) { + name += message[i]; + } + address = name; + } else { + setState(() { + _msgs.addAll(message.split('\n')); + }); + // print("_msgs: $_msgs"); + } + }, + onDone: () { + print('Server disconnected.'); + toast('Server disconnected', 1); + _socket.destroy(); + }, + onError: (error) { + print('Error: $error'); + toast('Error: $error', 1); + _socket.destroy(); + }, + ); + } catch (e) { + print('Error: $e'); + toast('An unexpected error occurred: $e', 1); + } + } + + void _send() { + final value = _inputController.text; + if (value.isNotEmpty) { + _socket.write('$value\n'); + _inputController.clear(); + } + } + + void toast(String msg, int type) { + Color bg = Color(0x7aa2f7ff); + Color fg = Colors.black; + switch (type) { + case 0: + bg = Colors.green; + break; + case 1: + bg = Colors.red; + break; + } + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(msg, style: TextStyle(color: fg)), + backgroundColor: bg, + )); + } +} + +class BubbleReceive extends StatelessWidget { + final String message; + final String user; + const BubbleReceive({super.key, required this.message, required this.user}); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Flexible( + child: Container( + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.blueGrey, + borderRadius: BorderRadius.circular(15), + ), + child: Text( + message, + style: const TextStyle(color: Colors.white, fontSize: 15), + ), + ), + ), + SizedBox( + width: 20, + height: 20, + child: CustomPaint(painter: Triangle(false, Colors.blueGrey)), + ), + ], + ), + Text(user), + SizedBox(height: 10), + ]); + } +} + +class BubbleSend extends StatelessWidget { + final String message; + final String user; + const BubbleSend({super.key, required this.message, required this.user}); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + width: 20, + height: 20, + child: CustomPaint(painter: Triangle(true, Colors.indigo)), + ), + Container( + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.indigo, + borderRadius: BorderRadius.circular(15), + ), + child: Text( + message, + style: const TextStyle(color: Colors.white, fontSize: 15), + ), + ), + ], + ), + Text(user), + SizedBox(height: 10), + ]); + } +} + +class Triangle extends CustomPainter { + final Color backgroundColor; + final bool send; + Triangle(this.send, this.backgroundColor); + + @override + void paint(Canvas canvas, Size size) { + var paint = Paint()..color = backgroundColor; + + var path = Path(); + if (send) { + path.moveTo(20, 0); + path.lineTo(5, 15); + path.lineTo(35, 15); + } else { + path.lineTo(15, 15); + path.lineTo(-15, 15); + } + path.close(); + canvas.drawPath(path, paint); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} |