From 2619c9dcdf519a2446aa59a01c19ba575e0b8d15 Mon Sep 17 00:00:00 2001 From: suresh Date: Mon, 8 Apr 2024 14:36:06 +0530 Subject: [PATCH] Chat function added --- android/app/google-services.json | 67 +++++ lib/chat/chat_controller.dart | 88 ++++++ lib/chat/chatmessage.dart | 15 + lib/chat/chatpage.dart | 235 +++++++++++++++ lib/chat/chatzoomable_image.dart | 40 +++ lib/common/dashboard.dart | 29 ++ lib/common/settings.dart | 2 + lib/main.dart | 12 + lib/pages/call.dart | 271 ++++++++++++++++++ lib/pages/index.dart | 120 ++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 4 + pubspec.lock | 50 +++- pubspec.yaml | 5 +- .../flutter/generated_plugin_registrant.cc | 9 + windows/flutter/generated_plugins.cmake | 3 + 15 files changed, 938 insertions(+), 12 deletions(-) create mode 100644 android/app/google-services.json create mode 100644 lib/chat/chat_controller.dart create mode 100644 lib/chat/chatmessage.dart create mode 100644 lib/chat/chatpage.dart create mode 100644 lib/chat/chatzoomable_image.dart create mode 100644 lib/pages/call.dart create mode 100644 lib/pages/index.dart diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..3d99856 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,67 @@ +{ + "project_info": { + "project_number": "60196905754", + "project_id": "health-pharma-67443", + "storage_bucket": "health-pharma-67443.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:60196905754:android:05ea9ecef5280e578a42a3", + "android_client_info": { + "package_name": "com.arminta.healthcare_pharmacy" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:60196905754:android:44f95d2cea26698a8a42a3", + "android_client_info": { + "package_name": "com.arminta.healthcare_user" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:60196905754:android:a35c084e291315488a42a3", + "android_client_info": { + "package_name": "com.arminta.healthparma" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/lib/chat/chat_controller.dart b/lib/chat/chat_controller.dart new file mode 100644 index 0000000..f20b789 --- /dev/null +++ b/lib/chat/chat_controller.dart @@ -0,0 +1,88 @@ +import 'dart:io'; + +import 'package:firebase_storage/firebase_storage.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'chatmessage.dart'; + + +class ChatController extends GetxController { + final CollectionReference _messagesCollection = + FirebaseFirestore.instance.collection('messages'); + + // Observable list of messages + RxList messages = [].obs; + + void sendMessage(String messageContent, String messageType, bool isText) async { + try { + await _messagesCollection.add({ + 'messageContent': messageContent, + 'messageType': messageType, + 'isText': isText, + 'timestamp': Timestamp.now(), + }); + print("Message sent successfully"); + } catch (e) { + print('Error sending message: $e'); + } + } + + Future uploadImage(File image, String id) async { + try { + String fileName = DateTime.now().millisecondsSinceEpoch.toString(); + Reference storageReference = + FirebaseStorage.instance.ref().child('products/$fileName'); + SettableMetadata metadata = SettableMetadata(contentType: 'image/jpeg'); + UploadTask uploadTask = storageReference.putFile(image, metadata); + + String temporaryMessageId = UniqueKey().toString(); + messages.add(ChatMessage( + messageContent: 'Uploading...', + messageType: id, + isText: true, + temporaryMessageId: temporaryMessageId, + )); + + TaskSnapshot taskSnapshot = await uploadTask; + String downloadURL = await storageReference.getDownloadURL(); + + // Replace the temporary message with the uploaded image + int index = messages.indexWhere((message) => message.temporaryMessageId == temporaryMessageId); + if (index != -1) { + messages[index] = ChatMessage( + messageContent: downloadURL, + messageType: id, + isText: false, + temporaryMessageId: '', + ); + } + + print('Image uploaded successfully. Download URL: $downloadURL'); + return downloadURL; + } catch (e) { + print('Error uploading image: $e'); + throw e; + } + } + + Stream getMessagesStream() { + return _messagesCollection.orderBy('timestamp').snapshots(); + } + + @override + void onInit() { + super.onInit(); + // Listen for changes in the messages collection and update the local list + getMessagesStream().listen((QuerySnapshot snapshot) { + messages.assignAll(snapshot.docs.map((doc) => ChatMessage( + messageContent: doc['messageContent'], + messageType: doc['messageType'], + isText: doc['isText'], + temporaryMessageId: '', + ))); + }); + + + } +} diff --git a/lib/chat/chatmessage.dart b/lib/chat/chatmessage.dart new file mode 100644 index 0000000..03695f0 --- /dev/null +++ b/lib/chat/chatmessage.dart @@ -0,0 +1,15 @@ +import 'package:flutter/cupertino.dart'; + +class ChatMessage { + String messageContent; + String messageType; + bool isText; + String temporaryMessageId; // New property for temporary message identifier + + ChatMessage({ + required this.messageContent, + required this.messageType, + required this.isText, + required this.temporaryMessageId, // Include in the constructor + }); +} diff --git a/lib/chat/chatpage.dart b/lib/chat/chatpage.dart new file mode 100644 index 0000000..af12d97 --- /dev/null +++ b/lib/chat/chatpage.dart @@ -0,0 +1,235 @@ +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:healthcare_user/chat/chatzoomable_image.dart'; +import 'package:healthcare_user/common/settings.dart'; +import 'package:healthcare_user/pages/index.dart'; +import 'package:image_picker/image_picker.dart'; +import 'chat_controller.dart'; +import 'chatmessage.dart'; +import 'package:photo_view/photo_view.dart'; + +class ChatPage extends StatefulWidget { + const ChatPage({Key? key}); + + @override + State createState() => _ChatPageState(); +} + +class _ChatPageState extends State { + final ChatController chatController = Get.put(ChatController()); + final TextEditingController content = TextEditingController(); + final ImagePicker _picker = ImagePicker(); + XFile? _image; + var id="1"; + bool _sending = false; + final ScrollController _scrollController = ScrollController(); + + @override + void initState() { + super.initState(); + _scrollToBottom(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor:Colors.green, + elevation: 0, + automaticallyImplyLeading: false, + flexibleSpace: SafeArea( + child: Container( + padding: EdgeInsets.only(right: 16), + child: Row( + children: [ + IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Icon(Icons.arrow_back,color: Colors.black,), + ), + SizedBox(width: 2,), + CircleAvatar( + backgroundImage: NetworkImage(AppSettings.profilePictureUrl), + maxRadius: 20, + ), + SizedBox(width: 12,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(AppSettings.userName,style: TextStyle( fontSize: 16 ,fontWeight: FontWeight.w600),), + // SizedBox(height: 6,), + // Text("Online",style: TextStyle(color: Colors.grey.shade600, fontSize: 13),), + ], + ), + ), + /*IconButton( + onPressed: () { + UrlLauncher.launch("tel://8328206298"); + }, + icon: Icon(Icons.call, color: Colors.black), + ),*/ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => IndexPage()), + ); + }, + icon: Icon(Icons.videocam, color: Colors.black), + ), + ], + ), + ), + ), + ), + body: Stack( + children: [ + Obx(() => ListView.builder( + itemCount: chatController.messages.length, + shrinkWrap: true, + padding: EdgeInsets.only(top: 10, bottom: 80), // Adjust bottom padding to accommodate the input field + physics: ScrollPhysics(), + controller: _scrollController, + itemBuilder: (context, index) { + final data = chatController.messages[index]; + return Container( + padding: EdgeInsets.only( + left: 14, right: 14, top: 10, bottom: 10), + child: Align( + alignment: (data.messageType != id ? Alignment.topLeft : Alignment.topRight), + child: GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChatZoomableImage(data.messageContent), + ), + ); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: (data.messageType != id + ? Colors.grey.shade200 + : Colors.blue[200]), + ), + padding: EdgeInsets.all(16), + child: data.isText + ? Text(data.messageContent, style: TextStyle(fontSize: 15)) + : Image.network( + data.messageContent, + scale: 3, + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + ), + + ), + ); + }, + )), + Align(alignment: Alignment.bottomCenter,child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Container( + height: 60, + width: double.infinity, + color: Colors.white, + child: Row( + children: [ + GestureDetector( + onTap: getImage, + child: Container( + height: 30, + width: 30, + decoration: BoxDecoration( + color: Colors.lightBlue, + borderRadius: BorderRadius.circular(30), + ), + child: Icon(Icons.add, color: Colors.white, size: 20), + ), + ), + SizedBox(width: 15), + Expanded( + child: TextField( + controller: content, + decoration: InputDecoration( + hintText: "Write message...", + hintStyle: TextStyle(color: Colors.black54), + border: InputBorder.none, + ), + ), + ), + SizedBox(width: 15), + FloatingActionButton( + onPressed: () { + sendMessage(); + }, + child: Icon(Icons.send, color: Colors.white, size: 18), + backgroundColor: Colors.blue, + elevation: 0, + ), + ], + ), + ), + ),) + ], + ), + ); + } + + void _scrollToBottom() { + Future.delayed(Duration(milliseconds: 300), () { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: Duration(milliseconds: 300), + curve: Curves.easeInOut, + ); + } + }); + } + + Future getImage() async { + final XFile? image = + await _picker.pickImage(source: ImageSource.gallery); + if (image != null) { + setState(() { + _image = image; + }); + sendMessage(); // Call sendMessage function to send the selected image immediately + } + } + + void sendMessage() async { + String messageContent = content.text.trim(); + if (messageContent.isNotEmpty || _image != null) { + setState(() { + _sending = true; + }); + try { + if (_image != null) { + String imageUrl = + await chatController.uploadImage(File(_image!.path),'$id'); + chatController.sendMessage(imageUrl, '$id', false); + _image = null; // Clear the selected image after sending + } + if (messageContent.isNotEmpty) { + chatController.sendMessage(messageContent, '$id', true); + content.clear(); + } + } finally { + setState(() { + _sending = false; + }); + } + _scrollToBottom(); // Scroll to the bottom after sending message + } + } +} diff --git a/lib/chat/chatzoomable_image.dart b/lib/chat/chatzoomable_image.dart new file mode 100644 index 0000000..299de5e --- /dev/null +++ b/lib/chat/chatzoomable_image.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:healthcare_user/common/settings.dart'; +import 'package:photo_view/photo_view.dart'; + +class ChatZoomableImage extends StatelessWidget { + final String imageUrl; + + ChatZoomableImage(this.imageUrl); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: primaryColor, // Set the background color + title: Text('Preview Image'), // Set the title text + actions: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ), + body: Center( + child: imageUrl.isNotEmpty + ? PhotoView( + imageProvider: NetworkImage(imageUrl), + minScale: PhotoViewComputedScale.contained, + maxScale: PhotoViewComputedScale.contained * 3.0, + ) + : Image.asset( + 'images/mobilebg.png', // Path to your default image + fit: BoxFit.cover, + ), + ), + ); + } +} + diff --git a/lib/common/dashboard.dart b/lib/common/dashboard.dart index 4e41b5e..7f0520e 100644 --- a/lib/common/dashboard.dart +++ b/lib/common/dashboard.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:healthcare_user/Reports/allreports.dart'; +import 'package:healthcare_user/chat/chatpage.dart'; import 'package:healthcare_user/common/qrcode_display.dart'; import 'package:healthcare_user/common/updateprofile.dart'; import 'package:healthcare_user/emergency.dart'; @@ -930,6 +931,34 @@ class _DashboardState extends State { Divider( color: Colors.grey, ), + ListTile( + title: Row( + children: [ + Image( + image: const AssetImage('images/updatepin.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + const SizedBox( + width: 10, + ), + const SizedBox( + width: 10, + ), + Text('Chats', style: drawerListItemsTextStyle()), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ChatPage()), + ); + }, + ), + Divider( + color: Colors.grey, + ), ListTile( title: Row( children: [ diff --git a/lib/common/settings.dart b/lib/common/settings.dart index bf5cbf6..ac48d3e 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -22,6 +22,8 @@ const Color textFieldStartColor = Colors.grey; const Color screenBackgroundColor = Color(0XFFEAF6FF); const Color screenBackgroundColord = Colors.black12; const Color dashboardbackground = Color(0XFFF5F5F5); +const appId="e5b593d506884e32856b5d6b1d72860f"; +const token="007eJxTYDibv+bcAy2rY7+OVHIEfQj1+/0y//Sai9e3BXUrfzsU+G65AkOqaZKppXGKqYGZhYVJqrGRhalZkmmKWZJhirmRhZlBmt9i4bSGQEaG63HbWBkZIBDEZ2FITszJYWAAAHfyIs8="; //Color AppBarGradient_1 = Color(0XFF1258F6); Color AppBarGradient_1 = Color(0XFF68A85D); diff --git a/lib/main.dart b/lib/main.dart index 63fd8b3..772d944 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,8 @@ +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; +import 'package:healthcare_user/chat/chatpage.dart'; import 'package:healthcare_user/common/splash_screen.dart'; import 'package:sizer/sizer.dart'; import 'package:flutter/services.dart'; @@ -7,6 +11,14 @@ void main () async { // Set default home. Widget _defaultHome = Splash(); WidgetsFlutterBinding.ensureInitialized(); + FirebaseOptions firebaseOptions = FirebaseOptions( + apiKey: 'AIzaSyC89L-Xg53Bd_mdCPvKOu7BcC9Ya6UZeds', + appId: '1:60196905754:android:05ea9ecef5280e578a42a3', + messagingSenderId: '60196905754 ', + projectId: 'health-pharma-67443', + storageBucket: "health-pharma-67443.appspot.com"// Firebase Realtime Database URL + ); + Platform.isAndroid? await Firebase.initializeApp(options: firebaseOptions):await Firebase.initializeApp(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp(Sizer( diff --git a/lib/pages/call.dart b/lib/pages/call.dart new file mode 100644 index 0000000..71e6a6c --- /dev/null +++ b/lib/pages/call.dart @@ -0,0 +1,271 @@ + +import 'package:flutter/material.dart'; +import 'package:healthcare_user/common/settings.dart'; +import 'dart:async'; +import 'package:permission_handler/permission_handler.dart'; + +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:agora_rtc_engine/rtc_engine.dart' as rtc_engine; +import 'package:agora_rtc_engine/rtc_local_view.dart' as rtc_local_view; +import 'package:agora_rtc_engine/rtc_remote_view.dart' as rtc_remote_view; + +class CallPage extends StatefulWidget { + final String? channelName; + final ClientRole? role; + const CallPage({Key? key, this.channelName, this.role}) : super(key: key); + + @override + State createState() => _CallPageState(); +} + +class _CallPageState extends State { + final _users = []; + final _infoString = []; + late RtcEngine _engine; + bool muted = false; // Define the muted variable + bool viewPanel = true; + @override + void initState() { + super.initState(); + initialize(); + } + + @override + void dispose() { + _users.clear(); + _engine.leaveChannel(); + _engine.destroy(); + super.dispose(); + } + + Future initialize() async { + if (appId.isEmpty) { + setState(() { + _infoString.add('AppId is missing please provide AppId'); + _infoString.add('Agora Engine is not starting'); + }); + return; + } + _engine = await rtc_engine.RtcEngine.create(appId); + await _engine.enableVideo(); + await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting); + await _engine.setClientRole(widget.role!); + _addAgoraEventHandler(); + VideoEncoderConfiguration configuration = VideoEncoderConfiguration( + dimensions: VideoDimensions(width: 1920, height: 1080), + ); + await _engine.setVideoEncoderConfiguration(configuration); + await _engine.joinChannel(token, widget.channelName!, null, 0); + } + + void _addAgoraEventHandler() { + _engine.setEventHandler( + rtc_engine.RtcEngineEventHandler( + error: (code) { + setState(() { + final info = 'Error: $code'; + _infoString.add(info); + }); + }, + joinChannelSuccess: (channel, uid, elapsed) { + setState(() { + final info = 'Join Channel: $channel, uid:$uid'; + _infoString.add(info); + }); + }, + leaveChannel: (stats) { + setState(() { + _infoString.add('Leave Channel'); + _users.clear(); + }); + }, + userJoined: (uid, elapsed) { + setState(() { + final info = 'User joined: $uid'; + _infoString.add(info); + _users.add(uid); + }); + }, + userOffline: (uid, elapsed) { + setState(() { + final info = 'User Offline: $uid'; + _infoString.add(info); + _users.remove(uid); + }); + }, + firstRemoteVideoFrame: (uid, width, height, elapsed) { + setState(() { + final info = 'First Remote Video: $uid $width*$height'; + _infoString.add(info); + _users.remove(uid); + }); + }, + ), + ); + } + + + + + + Widget _viewRows() { + final List list = []; + if (widget.role == ClientRole.Broadcaster) { + list.add(const rtc_local_view.SurfaceView()); + } + for (var uid in _users) { + list.add(rtc_remote_view.SurfaceView( + uid: uid, + channelId: widget.channelName!, + )); + } + final views=list; + return Column( + children: List.generate( + views.length, + (index) => Expanded( + child: views[index], + ), + ), + ); + } + + + Widget _toolbar() { + if (widget.role == ClientRole.Audience) return SizedBox(); + + return Container( + alignment: Alignment.bottomCenter, + padding: const EdgeInsets.symmetric(vertical: 48), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RawMaterialButton( + onPressed: () { + setState(() { + muted = !muted; + }); + _engine.muteLocalAudioStream(muted); + }, + child: Icon( + muted ? Icons.mic_off : Icons.mic, + color: muted ? Colors.white : Colors.blueAccent, + size: 20.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: muted ? Colors.blueAccent : Colors.white, + padding: EdgeInsets.all(12.0), + ), + RawMaterialButton( + onPressed: () => Navigator.pop(context), + child: Icon( + Icons.call_end, + color: Colors.white, + size: 35.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.redAccent, + padding: EdgeInsets.all(15.0), + ), + RawMaterialButton( + onPressed: () { + _engine.switchCamera(); + }, + child: Icon( + Icons.switch_camera, + color: Colors.blueAccent, + size: 20.0, + ), + shape: CircleBorder(), + elevation: 2.0, + fillColor: Colors.white, + padding: EdgeInsets.all(12.0), + ), + ], + ), + ); + } + + + Widget _panel() + { + return Visibility( + visible: viewPanel, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 48), + alignment: Alignment.bottomCenter, + child: FractionallySizedBox( + heightFactor: 0.5, + child: Container( + padding: EdgeInsets.symmetric(vertical: 48), + child: ListView.builder( + reverse: true, + itemCount: _infoString.length, + itemBuilder:(BuildContext context,int index) + { + if(_infoString.isEmpty) + { + return const Text("null"); + } + return Padding( + padding: const EdgeInsets.symmetric(vertical: 3,horizontal: 10), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5) + ), + child: Text( + _infoString[index], + style: const TextStyle(color:Colors.blueGrey), + ), + ), + + ) + ], + ), + ); + }, + ), + ), + ), + ), + ); + } + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("VideoCall"), + centerTitle: true, + actions: [ + IconButton(onPressed:() + { + setState(() { + viewPanel=!viewPanel; + }); + }, icon: const Icon(Icons.ice_skating)) + ], + ), + backgroundColor: Colors.black, + body: Center( + child: Stack( + children: [ + _viewRows(), + _panel(), + _toolbar(), + ] + ), + ), + ); + } +} diff --git a/lib/pages/index.dart b/lib/pages/index.dart new file mode 100644 index 0000000..de048ea --- /dev/null +++ b/lib/pages/index.dart @@ -0,0 +1,120 @@ +import 'package:agora_rtc_engine/rtc_engine.dart'; +import 'package:flutter/material.dart'; +import 'package:async/async.dart'; +import 'dart:developer'; +import 'package:permission_handler/permission_handler.dart'; +import './call.dart'; +import 'package:flutter/material.dart' hide Size; +import 'dart:ui' as ui; + +class IndexPage extends StatefulWidget { + const IndexPage({Key? key}) : super(key: key); + + @override + State createState() => _IndexPageState(); +} + +class _IndexPageState extends State { + + TextEditingController _channelController = TextEditingController(text: 'call'); + + bool _validateError=false; + ClientRole? _role= ClientRole.Broadcaster; + + + @override + void dispose() { + _channelController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("VideoCall"), + centerTitle: true, + ), + body: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Column( + children: [ + const SizedBox(height: 20), + const SizedBox(height: 20), + TextField( + controller: _channelController, + decoration: InputDecoration( + errorText: _validateError ? 'Chanel Name is Mondatory' : null, + border: UnderlineInputBorder(borderSide: BorderSide(width: 1),), + hintText: 'channel name', + ), + ), + RadioListTile( + title: const Text('Broadcaster'), + onChanged: (ClientRole? value) + { + setState(() { + _role=value; + }); + }, + value: ClientRole.Broadcaster, + groupValue: _role, + ), + RadioListTile( + title: const Text('Audience'), + onChanged: (ClientRole? value) + { + setState(() { + _role=value; + }); + }, + value: ClientRole.Audience, + groupValue: _role, + ), + ElevatedButton( + onPressed: onjoin, + child: const Text('Join'), + style: ElevatedButton.styleFrom( + minimumSize: const ui.Size(double.infinity, 40), + ), + ) + ], + ), + ), + ), + ); + } + + Future onjoin() async { + setState(() { + _channelController.text.isEmpty + ? _validateError=true: + _validateError=false; // This line doesn't actually update any state + }); + + if(_channelController.text.isNotEmpty) + { + await _handlecameraAndMic(Permission.camera); + await _handlecameraAndMic(Permission.microphone); + await Navigator.push( + context, + MaterialPageRoute( + builder: (__) => CallPage( + channelName: _channelController.text, // Passes the text from _channelController as channelName + role: _role, // Passes the value of _role as role + ), + ), + ); + + + + } + } + + Future _handlecameraAndMic(Permission permission) async + { + final status=await permission.request(); + log(status.toString()); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index a038202..25bffdb 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,7 @@ import FlutterMacOS import Foundation +import agora_rtc_engine import assets_audio_player import assets_audio_player_web import cloud_firestore @@ -12,6 +13,7 @@ import device_info_plus_macos import file_selector_macos import firebase_core import firebase_messaging +import firebase_storage import flutter_local_notifications import geolocator_apple import location @@ -22,6 +24,7 @@ import url_launcher_macos import wakelock_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AgoraRtcEnginePlugin.register(with: registry.registrar(forPlugin: "AgoraRtcEnginePlugin")) AssetsAudioPlayerPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerPlugin")) AssetsAudioPlayerWebPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerWebPlugin")) FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) @@ -29,6 +32,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 2d2c55f..309dded 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,14 @@ packages: name: _flutterfire_internals url: "https://pub.dartlang.org" source: hosted - version: "1.3.6" + version: "1.3.16" + agora_rtc_engine: + dependency: "direct main" + description: + name: agora_rtc_engine + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" archive: dependency: transitive description: @@ -119,21 +126,21 @@ packages: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "4.9.2" + version: "4.14.0" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.16.1" + version: "6.1.0" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "3.7.1" + version: "3.9.0" cloudinary_public: dependency: "direct main" description: @@ -317,47 +324,68 @@ packages: source: hosted version: "0.9.3" firebase_core: - dependency: transitive + dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "2.16.0" + version: "2.24.2" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.8.0" + version: "5.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "2.8.0" + version: "2.10.0" firebase_messaging: dependency: "direct main" description: name: firebase_messaging url: "https://pub.dartlang.org" source: hosted - version: "14.6.8" + version: "14.7.10" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.5.7" + version: "4.5.18" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web url: "https://pub.dartlang.org" source: hosted - version: "3.5.7" + version: "3.5.18" + firebase_storage: + dependency: "direct main" + description: + name: firebase_storage + url: "https://pub.dartlang.org" + source: hosted + version: "11.6.0" + firebase_storage_platform_interface: + dependency: transitive + description: + name: firebase_storage_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.3" + firebase_storage_web: + dependency: transitive + description: + name: firebase_storage_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.6.17" flick_video_player: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 53af8ef..cff71e8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,7 +35,6 @@ dependencies: card_swiper: ^2.0.4 firebase_messaging: ^14.4.1 flutter_local_notifications: ^9.0.2 - cloud_firestore: ^4.5.2 flutter_device_type: ^0.4.0 device_information: ^0.0.4 device_info_plus: ^3.2.4 @@ -67,6 +66,10 @@ dependencies: qr_code_scanner: ^1.0.1 flutter_barcode_scanner: ^2.0.0 pull_to_refresh: ^2.0.0 + cloud_firestore: + firebase_storage: + firebase_core: ^2.24.2 + agora_rtc_engine: ^5.3.1 dev_dependencies: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 5d27235..9e818bf 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,17 +6,26 @@ #include "generated_plugin_registrant.h" +#include +#include #include #include +#include #include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + AgoraRtcEnginePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AgoraRtcEnginePlugin")); + CloudFirestorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + FirebaseStoragePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseStoragePluginCApi")); GeolocatorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("GeolocatorWindows")); PermissionHandlerWindowsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ec01e6b..6f1c63a 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,8 +3,11 @@ # list(APPEND FLUTTER_PLUGIN_LIST + agora_rtc_engine + cloud_firestore file_selector_windows firebase_core + firebase_storage geolocator_windows permission_handler_windows url_launcher_windows