From deeda09ca3ef6ad8ae983da2de49195244890b65 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 11 Oct 2021 20:43:08 +0500 Subject: [PATCH] group conversation + contact enabled --- .../contact_detail_conversation.dart | 32 +++ .../views/conversation/conversation_view.dart | 52 +++- .../group_detail_conversation.dart | 257 ++++++++++++++++++ 3 files changed, 338 insertions(+), 3 deletions(-) create mode 100644 packages/simplex_app/lib/views/conversation/contact_detail_conversation.dart create mode 100644 packages/simplex_app/lib/views/conversation/group_detail_conversation.dart diff --git a/packages/simplex_app/lib/views/conversation/contact_detail_conversation.dart b/packages/simplex_app/lib/views/conversation/contact_detail_conversation.dart new file mode 100644 index 0000000000..03b09e660f --- /dev/null +++ b/packages/simplex_app/lib/views/conversation/contact_detail_conversation.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:simplex_chat/constants.dart'; +import 'package:simplex_chat/model/contact.dart'; + +class ContactDetailsConversation extends StatelessWidget { + final Contact contact; + const ContactDetailsConversation({Key key, this.contact}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(contact.name), + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 12.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const CircleAvatar( + radius: 65, + backgroundImage: AssetImage('assets/dp.png'), + ), + const SizedBox(height: 15.0), + const Text('Display Name', style: kMediumHeadingStyle), + Text(contact.name), + ], + ), + ), + ); + } +} diff --git a/packages/simplex_app/lib/views/conversation/conversation_view.dart b/packages/simplex_app/lib/views/conversation/conversation_view.dart index e6d90a89e6..2ef273361a 100644 --- a/packages/simplex_app/lib/views/conversation/conversation_view.dart +++ b/packages/simplex_app/lib/views/conversation/conversation_view.dart @@ -1,9 +1,16 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:simplex_chat/model/contact.dart'; +import 'package:simplex_chat/model/group.dart'; +import 'package:simplex_chat/views/conversation/contact_detail_conversation.dart'; +import 'package:simplex_chat/views/conversation/group_detail_conversation.dart'; import 'package:simplex_chat/widgets/message_bubble.dart'; class ConversationView extends StatefulWidget { - final String name; - const ConversationView({Key key, @required this.name}) : super(key: key); + final Contact contact; + final Group group; + const ConversationView({Key key, this.contact, this.group}) : super(key: key); @override _ConversationViewState createState() => _ConversationViewState(); @@ -42,7 +49,46 @@ class _ConversationViewState extends State { onTap: () => FocusScope.of(context).unfocus(), child: Scaffold( appBar: AppBar( - title: Text(widget.name), + leading: InkWell( + onTap: () => Navigator.of(context).pop(true), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.arrow_back), + const SizedBox(width: 8.0), + CircleAvatar( + backgroundImage: widget.contact == null + ? widget.group.photoPath == '' + ? const AssetImage('assets/dp.png') + : FileImage( + File(widget.group.photoPath), + ) + : const AssetImage('assets/dp.png')), + ], + ), + ), + leadingWidth: MediaQuery.of(context).size.width * 0.2, + title: Text(widget.contact != null + ? widget.contact.name + : widget.group.groupName), + actions: [ + IconButton( + onPressed: widget.contact != null + ? () => Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ContactDetailsConversation( + contact: widget.contact, + ))) + : () => Navigator.push( + context, + MaterialPageRoute( + builder: (_) => GroupDetailsConversation( + group: widget.group, + ))), + icon: const Icon(Icons.info), + ), + ], ), body: Column( children: [ diff --git a/packages/simplex_app/lib/views/conversation/group_detail_conversation.dart b/packages/simplex_app/lib/views/conversation/group_detail_conversation.dart new file mode 100644 index 0000000000..98b73381c2 --- /dev/null +++ b/packages/simplex_app/lib/views/conversation/group_detail_conversation.dart @@ -0,0 +1,257 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:simplex_chat/constants.dart'; +import 'package:simplex_chat/model/contact.dart'; +import 'package:simplex_chat/model/group.dart'; + +class GroupDetailsConversation extends StatefulWidget { + final Group group; + const GroupDetailsConversation({Key key, this.group}) : super(key: key); + + @override + _GroupDetailsConversationState createState() => + _GroupDetailsConversationState(); +} + +class _GroupDetailsConversationState extends State { + bool _addMember = false; + List _contactsList = []; // for storing contacts + List _newMembers = []; + + List _groupList = []; + List _members = []; + + // getting all members of group + void _getMembers() { + setState(() { + _members = List.from(widget.group.members); + }); + } + + // getting groups + void _getGroups() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String _groups = prefs.getString('groups'); + if (_groups != null) { + setState(() { + _groupList = List.from(Group.decode(_groups)); + }); + } + } + + // getting data from local storage FOR NOW + void _getContacts() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String _contacts = prefs.getString('contacts'); + setState(() { + _contactsList = List.from(Contact.decode(_contacts)); + }); + } + + @override + void initState() { + _getContacts(); + _getGroups(); + _getMembers(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.group.groupName), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: CircleAvatar( + radius: 70, + backgroundImage: widget.group.photoPath == '' + ? const AssetImage('assets/dp.png') + : FileImage(File(widget.group.photoPath)), + ), + ), + const SizedBox(height: 25.0), + const Text('Group Name', style: kMediumHeadingStyle), + Text(widget.group.groupName), + const Divider(), + ListTile( + leading: const Icon(Icons.person_add), + title: const Text('Add a member'), + onTap: () { + setState(() { + _addMember = !_addMember; + }); + }, + ), + const Divider(), + _newMembers.isNotEmpty + ? const Text('New Members Added') + : Container(), + SizedBox(height: _newMembers.isNotEmpty ? 10.0 : 0.0), + _newMembers.isNotEmpty + ? SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.generate( + _newMembers.length, + (index) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + child: InkWell( + onTap: () { + setState(() { + _newMembers.remove(_newMembers[index]); + }); + }, + child: Container( + padding: const EdgeInsets.all(7.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.0), + color: Colors.grey.withAlpha(100)), + child: Text(_newMembers[index]), + ), + ), + ), + )), + ) + : Container(), + SizedBox(height: _addMember ? 10.0 : 0.0), + _addMember ? const Text('Contacts Available') : Container(), + SizedBox(height: _addMember ? 10.0 : 0.0), + _addMember + ? ListView( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + children: List.generate( + _contactsList.length, + (index) => ListTile( + leading: const CircleAvatar( + backgroundImage: AssetImage('assets/dp.png'), + ), + title: Text(_contactsList[index].name), + onTap: () { + setState(() { + _newMembers.add(_contactsList[index].name); + }); + }, + ), + ), + ) + : Container(), + SizedBox(height: _addMember ? 10.0 : 0.0), + const Text('Members', style: kMediumHeadingStyle), + const SizedBox(height: 5.0), + for (int i = 0; i < _members.length; i++) + ListTile( + leading: const CircleAvatar( + backgroundImage: AssetImage('assets/dp.png'), + ), + title: Text(_members[i]), + trailing: InkWell( + onTap: () => _removeMember(_members[i]), + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.delete, + color: Colors.red, + ), + ), + ), + ) + ], + ), + ), + ), + floatingActionButton: _newMembers.isEmpty + ? Container() + : FloatingActionButton( + onPressed: _addNewMembers, + child: const Icon(Icons.check), + ), + ); + } + + void _addNewMembers() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + // add new members to the _members list + setState(() { + _members = _members + _newMembers; + _newMembers = []; + _addMember = false; + }); + + const snackBar = SnackBar( + backgroundColor: Colors.green, content: Text('New members added!')); + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(snackBar); + + // get index of group in local + int index = 0; + + index = _groupList + .indexWhere((group) => group.groupName == widget.group.groupName); + + // add the full _members list to the group + Group _updatedGroup = Group( + groupName: widget.group.groupName, + groupDescription: widget.group.groupDescription, + members: _members, + photoPath: widget.group.photoPath, + ); + + // put it in updated group local list + _groupList[index] = _updatedGroup; + + // convert to string + final String _updatedGroupString = Group.encode(_groupList); + + // update the group in local storage + await prefs.setString('groups', _updatedGroupString); + } + + void _removeMember(String contact) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + // remove the current member + setState(() { + _members.remove(contact); + }); + + var snackBar = SnackBar( + backgroundColor: Colors.red, content: Text('$contact removed!')); + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(snackBar); + + // get index of group in local + int index = 0; + + index = _groupList + .indexWhere((group) => group.groupName == widget.group.groupName); + + // new instance of group (updated) + Group _updatedGroup = Group( + groupName: widget.group.groupName, + groupDescription: widget.group.groupDescription, + photoPath: widget.group.photoPath, + members: _members, + ); + + // put it in group local list + _groupList[index] = _updatedGroup; + + // convert to string + final String _updatedGroupString = Group.encode(_groupList); + + // update the group in local storage + await prefs.setString('groups', _updatedGroupString); + } +}