diff --git a/lib/chatting/chat_page.dart b/lib/chatting/chat_page.dart index 197812c..459a021 100644 --- a/lib/chatting/chat_page.dart +++ b/lib/chatting/chat_page.dart @@ -1,30 +1,99 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:signalr_netcore/http_connection_options.dart'; +import 'package:signalr_netcore/hub_connection.dart'; +import 'package:signalr_netcore/hub_connection_builder.dart'; +import 'package:signalr_netcore/ihub_protocol.dart'; +import 'package:signalr_netcore/itransport.dart'; +import 'package:zoomerm_client/chatting/receiver.dart'; import 'package:zoomerm_client/chatting/service.dart'; import 'package:zoomerm_client/global/global.dart'; +import 'package:zoomerm_client/helpers/http_helper.dart'; import 'package:zoomerm_client/models/chatting_model.dart'; class ChattingPage extends StatefulWidget { - const ChattingPage({super.key}); + final chatid; + final interlocutor; + ChattingPage({super.key, required this.chatid, required this.interlocutor}); @override State createState() => _ChattingPageState(); } class _ChattingPageState extends State { + ScrollController _scrollController = ScrollController(); List chattingPage = []; + final TextEditingController _messageController = TextEditingController(); + HubConnection? hubConnection; + @override void initState() { super.initState(); + _initConnection(); + } + + + + @override + void dispose() { + hubConnection?.stop(); + _messageController.dispose(); + super.dispose(); } Future populateChatting() async { - chattingPage = await ChattingService().getChat("3a7d1341-993e-4981-93a2-03f912c06c97"); + List tempItems = await ChattingService().getChat(widget.chatid); + chattingPage = + tempItems.reversed.toList(); } + void _initConnection() async { + MessageHeaders headers = MessageHeaders(); + + hubConnection = HubConnectionBuilder() + .withUrl('${HUB_ENDPOINT}?token=${currentLogin?.token}') + .withAutomaticReconnect(retryDelays: [2000, 5000, 10000]).build(); + + try { + await hubConnection?.start(); + hubConnection?.on('newChatMessage', (messageData) { + if (messageData is List) { + for (var element in messageData) { + String messageMap = jsonEncode(element); + Items tempItems = new Items(sender: new Sender(userName: widget.interlocutor), content: messageMap); + setState(() { + chattingPage.add(tempItems); + _scrollController.jumpTo(_scrollController.position.minScrollExtent); + }); + } + } else { + debugPrint("Invalid message data format: $messageData"); + } + }); + } catch (e) { + debugPrint('Connection error: $e'); + } +} + + void sendMessage(String message) async { + if (hubConnection?.state == HubConnectionState.Connected) { + debugPrint("Sent message"); + await hubConnection!.invoke('Send', + args: [widget.chatid, message]); + setState(() { + _scrollController.jumpTo(_scrollController.position.minScrollExtent); + }); + } else { + debugPrint('Not connected to SignalR'); + } + } + @override Widget build(BuildContext context) { + return Scaffold( appBar: AppBar( elevation: 0, @@ -61,7 +130,7 @@ class _ChattingPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - "Random Person Name", + widget.interlocutor, style: TextStyle(fontSize: 16), ), SizedBox( @@ -82,47 +151,47 @@ class _ChattingPageState extends State { body: Stack( children: [ FutureBuilder( - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.none || - chattingPage.length == 0) { - return Center(child: CircularProgressIndicator()); - } - return ListView.builder( - itemCount: chattingPage.length, - shrinkWrap: true, - padding: EdgeInsets.only(top: 10, bottom: 70), - physics: NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return Container( - padding: EdgeInsets.only( - left: 14, right: 14, top: 10, bottom: 10), - child: Align( - alignment: - (chattingPage[index].sender?.userName != "ismail" - ? Alignment.topLeft - : Alignment.topRight), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: - (chattingPage[index].sender?.userName != "ismail" - ? Colors.grey.shade200 - : Colors.blue[200]), - ), - padding: EdgeInsets.all(16), - child: Text( - chattingPage[index].content.toString(), - style: TextStyle(fontSize: 15), - ), - ), - ), - ); - }, - ); - }, - future: populateChatting(), - ), - + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.none || + chattingPage.length == 0) { + return Center(child: CircularProgressIndicator()); + } + return ListView.builder( + controller: _scrollController, + itemCount: chattingPage.length, + shrinkWrap: true, + reverse: true, + padding: EdgeInsets.only(top: 10, bottom: 70), + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return Container( + padding: EdgeInsets.only( + left: 14, right: 14, top: 10, bottom: 10), + child: Align( + alignment: + (chattingPage[index].sender?.userName == widget.interlocutor + ? Alignment.topLeft + : Alignment.topRight), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: (chattingPage[index].sender?.userName == widget.interlocutor + ? Colors.grey.shade200 + : Colors.blue[200]), + ), + padding: EdgeInsets.all(16), + child: Text( + chattingPage[index].content.toString(), + style: TextStyle(fontSize: 15), + ), + ), + ), + ); + }, + ); + }, + future: populateChatting(), + ), Align( alignment: Alignment.bottomLeft, child: Container( @@ -148,12 +217,12 @@ class _ChattingPageState extends State { ), ), ), - SizedBox( width: 15, ), Expanded( child: TextField( + controller: _messageController, maxLines: null, decoration: InputDecoration( hintText: "Write message...", @@ -166,7 +235,18 @@ class _ChattingPageState extends State { width: 15, ), FloatingActionButton( - onPressed: () {}, + onPressed: () { + sendMessage(_messageController.text); + setState(() { + Items tempSenderItems = new Items( + content: _messageController.text, + sender: Sender(userName: widget.interlocutor)); + + chattingPage.add(tempSenderItems); + _messageController.clear(); + }); + + }, child: Icon( Icons.send, color: Colors.white, diff --git a/lib/chatting/receiver.dart b/lib/chatting/receiver.dart new file mode 100644 index 0000000..ed97e01 --- /dev/null +++ b/lib/chatting/receiver.dart @@ -0,0 +1,11 @@ +class MessageDate { + final String content; + final String createdDate; + + MessageDate({required this.content, required this.createdDate}); + + @override + String toString() { + return 'MessageDate{content: $content, createdDate: $createdDate}'; + } +} \ No newline at end of file diff --git a/lib/chatting/service.dart b/lib/chatting/service.dart index a970f95..bd51bd4 100644 --- a/lib/chatting/service.dart +++ b/lib/chatting/service.dart @@ -20,7 +20,7 @@ class ChattingService extends BlocService { Future> getChat(String uuid) async { List charRes = []; - var rs = await HttpHelper.get("${DOMAIN}api/chats/p2p/${uuid}/messages", bearerToken: currentLogin?.token); + var rs = await HttpHelper.get("${DOMAIN}api/chats/p2p/${uuid}/messages?pageSize=1000", bearerToken: currentLogin?.token); print(await HttpHelper.get("api/chats/p2p/${uuid}/messages", bearerToken: currentLogin?.token)); if (rs.statusCode == 200) { print("For chatting request 202"); diff --git a/lib/helpers/http_helper.dart b/lib/helpers/http_helper.dart index 7e2fb2f..147f674 100644 --- a/lib/helpers/http_helper.dart +++ b/lib/helpers/http_helper.dart @@ -9,6 +9,7 @@ import 'package:zoomerm_client/models/login_model.dart'; //const DOMAIN = 'http://localhost:5135'; For developing const DOMAIN = 'https://localhost:7065/'; +const HUB_ENDPOINT = 'https://localhost:7065/hubs/chats/p2p'; const LOGIN_ENDPOINT = DOMAIN + 'login'; class HttpHelper { static Future post(String url, Map body, diff --git a/lib/helpers/login_helper.dart b/lib/helpers/login_helper.dart index eb1d838..2b08ed7 100644 --- a/lib/helpers/login_helper.dart +++ b/lib/helpers/login_helper.dart @@ -19,9 +19,6 @@ class LocalHelper { static Future getAccountFromLocal() async { SharedPreferences pref = await SharedPreferences.getInstance(); var account = pref.getString('login'); - print(account); - print("printing account"); - print(account.toString()); if (account != null) { return LoginModel.fromJson(jsonDecode(account)); } diff --git a/lib/homepage/chat_page.dart b/lib/homepage/chat_page.dart index 050aeae..bdf4ac8 100644 --- a/lib/homepage/chat_page.dart +++ b/lib/homepage/chat_page.dart @@ -12,7 +12,7 @@ class ChatPage extends StatefulWidget { class _ChatPageState extends State { List chats = []; - + @override void initState() { // chats = HomePageService().getAllChat(); @@ -31,7 +31,7 @@ class _ChatPageState extends State { } } } - + @override Widget build(BuildContext context) { @@ -46,8 +46,12 @@ class _ChatPageState extends State { return ListView.separated (itemBuilder: ((context, index) { return ListTile( + onTap: () { - context.go('/mychats'); + context.goNamed('mychats', + pathParameters: + {'chatid': chats[index].id.toString(), 'interl': chats[index].interlocutor!.userName.toString() + }); }, title: Text(chats[index].interlocutor!.userName.toString()), subtitle: Text('TYT SOOBSHENIYA BUDUT...'), diff --git a/lib/homepage/home_page.dart b/lib/homepage/home_page.dart index 674fba4..a6df586 100644 --- a/lib/homepage/home_page.dart +++ b/lib/homepage/home_page.dart @@ -4,6 +4,7 @@ import 'package:zoomerm_client/blocs/login_bloc.dart/service.dart'; import 'package:zoomerm_client/global/global.dart'; import 'package:zoomerm_client/homepage/chat_page.dart'; import 'package:zoomerm_client/homepage/forum_page.dart'; +import 'package:zoomerm_client/homepage/search_add_dialog.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -88,6 +89,15 @@ class _HomePageState extends State { ], ), ), + floatingActionButton: FloatingActionButton( + child: Icon(Icons.add), + hoverColor: Colors.green, + backgroundColor: Colors.red, + foregroundColor: Colors.white, + onPressed: () { + showDialog(context: context, builder: (context) => SearchAndAddDialog()); + }, + ), bottomNavigationBar: NavigationBar( onDestinationSelected: (int index) { setState(() { diff --git a/lib/homepage/search_add_dialog.dart b/lib/homepage/search_add_dialog.dart new file mode 100644 index 0000000..9a3d28c --- /dev/null +++ b/lib/homepage/search_add_dialog.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; + +class SearchAndAddDialog extends StatefulWidget { + const SearchAndAddDialog({super.key}); + + @override + State createState() => _SearchAndAddDialogState(); +} + +class _SearchAndAddDialogState extends State { + final List names = ['ismail', 'Bob', 'Charlie', 'Diana']; + List results = []; + TextEditingController searchController = TextEditingController(); + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + searchController.dispose(); + // TODO: implement dispose + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text("Search user"), + titleTextStyle: TextStyle(fontWeight: FontWeight.bold, + color: Colors.black, fontSize: 20), + actions: [ + Row( + children: [ + SizedBox( + width: 200, + child: TextFormField( + controller: searchController, + decoration: InputDecoration( + labelText: "put the name or id", + border: OutlineInputBorder() + ), + ), + ), + IconButton(onPressed: (){ + for(var temps in names) { + print(searchController.text); + if(temps == searchController.text){ + print("Added someone"); + setState(() { + debugPrint("Added someone"); + results.add(temps); + }); + } + } + }, + icon: Icon(Icons.search)) + + ], + ) + ], + content: Card( + child: Text(results.isEmpty ? "No results" : results[0]), + ) + ); + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index c17be0a..e6b23d4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -34,10 +34,11 @@ final GoRouter _router = GoRouter( return LoginEnter(); }), GoRoute( - path: '/mychats', - builder: (BuildContext context, GoRouterState state) { - return ChattingPage(); - }), + name: 'mychats', + path: '/mychats/:chatid/:interl', + builder: (context, state) => ChattingPage( + chatid: state.pathParameters['chatid'], interlocutor: state.pathParameters['interl']) + ), ] ); diff --git a/lib/profile_settings/profile_settings.dart b/lib/profile_settings/profile_settings.dart new file mode 100644 index 0000000..eccf519 --- /dev/null +++ b/lib/profile_settings/profile_settings.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class ProfileSettings extends StatefulWidget { + const ProfileSettings({super.key}); + + @override + State createState() => _ProfileSettingsState(); +} + +class _ProfileSettingsState extends State { + @override + Widget build(BuildContext context) { + return Container(); + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index fbaa9fb..e202ace 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -65,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" cupertino_icons: dependency: "direct main" description: @@ -173,6 +181,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.18.1" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" lints: dependency: transitive description: @@ -205,6 +221,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.0" + message_pack_dart: + dependency: transitive + description: + name: message_pack_dart + sha256: "71b9f0ff60e5896e60b337960bb535380d7dba3297b457ac763ccae807385b59" + url: "https://pub.dev" + source: hosted + version: "2.0.1" meta: dependency: transitive description: @@ -269,6 +293,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" provider: dependency: transitive description: @@ -333,6 +365,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + signalr_netcore: + dependency: "direct main" + description: + name: signalr_netcore + sha256: "7e04ab4b541bff9437f83af701ef7b0c413c65437df67a65cf5580e5b842051e" + url: "https://pub.dev" + source: hosted + version: "1.3.7" sky_engine: dependency: transitive description: flutter @@ -346,6 +394,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sse: + dependency: transitive + description: + name: sse + sha256: "8168874cdbd42c36ea118ba9f88a656ad97f604f28c976c61cb6d5b281c5319c" + url: "https://pub.dev" + source: hosted + version: "4.1.4" + sse_channel2: + dependency: transitive + description: + name: sse_channel2 + sha256: be9bd58151b38e2cceb5c507bad746efa40c601a22b63d46e1a7cb60fc5cd24f + url: "https://pub.dev" + source: hosted + version: "0.0.4" stack_trace: dependency: transitive description: @@ -386,6 +450,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" typed_data: dependency: transitive description: @@ -394,6 +466,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" vector_math: dependency: transitive description: @@ -410,6 +490,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5a04bac..695c89a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,7 @@ dependencies: bloc_provider: ^1.0.0 equatable: ^2.0.5 adaptive_theme: ^3.6.0 + signalr_netcore: ^1.3.7 dev_dependencies: flutter_test: