import 'package:flutter/material.dart'; import 'package:web_socket_client/web_socket_client.dart'; import 'dart:convert'; import 'dart:io'; dynamic socket; String constructMessage({required String content, String? type, String? username, String? token}) { if (type == null) type = "message"; if (username == null) username = "max"; if (token == null) token = "750c63441033127dccaa91c16b21614e"; String jsonMessage = ''' { "type": "${type}", "username": "${username}", "token": "${token}", "content": "${content}" } '''; return jsonMessage; } String roomJoinMessage({required String room, String? content, String? type, String? username, String? token}) { if (content == null) content = ""; if (type == null) type = "message"; if (username == null) username = "max"; if (token == null) token = "750c63441033127dccaa91c16b21614e"; String jsonMessage = ''' { "type": "${type}", "username": "${username}", "token": "${token}", "room": "${room}", "content": "${room}" } '''; return jsonMessage; } void main() async { runApp(const MaterialApp(home: ChatScreen())); print("Chookchat Client Test"); print("Connecting to websocket..."); const wsUrl = 'ws://localhost:7070'; String jsonMessage = ''' { "type": "test", "username": "max", "token": "750c63441033127dccaa91c16b21614e", "content": "hello server!" } '''; final timeout = Duration(seconds: 10); const backoff = ConstantBackoff(Duration(seconds: 1)); socket = WebSocket(Uri.parse('ws://localhost:7070/api/websocket'), timeout: timeout, backoff: backoff); socket.messages.listen((message) { if (message == 'ping') { socket.send('pong'); } }); } class ChatScreen extends StatefulWidget { const ChatScreen({Key? key}) : super(key: key); @override _ChatScreenState createState() => _ChatScreenState(); } class _ChatScreenState extends State { List messages = []; final _scrollController = ScrollController(); bool hasSetRoom = false; @override void initState() { super.initState(); socket.messages.listen((message) { setState(() { if (message != 'ping') { print(message); messages.add(message); } else { if (!hasSetRoom) { print(roomJoinMessage(room: "general", type: "joinRoom")); socket.send(roomJoinMessage(room: "general", type: "joinRoom")); hasSetRoom = true; } } WidgetsBinding.instance.addPostFrameCallback((_) { _scrollController.animateTo( _scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut, ); }); }); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Chookchat'), leading: Builder( builder: (BuildContext context) { return IconButton( icon: const Icon(Icons.menu), onPressed: () { Scaffold.of(context).openDrawer(); }, ); }, ), ), drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration( color: Colors.blue, ), child: Text( 'Menu', style: TextStyle( color: Colors.white, fontSize: 24, ), ), ), ListTile( leading: const Icon(Icons.settings), title: const Text('Settings'), onTap: () { Navigator.pop(context); }, ), ListTile( leading: const Icon(Icons.help), title: const Text('Help'), onTap: () { Navigator.pop(context); }, ), ], ), ), body: Column( children: [ Expanded( child: ListView.builder( controller: _scrollController, itemCount: messages.length, itemBuilder: (context, index) { return ListTile( title: Text(messages[index]), ); }, ), ), Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( offset: const Offset(0, -2), blurRadius: 4, color: Colors.black.withOpacity(0.1), ), ], ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Row( children: [ Expanded( child: TextField( decoration: const InputDecoration( hintText: 'Type a message...', border: InputBorder.none, ), onSubmitted: (text) { socket.send(constructMessage(content: text)); }, ), ), ], ), ), ), ], ), ); } @override void dispose() { _scrollController.dispose(); super.dispose(); } }