diff --git a/packages/simplex_app/lib/animations/bottom_animation.dart b/packages/simplex_app/lib/animations/bottom_animation.dart index af177f3ac..52fb2cc8d 100644 --- a/packages/simplex_app/lib/animations/bottom_animation.dart +++ b/packages/simplex_app/lib/animations/bottom_animation.dart @@ -6,7 +6,7 @@ class Animator extends StatefulWidget { final Widget child; final Duration time; - const Animator(this.child, this.time, {Key? key}) : super(key: key); + const Animator(this.child, this.time, {Key key}) : super(key: key); @override _AnimatorState createState() => _AnimatorState(); @@ -14,9 +14,9 @@ class Animator extends StatefulWidget { class _AnimatorState extends State with SingleTickerProviderStateMixin { - Timer? timer; - AnimationController? animationController; - Animation? animation; + Timer timer; + AnimationController animationController; + Animation animation; @override void initState() { @@ -24,27 +24,27 @@ class _AnimatorState extends State animationController = AnimationController( duration: const Duration(milliseconds: 290), vsync: this); animation = - CurvedAnimation(parent: animationController!, curve: Curves.easeInOut); - timer = Timer(widget.time, animationController!.forward); + CurvedAnimation(parent: animationController, curve: Curves.easeInOut); + timer = Timer(widget.time, animationController.forward); } @override void dispose() { - animationController!.dispose(); + animationController.dispose(); super.dispose(); - timer!.cancel(); + timer.cancel(); } @override Widget build(BuildContext context) { return AnimatedBuilder( - animation: animation!, + animation: animation, child: widget.child, - builder: (BuildContext context, Widget? child) { + builder: (BuildContext context, Widget child) { return Opacity( - opacity: animation!.value, + opacity: animation.value, child: Transform.translate( - offset: Offset(0.0, (1 - animation!.value) * 20), + offset: Offset(0.0, (1 - animation.value) * 20), child: child, ), ); @@ -53,11 +53,11 @@ class _AnimatorState extends State } } -Timer? timer; +Timer timer; Duration duration = const Duration(); Duration wait() { - if (timer == null || !timer!.isActive) { + if (timer == null || !timer.isActive) { timer = Timer(const Duration(microseconds: 120), () { duration = const Duration(); }); @@ -67,12 +67,12 @@ Duration wait() { } class WidgetAnimator extends StatelessWidget { - final Widget? child; + final Widget child; - const WidgetAnimator({this.child, Key? key}) : super(key: key); + const WidgetAnimator({this.child, Key key}) : super(key: key); @override Widget build(BuildContext context) { - return Animator(child!, wait()); + return Animator(child, wait()); } } diff --git a/packages/simplex_app/lib/animations/entrance_fader.dart b/packages/simplex_app/lib/animations/entrance_fader.dart index 4ddcd52c3..5af97b5f2 100644 --- a/packages/simplex_app/lib/animations/entrance_fader.dart +++ b/packages/simplex_app/lib/animations/entrance_fader.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class EntranceFader extends StatefulWidget { /// Child to be animated on entrance - final Widget? child; + final Widget child; /// Delay after which the animation will start final Duration delay; @@ -14,7 +14,7 @@ class EntranceFader extends StatefulWidget { final Offset offset; const EntranceFader({ - Key? key, + Key key, this.child, this.delay = const Duration(milliseconds: 0), this.duration = const Duration(milliseconds: 400), @@ -29,39 +29,39 @@ class EntranceFader extends StatefulWidget { class EntranceFaderState extends State with SingleTickerProviderStateMixin { - AnimationController? _controller; - Animation? _dxAnimation; - Animation? _dyAnimation; + AnimationController _controller; + Animation _dxAnimation; + Animation _dyAnimation; @override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: widget.duration); _dxAnimation = - Tween(begin: widget.offset.dx, end: 0.0).animate(_controller!); + Tween(begin: widget.offset.dx, end: 0.0).animate(_controller); _dyAnimation = - Tween(begin: widget.offset.dy, end: 0.0).animate(_controller!); + Tween(begin: widget.offset.dy, end: 0.0).animate(_controller); Future.delayed(widget.delay, () { if (mounted) { - _controller!.forward(); + _controller.forward(); } }); } @override void dispose() { - _controller!.dispose(); + _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( - animation: _controller!, + animation: _controller, builder: (context, child) => Opacity( - opacity: _controller!.value, + opacity: _controller.value, child: Transform.translate( - offset: Offset(_dxAnimation!.value, _dyAnimation!.value), + offset: Offset(_dxAnimation.value, _dyAnimation.value), child: widget.child, ), ), diff --git a/packages/simplex_app/lib/custom_scroll_behavior.dart b/packages/simplex_app/lib/custom_scroll_behavior.dart index f777304d7..0923692fa 100644 --- a/packages/simplex_app/lib/custom_scroll_behavior.dart +++ b/packages/simplex_app/lib/custom_scroll_behavior.dart @@ -14,5 +14,6 @@ class ScrollBehaviorModified extends ScrollBehavior { case TargetPlatform.windows: return const ClampingScrollPhysics(); } + return null; } } diff --git a/packages/simplex_app/lib/main.dart b/packages/simplex_app/lib/main.dart index 945b4f195..28c131ebd 100644 --- a/packages/simplex_app/lib/main.dart +++ b/packages/simplex_app/lib/main.dart @@ -17,7 +17,7 @@ void main() { } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({Key key}) : super(key: key); @override Widget build(BuildContext context) { @@ -38,9 +38,7 @@ class MyApp extends StatelessWidget { ), builder: (context, widget) { return ScrollConfiguration( - behavior: const ScrollBehaviorModified(), - child: widget!, - ); + behavior: const ScrollBehaviorModified(), child: widget); }, initialRoute: AppRoutes.splash, routes: { diff --git a/packages/simplex_app/lib/model/contact.dart b/packages/simplex_app/lib/model/contact.dart index 04f1feb05..273719316 100644 --- a/packages/simplex_app/lib/model/contact.dart +++ b/packages/simplex_app/lib/model/contact.dart @@ -1,9 +1,9 @@ import 'dart:convert'; class Contact { - final String? name; - final String? msg; - final String? msgTime; + final String name; + final String msg; + final String msgTime; Contact({this.name, this.msg, this.msgTime}); @@ -26,8 +26,8 @@ class Contact { .toList(), ); - static List decode(String? contacts) => - (json.decode(contacts!) as List) + static List decode(String contacts) => + (json.decode(contacts) as List) .map((item) => Contact.fromJson(item)) .toList(); } diff --git a/packages/simplex_app/lib/model/group.dart b/packages/simplex_app/lib/model/group.dart index 268f94962..56a19e83d 100644 --- a/packages/simplex_app/lib/model/group.dart +++ b/packages/simplex_app/lib/model/group.dart @@ -1,14 +1,20 @@ import 'dart:convert'; class Group { - final String? groupName; - final String? groupDescription; + final String photoPath; + final String groupName; + final String groupDescription; final List members; - Group({this.groupName, this.groupDescription, this.members = const []}); + Group( + {this.groupName, + this.photoPath, + this.groupDescription, + this.members = const []}); factory Group.fromJson(Map json) { return Group( + photoPath: json['gPhoto'], groupName: json['gName'], groupDescription: json['desc'], members: json['contacts'], @@ -17,6 +23,7 @@ class Group { static Map toJson(Group group) { return { + 'gPhoto': group.photoPath, 'gName': group.groupName, 'desc': group.groupDescription, 'contacts': group.members, @@ -29,8 +36,8 @@ class Group { .toList(), ); - static List decode(String? groups) => - (json.decode(groups!) as List) + static List decode(String groups) => + (json.decode(groups) as List) .map((item) => Group.fromJson(item)) .toList(); } diff --git a/packages/simplex_app/lib/providers/drawer_providers.dart b/packages/simplex_app/lib/providers/drawer_providers.dart index 3a981fdee..5a95095c6 100644 --- a/packages/simplex_app/lib/providers/drawer_providers.dart +++ b/packages/simplex_app/lib/providers/drawer_providers.dart @@ -1,7 +1,7 @@ import 'package:flutter/cupertino.dart'; class DrawerProvider extends ChangeNotifier { - int _currentIndex = 0; + int _currentIndex = 1; int get currentIndex => _currentIndex; @@ -9,13 +9,4 @@ class DrawerProvider extends ChangeNotifier { _currentIndex = value; notifyListeners(); } - - // toggle drawer - TickerFuture toggle( - AnimationController? animationController) { - - return animationController!.isDismissed - ? animationController.forward() - : animationController.reverse(); - } } diff --git a/packages/simplex_app/lib/views/contacts/add_contact_view.dart b/packages/simplex_app/lib/views/contacts/add_contact_view.dart index 91dbdbbcd..bdbc786f9 100644 --- a/packages/simplex_app/lib/views/contacts/add_contact_view.dart +++ b/packages/simplex_app/lib/views/contacts/add_contact_view.dart @@ -5,7 +5,7 @@ import 'package:qr_code_scanner/qr_code_scanner.dart'; import 'package:simplex_chat/views/contacts/qr_code_details_view.dart'; class AddContactView extends StatefulWidget { - const AddContactView({Key? key}) : super(key: key); + const AddContactView({Key key}) : super(key: key); @override _AddContactViewState createState() => _AddContactViewState(); @@ -13,16 +13,16 @@ class AddContactView extends StatefulWidget { class _AddContactViewState extends State { final qrKey = GlobalKey(debugLabel: 'qr'); - QRViewController? _qrViewController; - Barcode? result; + QRViewController _qrViewController; + Barcode result; @override void reassemble() { super.reassemble(); if (Platform.isAndroid) { - _qrViewController!.pauseCamera(); + _qrViewController.pauseCamera(); } else if (Platform.isIOS) { - _qrViewController!.resumeCamera(); + _qrViewController.resumeCamera(); } } diff --git a/packages/simplex_app/lib/views/contacts/contacts_view.dart b/packages/simplex_app/lib/views/contacts/contacts_view.dart index 47a444459..374d34392 100644 --- a/packages/simplex_app/lib/views/contacts/contacts_view.dart +++ b/packages/simplex_app/lib/views/contacts/contacts_view.dart @@ -9,14 +9,14 @@ import 'package:simplex_chat/model/contact.dart'; import 'package:simplex_chat/views/conversation/conversation_view.dart'; class ContactsView extends StatefulWidget { - const ContactsView({Key? key}) : super(key: key); + const ContactsView({Key key}) : super(key: key); @override _ContactsViewState createState() => _ContactsViewState(); } class _ContactsViewState extends State { - bool? _eraseMedia = false; + bool _eraseMedia = false; List _contactsList = []; // for storing contacts @@ -44,14 +44,16 @@ class _ContactsViewState extends State { // 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)); - }); + final String _contacts = prefs.getString('contacts'); + if (_contacts != null) { + setState(() { + _contactsList = List.from(Contact.decode(_contacts)); + }); + } } - String? _photo; - String? _displayName; + String _photo = ''; + String _displayName = ''; void _getUserData() async { SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -89,10 +91,13 @@ class _ContactsViewState extends State { ], ), const SizedBox(width: 10.0), - CircleAvatar( - backgroundImage: _photo == null - ? const AssetImage('assets/dp.png') as ImageProvider - : FileImage(File(_photo!)), + GestureDetector( + onTap: _addNewContacts, + child: CircleAvatar( + backgroundImage: _photo.isEmpty + ? const AssetImage('assets/dp.png') as ImageProvider + : FileImage(File(_photo)), + ), ) ], ), @@ -138,10 +143,10 @@ class _ContactsViewState extends State { leading: const CircleAvatar( backgroundImage: AssetImage('assets/dp.png'), ), - title: Text(_contactsList[index].name!), - subtitle: Text(_contactsList[index].msg!), + title: Text(_contactsList[index].name), + subtitle: Text(_contactsList[index].msg), trailing: Text( - _contactsList[index].msgTime!, + _contactsList[index].msgTime, style: const TextStyle( fontSize: 11, color: Colors.grey), ), @@ -171,9 +176,9 @@ class _ContactsViewState extends State { offset: const Offset(-10, -120), onSelected: (value) { if (value == _options[0]) { - Navigator.pushNamed(context, AppRoutes.addContact); - } else { Navigator.pushNamed(context, AppRoutes.scanInvitation); + } else { + Navigator.pushNamed(context, AppRoutes.addContact); } }, itemBuilder: (context) => _options @@ -325,7 +330,10 @@ class _ContactsViewState extends State { SharedPreferences prefs = await SharedPreferences.getInstance(); List _localList = []; - _localList = List.from(Contact.decode(prefs.getString('contacts'))); + final String _local = prefs.getString('contacts'); + if (_local != null) { + _localList = List.from(Contact.decode(_local)); + } List _newList = [ Contact( diff --git a/packages/simplex_app/lib/views/contacts/qr_code_details_view.dart b/packages/simplex_app/lib/views/contacts/qr_code_details_view.dart index fe8a6aad5..f3ad04ff7 100644 --- a/packages/simplex_app/lib/views/contacts/qr_code_details_view.dart +++ b/packages/simplex_app/lib/views/contacts/qr_code_details_view.dart @@ -4,9 +4,9 @@ import 'package:simplex_chat/constants.dart'; import 'package:simplex_chat/widgets/custom_btn.dart'; class QRCodeDetailsView extends StatelessWidget { - final Barcode? barcode; + final Barcode barcode; const QRCodeDetailsView({ - Key? key, + Key key, this.barcode, }) : super(key: key); @@ -26,7 +26,7 @@ class QRCodeDetailsView extends StatelessWidget { ), const SizedBox(height: 30.0), Text( - barcode!.code, + barcode.code, style: kMediumHeadingStyle, textAlign: TextAlign.center, ), diff --git a/packages/simplex_app/lib/views/conversation/conversation_view.dart b/packages/simplex_app/lib/views/conversation/conversation_view.dart index 0d69d54b3..e6d90a89e 100644 --- a/packages/simplex_app/lib/views/conversation/conversation_view.dart +++ b/packages/simplex_app/lib/views/conversation/conversation_view.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.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 String name; + const ConversationView({Key key, @required this.name}) : super(key: key); @override _ConversationViewState createState() => _ConversationViewState(); @@ -13,17 +13,17 @@ class _ConversationViewState extends State { final ScrollController _scrollController = ScrollController(); final TextEditingController _messageFieldController = TextEditingController(); - FocusNode? _focus; + FocusNode _focus; bool _fieldEnabled = false; final List _chatMessages = []; @override void initState() { _focus = FocusNode(); - _focus!.addListener(() { - debugPrint('FOCUS ${_focus!.hasFocus}'); - _fieldEnabled = _focus!.hasFocus; - debugPrint('MESSAGE ENABLED! $_fieldEnabled'); + _focus.addListener(() { + debugPrint('FOCUS ${_focus.hasFocus}'); + _fieldEnabled = _focus.hasFocus; + debugPrint('MESSAGE ENABLED $_fieldEnabled'); }); super.initState(); } @@ -32,7 +32,7 @@ class _ConversationViewState extends State { void dispose() { _messageFieldController.dispose(); _scrollController.dispose(); - _focus!.dispose(); + _focus.dispose(); super.dispose(); } @@ -42,7 +42,7 @@ class _ConversationViewState extends State { onTap: () => FocusScope.of(context).unfocus(), child: Scaffold( appBar: AppBar( - title: Text('${widget.name}'), + title: Text(widget.name), ), body: Column( children: [ @@ -50,7 +50,7 @@ class _ConversationViewState extends State { child: Container( child: _chatMessages.isEmpty ? const Center( - child: Text('Send a message to get started!'), + child: Text('Send a message to get started'), ) : SingleChildScrollView( controller: _scrollController, @@ -96,7 +96,7 @@ class _ConversationViewState extends State { const SizedBox(width: 15.0), InkWell( onTap: () async { - if (_messageFieldController.text != '') { + if (_messageFieldController.text == '') { setState(() { _chatMessages.add(MessageBubble( isUser: true, @@ -105,7 +105,7 @@ class _ConversationViewState extends State { )); }); _messageFieldController.clear(); - _focus!.unfocus(); + _focus.unfocus(); } }, child: const Icon(Icons.send_rounded, diff --git a/packages/simplex_app/lib/views/group/add_group_view.dart b/packages/simplex_app/lib/views/group/add_group_view.dart index b9b6c4c3f..cf4929535 100644 --- a/packages/simplex_app/lib/views/group/add_group_view.dart +++ b/packages/simplex_app/lib/views/group/add_group_view.dart @@ -9,34 +9,61 @@ import 'package:simplex_chat/model/group.dart'; import 'package:simplex_chat/widgets/custom_text_field.dart'; class AddGroupView extends StatefulWidget { - const AddGroupView({Key? key}) : super(key: key); + const AddGroupView({Key key}) : super(key: key); @override _AddGroupViewState createState() => _AddGroupViewState(); } class _AddGroupViewState extends State { - bool _addMember = false; - List _contactsList = []; // for storing contacts + // Image Picker --> DP properties + final imgPicker = ImagePicker(); + File image; + String _groupPhotoPath = ''; + bool _uploading = false; + bool _imageUploaded = false; final List _members = []; - final _formKey = GlobalKey(); - final _displayNameController = TextEditingController(); final _descController = TextEditingController(); - // getting data from local storage FOR NOW!! + bool _addMember = false; + List _contactsList = []; // for storing contacts + + // image buttons options + final _dpBtnText = ['Remove', 'Gallery', 'Camera']; + final _dpBtnColors = [Colors.red, Colors.purple, Colors.green]; + final _dpBtnIcons = [ + Icons.delete, + Icons.photo_rounded, + Icons.camera_alt_rounded + ]; + + // getting data from local storage FOR NOW void _getContacts() async { SharedPreferences prefs = await SharedPreferences.getInstance(); - final String? _contacts = prefs.getString('contacts'); + final String _contacts = prefs.getString('contacts'); setState(() { _contactsList = List.from(Contact.decode(_contacts)); }); } + String _userPhotoPath = ''; + void _getUserPhoto() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + String _photo = prefs.getString('photo${prefs.getString('displayName')}'); + if (_photo != null) { + setState(() { + _userPhotoPath = _photo; + }); + } + debugPrint(_userPhotoPath); + } + @override void initState() { + _getUserPhoto(); _getContacts(); super.initState(); } @@ -68,8 +95,50 @@ class _AddGroupViewState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 10.0), - const Center( - child: GroupDP(), + Center( + child: SizedBox( + height: 180.0, + width: 180.0, + child: Stack( + children: [ + _imageUploaded + ? CircleAvatar( + radius: 100.0, + backgroundImage: + FileImage(File(_groupPhotoPath)), + ) + : const CircleAvatar( + radius: 100.0, + backgroundImage: AssetImage('assets/dp.png'), + ), + Positioned( + right: 0, + bottom: 0, + child: FloatingActionButton( + backgroundColor: kSecondaryColor, + elevation: 2.0, + mini: true, + onPressed: _updateProfilePic, + child: _uploading + ? const SizedBox( + height: 18.0, + width: 18.0, + child: CircularProgressIndicator( + strokeWidth: 2.0, + valueColor: + AlwaysStoppedAnimation( + Colors.white), + ), + ) + : const Icon( + Icons.add_a_photo, + size: 20, + ), + ), + ) + ], + ), + ), ), const SizedBox(height: 25.0), const Text('Group Name', style: kSmallHeadingStyle), @@ -79,8 +148,8 @@ class _AddGroupViewState extends State { textInputType: TextInputType.name, hintText: 'e.g College friends', validatorFtn: (value) { - if (value!.isEmpty) { - return 'Group name cannot be empty!'; + if (value.isEmpty) { + return 'Group name cannot be empty'; } return null; }, @@ -148,10 +217,10 @@ class _AddGroupViewState extends State { leading: const CircleAvatar( backgroundImage: AssetImage('assets/dp.png'), ), - title: Text(_contactsList[index].name!), + title: Text(_contactsList[index].name), onTap: () { setState(() { - _members.add(_contactsList[index].name!); + _members.add(_contactsList[index].name); }); }, ), @@ -159,12 +228,14 @@ class _AddGroupViewState extends State { ) : Container(), const Divider(height: 30.0), - const ListTile( + ListTile( leading: CircleAvatar( - backgroundImage: AssetImage('assets/dp.png'), + backgroundImage: _userPhotoPath == '' + ? const AssetImage('assets/dp.png') as ImageProvider + : FileImage(File(_userPhotoPath)), ), - title: Text('You'), - subtitle: Text( + title: const Text('You'), + subtitle: const Text( 'Owner', style: TextStyle(color: Colors.grey, fontSize: 12.0), )), @@ -178,9 +249,11 @@ class _AddGroupViewState extends State { child: FloatingActionButton( heroTag: 'setup', onPressed: () async { - if (_formKey.currentState!.validate()) { + if (_formKey.currentState.validate()) { FocusScope.of(context).unfocus(); - _addNewGroup(_displayNameController.text.trim(), + _addNewGroup( + _groupPhotoPath, + _displayNameController.text.trim(), _descController.text.trim()); _descController.clear(); _displayNameController.clear(); @@ -194,102 +267,6 @@ class _AddGroupViewState extends State { ); } - void _addNewGroup(String name, String desc) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - List _localList = []; - _localList = List.from(Group.decode(prefs.getString('groups'))); - - List _groups = [ - Group( - groupName: name, - groupDescription: desc, - members: _members, - ), - ]; - _groups = _localList + _groups; - - final String _newGroups = Group.encode(_groups); - - await prefs.setString('groups', _newGroups); - - var snackBar = SnackBar( - backgroundColor: Colors.green, - content: Text('$name added!'), - ); - ScaffoldMessenger.of(context) - ..hideCurrentSnackBar() - ..showSnackBar(snackBar); - } -} - -class GroupDP extends StatefulWidget { - const GroupDP({Key? key}) : super(key: key); - - @override - _GroupDPState createState() => _GroupDPState(); -} - -class _GroupDPState extends State { - // Image Picker --> DP properties - final imgPicker = ImagePicker(); - File? image; - String photoUrl = ''; - bool _uploading = false; - bool _imageUploaded = false; - - // image buttons options - final _dpBtnText = ['Remove', 'Gallery', 'Camera']; - final _dpBtnColors = [Colors.red, Colors.purple, Colors.green]; - final _dpBtnIcons = [ - Icons.delete, - Icons.photo_rounded, - Icons.camera_alt_rounded - ]; - - @override - Widget build(BuildContext context) { - return SizedBox( - height: 180.0, - width: 180.0, - child: Stack( - children: [ - _imageUploaded - ? CircleAvatar( - radius: 100.0, - backgroundImage: FileImage(image!), - ) - : const CircleAvatar( - radius: 100.0, - backgroundImage: AssetImage('assets/dp.png'), - ), - Positioned( - right: 0, - bottom: 0, - child: FloatingActionButton( - backgroundColor: kSecondaryColor, - elevation: 2.0, - mini: true, - onPressed: _updateProfilePic, - child: _uploading - ? const SizedBox( - height: 18.0, - width: 18.0, - child: CircularProgressIndicator( - strokeWidth: 2.0, - valueColor: AlwaysStoppedAnimation(Colors.white), - ), - ) - : const Icon( - Icons.add_a_photo, - size: 20, - ), - ), - ) - ], - ), - ); - } - void _updateProfilePic() { showModalBottomSheet( shape: const RoundedRectangleBorder( @@ -356,6 +333,7 @@ class _GroupDPState extends State { setState(() { _imageUploaded = false; image = null; + _groupPhotoPath = ''; }); Navigator.pop(context); } @@ -376,6 +354,7 @@ class _GroupDPState extends State { setState(() { _uploading = false; _imageUploaded = true; + _groupPhotoPath = file.path; }); } else { setState(() { @@ -405,6 +384,7 @@ class _GroupDPState extends State { setState(() { _uploading = false; _imageUploaded = true; + _groupPhotoPath = file.path; }); } else { setState(() { @@ -417,4 +397,34 @@ class _GroupDPState extends State { rethrow; } } + + void _addNewGroup(String photo, String name, String desc) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + List _localList = []; + final String _local = prefs.getString('groups'); + if (_local != null) { + _localList = List.from(Group.decode(_local)); + } + List _groups = [ + Group( + photoPath: _groupPhotoPath, + groupName: name, + groupDescription: desc, + members: _members, + ), + ]; + _groups = _localList + _groups; + + final String _newGroups = Group.encode(_groups); + + await prefs.setString('groups', _newGroups); + + var snackBar = SnackBar( + backgroundColor: Colors.green, + content: Text('$name added'), + ); + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(snackBar); + } } diff --git a/packages/simplex_app/lib/views/group/group_view.dart b/packages/simplex_app/lib/views/group/group_view.dart index e86d278e5..5b5e8480b 100644 --- a/packages/simplex_app/lib/views/group/group_view.dart +++ b/packages/simplex_app/lib/views/group/group_view.dart @@ -1,5 +1,6 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:simplex_chat/animations/bottom_animation.dart'; import 'package:simplex_chat/app_routes.dart'; @@ -8,14 +9,14 @@ import 'package:simplex_chat/model/group.dart'; import 'package:simplex_chat/views/conversation/conversation_view.dart'; class GroupView extends StatefulWidget { - const GroupView({Key? key}) : super(key: key); + const GroupView({Key key}) : super(key: key); @override State createState() => _GroupViewState(); } class _GroupViewState extends State { - bool? _eraseMedia = false; + bool _eraseMedia = false; final List _options = [ 'Add group', 'Scan invitation', @@ -42,14 +43,28 @@ class _GroupViewState extends State { // getting data from local storage FOR NOW!! void _getGroups() async { SharedPreferences prefs = await SharedPreferences.getInstance(); - final String? _groups = prefs.getString('groups'); + final String _groups = prefs.getString('groups'); + if (_groups != null) { + setState(() { + _groupList = List.from(Group.decode(_groups)); + }); + } + } + + String _photo = ''; + String _displayName = ''; + + void _getUserData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); setState(() { - _groupList = List.from(Group.decode(_groups)); + _displayName = prefs.getString('displayName'); + _photo = prefs.getString('photo$_displayName'); }); } @override void initState() { + _getUserData(); _getGroups(); super.initState(); } @@ -62,15 +77,23 @@ class _GroupViewState extends State { padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0), child: Column( children: [ - Align( - alignment: Alignment.centerRight, - child: GestureDetector( - onTap: _addNewGroups, - child: SvgPicture.asset( - 'assets/logo.svg', - height: 40.0, + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Hi! $_displayName', style: kSmallHeadingStyle), + const Text('Good day!'), + ], ), - ), + const SizedBox(width: 10.0), + CircleAvatar( + backgroundImage: _photo.isEmpty + ? const AssetImage('assets/dp.png') as ImageProvider + : FileImage(File(_photo)), + ), + ], ), const SizedBox(height: 15.0), Row( @@ -111,11 +134,14 @@ class _GroupViewState extends State { _groupList.length, (index) => WidgetAnimator( child: ListTile( - leading: const CircleAvatar( - backgroundImage: AssetImage('assets/dp.png'), + leading: CircleAvatar( + backgroundImage: _groupList[index].photoPath == '' + ? const AssetImage('assets/dp.png') + as ImageProvider + : FileImage(File(_groupList[index].photoPath)), ), - title: Text(_groupList[index].groupName!), - subtitle: Text(_groupList[index].groupDescription!), + title: Text(_groupList[index].groupName), + subtitle: Text(_groupList[index].groupDescription), trailing: Text( 'Members: ${_groupList[index].members.length}', style: const TextStyle( @@ -296,10 +322,14 @@ class _GroupViewState extends State { } // dummy ftn for loading new contacts + // ignore: unused_element void _addNewGroups() async { SharedPreferences prefs = await SharedPreferences.getInstance(); List _localList = []; - _localList = List.from(Group.decode(prefs.getString('groups'))); + final String _local = prefs.getString('groups'); + if (_local != null) { + _localList = List.from(Group.decode(_local)); + } List _groups = [ Group( diff --git a/packages/simplex_app/lib/views/home/drawer.dart b/packages/simplex_app/lib/views/home/drawer.dart index 207e2fd90..008177ffa 100644 --- a/packages/simplex_app/lib/views/home/drawer.dart +++ b/packages/simplex_app/lib/views/home/drawer.dart @@ -7,19 +7,17 @@ import 'package:simplex_chat/constants.dart'; import 'package:simplex_chat/providers/drawer_providers.dart'; class MyDrawer extends StatelessWidget { - final AnimationController? animationController; - const MyDrawer({Key? key, this.animationController}) : super(key: key); + const MyDrawer({Key key}) : super(key: key); @override Widget build(BuildContext context) { final _drawerProviders = Provider.of(context); return SizedBox( width: MediaQuery.of(context).size.width * 0.82, - child: Material( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Column( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Builder(builder: (context) { + return Column( children: [ const SizedBox(height: 30.0), SvgPicture.asset( @@ -32,30 +30,22 @@ class MyDrawer extends StatelessWidget { ? kPrimaryColor : Colors.transparent, leading: Icon( - Icons.contact_phone, + Icons.person, color: _drawerProviders.currentIndex == 0 ? Colors.white : Colors.grey, ), title: Text( - 'Your contacts', + 'Your Profile', style: TextStyle( color: _drawerProviders.currentIndex == 0 ? Colors.white : Colors.black, ), ), - subtitle: Text( - 'Start a conversation right away!', - style: TextStyle( - color: _drawerProviders.currentIndex == 0 - ? Colors.white - : Colors.grey, - ), - ), onTap: () { _drawerProviders.currentIndex = 0; - _drawerProviders.toggle(animationController); + Navigator.pop(context); }, ), ListTile( @@ -63,30 +53,22 @@ class MyDrawer extends StatelessWidget { ? kPrimaryColor : Colors.transparent, leading: Icon( - Icons.insert_invitation, + Icons.contact_phone, color: _drawerProviders.currentIndex == 1 ? Colors.white : Colors.grey, ), title: Text( - 'Invitations', + 'Your contacts', style: TextStyle( color: _drawerProviders.currentIndex == 1 ? Colors.white : Colors.black, ), ), - subtitle: Text( - 'Increase your contact circle!', - style: TextStyle( - color: _drawerProviders.currentIndex == 1 - ? Colors.white - : Colors.grey, - ), - ), onTap: () { _drawerProviders.currentIndex = 1; - _drawerProviders.toggle(animationController); + Navigator.pop(context); }, ), ListTile( @@ -94,47 +76,62 @@ class MyDrawer extends StatelessWidget { ? kPrimaryColor : Colors.transparent, leading: Icon( - Icons.group, + Icons.insert_invitation, color: _drawerProviders.currentIndex == 2 ? Colors.white : Colors.grey, ), title: Text( - 'Your groups', + 'Invitations', style: TextStyle( color: _drawerProviders.currentIndex == 2 ? Colors.white : Colors.black, ), ), - subtitle: Text( - 'Get in touch with numbers!', + onTap: () { + _drawerProviders.currentIndex = 2; + Navigator.pop(context); + }, + ), + ListTile( + tileColor: _drawerProviders.currentIndex == 3 + ? kPrimaryColor + : Colors.transparent, + leading: Icon( + Icons.group, + color: _drawerProviders.currentIndex == 3 + ? Colors.white + : Colors.grey, + ), + title: Text( + 'Your groups', style: TextStyle( - color: _drawerProviders.currentIndex == 2 + color: _drawerProviders.currentIndex == 3 ? Colors.white - : Colors.grey, + : Colors.black, ), ), onTap: () { - _drawerProviders.currentIndex = 2; - _drawerProviders.toggle(animationController); + _drawerProviders.currentIndex = 3; + Navigator.pop(context); }, ), const Spacer(), ListTile( - leading: const Icon(Icons.exit_to_app_rounded), - title: const Text('Logout'), - subtitle: const Text('Good bye! See you soon :)'), - onTap: () => _logout(context), + leading: const Icon(Icons.refresh), + title: const Text('Switch Profile'), + subtitle: const Text('*Not supported yet!*'), + onTap: () => _switchProfile(context), ), ], - ), - ), + ); + }), ), ); } - void _logout(BuildContext context) async { + void _switchProfile(BuildContext context) async { SharedPreferences prefs = await SharedPreferences.getInstance(); await Navigator.pushNamedAndRemoveUntil( @@ -142,7 +139,7 @@ class MyDrawer extends StatelessWidget { AppRoutes.setupProfile, (route) => route.settings.name == AppRoutes.setupProfile ? true : false, ); - String? _name = prefs.getString('displayName'); + String _name = prefs.getString('displayName'); await prefs.remove('displayName'); await prefs.remove('fullName'); await prefs.remove('photo$_name'); diff --git a/packages/simplex_app/lib/views/home/home_view.dart b/packages/simplex_app/lib/views/home/home_view.dart index 61e123fc5..177a06114 100644 --- a/packages/simplex_app/lib/views/home/home_view.dart +++ b/packages/simplex_app/lib/views/home/home_view.dart @@ -1,4 +1,3 @@ -import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -9,138 +8,60 @@ import 'package:simplex_chat/views/contacts/contacts_view.dart'; import 'package:simplex_chat/views/group/group_view.dart'; import 'package:simplex_chat/views/home/drawer.dart'; import 'package:simplex_chat/views/invitations/invitation_view.dart'; +import 'package:simplex_chat/views/profile/profile_view.dart'; class HomeView extends StatefulWidget { - final double? maxSlide; - const HomeView({ - Key? key, - this.maxSlide, - }) : super(key: key); + final double maxSlide; + const HomeView({Key key, this.maxSlide}) : super(key: key); @override _HomeViewState createState() => _HomeViewState(); } -class _HomeViewState extends State with TickerProviderStateMixin { - AnimationController? animationController; - bool? _canBeDragged; - +class _HomeViewState extends State { // views final List _views = [ + const ProfileView(), const ContactsView(), const Invitations(), const GroupView(), ]; - @override - void initState() { - super.initState(); - - animationController = AnimationController( - vsync: this, duration: const Duration(milliseconds: 250)); - } - @override Widget build(BuildContext context) { final _drawerProviders = Provider.of(context); return WillPopScope( onWillPop: _onWillPop, - child: GestureDetector( - onHorizontalDragStart: _onDragStart, - onHorizontalDragUpdate: _onDragUpdate, - onHorizontalDragEnd: _onDragEnd, - behavior: HitTestBehavior.translucent, - child: AnimatedBuilder( - animation: animationController!, - builder: (context, _) { - return Material( - color: Colors.white70, - child: SafeArea( - child: Stack( - children: [ - Transform.translate( - offset: Offset( - widget.maxSlide! * (animationController!.value - 1), - 0), - child: Transform( - transform: Matrix4.identity() - ..setEntry(3, 2, 0.001) - ..rotateY( - math.pi / 2 * (1 - animationController!.value)), - alignment: Alignment.centerRight, - child: MyDrawer( - animationController: animationController, - ), - ), + child: SafeArea( + child: Scaffold( + drawer: const Drawer( + child: MyDrawer(), + ), + body: Builder(builder: (context) { + return Stack( + children: [ + _views[_drawerProviders.currentIndex], + Positioned( + top: MediaQuery.of(context).size.height * 0.03, + left: MediaQuery.of(context).size.width * 0.03, + child: InkWell( + onTap: () { + Scaffold.of(context).openDrawer(); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/menu.svg'), ), - Transform.translate( - offset: Offset( - widget.maxSlide! * animationController!.value, 0), - child: Transform( - transform: Matrix4.identity() - ..setEntry(3, 2, 0.001) - ..rotateY( - -math.pi / 2 * animationController!.value), - alignment: Alignment.centerLeft, - child: _views[_drawerProviders.currentIndex]), - ), - Positioned( - top: MediaQuery.of(context).padding.top, - left: MediaQuery.of(context).size.width * 0.03 + - animationController!.value * widget.maxSlide!, - child: InkWell( - onTap: () { - _drawerProviders.toggle(animationController); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: SvgPicture.asset( - 'assets/menu.svg', - ), - ), - ), - ), - ], + ), ), - ), + ], ); - }, + }), ), ), ); } - void _onDragStart(DragStartDetails details) { - bool isDragOpenFromLeft = animationController!.isDismissed; - bool isDragCloseFromRight = animationController!.isCompleted; - _canBeDragged = isDragOpenFromLeft || isDragCloseFromRight; - } - - void _onDragUpdate(DragUpdateDetails details) { - if (_canBeDragged!) { - double delta = details.primaryDelta! / widget.maxSlide!; - animationController!.value += delta; - } - } - - void _onDragEnd(DragEndDetails details) { - double _kMinFlingVelocity = 365.0; - - if (animationController!.isDismissed || animationController!.isCompleted) { - return; - } - if (details.velocity.pixelsPerSecond.dx.abs() >= _kMinFlingVelocity) { - double visualVelocity = details.velocity.pixelsPerSecond.dx / - MediaQuery.of(context).size.width; - - animationController!.fling(velocity: visualVelocity); - } else if (animationController!.value < 0.5) { - animationController!.reverse(); - } else { - animationController!.forward(); - } - } - Future _onWillPop() async { return (await showDialog( context: context, diff --git a/packages/simplex_app/lib/views/invitations/invitation_view.dart b/packages/simplex_app/lib/views/invitations/invitation_view.dart index 02e45166f..28cfdbb63 100644 --- a/packages/simplex_app/lib/views/invitations/invitation_view.dart +++ b/packages/simplex_app/lib/views/invitations/invitation_view.dart @@ -1,9 +1,33 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:simplex_chat/constants.dart'; -class Invitations extends StatelessWidget { - const Invitations({Key? key}) : super(key: key); +class Invitations extends StatefulWidget { + const Invitations({Key key}) : super(key: key); + + @override + State createState() => _InvitationsState(); +} + +class _InvitationsState extends State { + String _photo = ''; + String _displayName = ''; + + void _getUserData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _displayName = prefs.getString('displayName'); + _photo = prefs.getString('photo$_displayName'); + }); + } + + @override + void initState() { + _getUserData(); + super.initState(); + } @override Widget build(BuildContext context) { @@ -13,12 +37,23 @@ class Invitations extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0), child: Column( children: [ - Align( - alignment: Alignment.centerRight, - child: SvgPicture.asset( - 'assets/logo.svg', - height: 40.0, - ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Hi! $_displayName', style: kSmallHeadingStyle), + const Text('Good day!'), + ], + ), + const SizedBox(width: 10.0), + CircleAvatar( + backgroundImage: _photo.isEmpty + ? const AssetImage('assets/dp.png') as ImageProvider + : FileImage(File(_photo)), + ), + ], ), const SizedBox(height: 15.0), Row( diff --git a/packages/simplex_app/lib/views/onBoarding/intro_view.dart b/packages/simplex_app/lib/views/onBoarding/intro_view.dart index aabd4ece3..765e49637 100644 --- a/packages/simplex_app/lib/views/onBoarding/intro_view.dart +++ b/packages/simplex_app/lib/views/onBoarding/intro_view.dart @@ -4,7 +4,7 @@ import 'package:simplex_chat/app_routes.dart'; import 'package:simplex_chat/constants.dart'; class IntroView extends StatelessWidget { - const IntroView({Key? key}) : super(key: key); + const IntroView({Key key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/packages/simplex_app/lib/views/profile/profile_view.dart b/packages/simplex_app/lib/views/profile/profile_view.dart new file mode 100644 index 000000000..e6b417b72 --- /dev/null +++ b/packages/simplex_app/lib/views/profile/profile_view.dart @@ -0,0 +1,318 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:simplex_chat/constants.dart'; +import 'package:simplex_chat/widgets/custom_text_field.dart'; + +class ProfileView extends StatefulWidget { + const ProfileView({Key key}) : super(key: key); + + @override + _ProfileViewState createState() => _ProfileViewState(); +} + +class _ProfileViewState extends State { + final _formKey = GlobalKey(); + // controllers + final TextEditingController _displayNameController = TextEditingController(); + final TextEditingController _fullNameController = TextEditingController(); + + // Image Picker --> DP properties + final imgPicker = ImagePicker(); + File image; + String _photo = ''; + bool _uploading = false; + + // image buttons options + final _dpBtnText = ['Remove', 'Gallery', 'Camera']; + final _dpBtnColors = [Colors.red, Colors.purple, Colors.green]; + final _dpBtnIcons = [ + Icons.delete, + Icons.photo_rounded, + Icons.camera_alt_rounded + ]; + + String _displayName = ''; + String _fullName = ''; + + void _getUserData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() { + _fullName = prefs.getString('fullName'); + _displayName = prefs.getString('displayName'); + _photo = prefs.getString('photo$_displayName'); + }); + _displayNameController.text = _displayName; + if (_fullName != null) _fullNameController.text = _fullName; + } + + @override + void initState() { + _getUserData(); + super.initState(); + } + + @override + void dispose() { + _displayNameController.dispose(); + _fullNameController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 30), + Center( + child: SizedBox( + height: 180.0, + width: 180.0, + child: Stack( + children: [ + _photo != '' + ? CircleAvatar( + radius: 100.0, + backgroundImage: FileImage(File(_photo)), + ) + : const CircleAvatar( + radius: 100.0, + backgroundImage: AssetImage('assets/dp.png'), + ), + Positioned( + right: 0, + bottom: 0, + child: FloatingActionButton( + backgroundColor: kSecondaryColor, + elevation: 2.0, + mini: true, + onPressed: _updateProfilePic, + child: _uploading + ? const SizedBox( + height: 18.0, + width: 18.0, + child: CircularProgressIndicator( + strokeWidth: 2.0, + valueColor: + AlwaysStoppedAnimation( + Colors.white), + ), + ) + : const Icon( + Icons.add_a_photo, + size: 20, + ), + ), + ) + ], + ), + )), + const SizedBox(height: 25.0), + const Text('Display Name', style: kSmallHeadingStyle), + const SizedBox(height: 10.0), + CustomTextField( + textEditingController: _displayNameController, + textInputType: TextInputType.name, + hintText: 'e.g John', + validatorFtn: (value) { + if (value.isEmpty) { + return 'Display name cannot be empty'; + } + return null; + }, + ), + const SizedBox(height: 25.0), + const Text('Full Name', style: kSmallHeadingStyle), + const SizedBox(height: 10.0), + CustomTextField( + textEditingController: _fullNameController, + textInputType: TextInputType.name, + hintText: 'e.g John Doe', + ), + const SizedBox(height: 25.0), + const Text( + 'Your display name is what your contact will know you :)', + style: TextStyle(letterSpacing: 1.2), + ) + ], + ), + ), + ), + ), + ), + ), + floatingActionButton: Visibility( + visible: MediaQuery.of(context).viewInsets.bottom == 0, + child: FloatingActionButton( + heroTag: 'setup', + onPressed: () async { + if (_formKey.currentState.validate()) { + FocusScope.of(context).unfocus(); + await _createProfile(); + const snackBar = SnackBar( + backgroundColor: Colors.green, + content: Text('Profile updated!'), + ); + + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar(snackBar); + } + }, + child: const Icon(Icons.check), + ), + ), + ); + } + + // create profile and store in local + Future _createProfile() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.setString('displayName', _displayNameController.text.trim()); + await prefs.setString('fullName', _fullNameController.text.trim()); + await prefs.setString('photo${_displayNameController.text.trim()}', _photo); + + debugPrint(prefs.getString('photo')); + } + + void _updateProfilePic() { + showModalBottomSheet( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10.0), + topRight: Radius.circular(10.0), + ), + ), + context: context, + builder: (context) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 20.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + decoration: BoxDecoration( + color: Colors.grey, + borderRadius: BorderRadius.circular(360.0)), + height: 7.0, + width: 50.0, + ), + const SizedBox(height: 20.0), + const Align( + alignment: Alignment.centerLeft, + child: Text( + ' Profile photo', + style: kHeadingStyle, + ), + ), + const SizedBox(height: 15.0), + Row( + children: List.generate( + 3, + (index) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + MaterialButton( + color: _dpBtnColors.map((e) => e).elementAt(index), + shape: const CircleBorder(), + onPressed: index == 0 + ? () => _removePic() + : index == 1 + ? () => _galleryPic() + : () => _cameraPic(), + child: Icon( + _dpBtnIcons.map((e) => e).elementAt(index), + color: Colors.white, + ), + ), + Text( + _dpBtnText.map((e) => e).elementAt(index), + textAlign: TextAlign.center, + ) + ], + ), + )) + ], + ), + ), + ); + } + + void _removePic() { + setState(() { + image = null; + _photo = ''; + }); + Navigator.pop(context); + } + + void _cameraPic() async { + try { + setState(() { + _uploading = true; + }); + + // picking Image from Camera + final file = await imgPicker.getImage( + source: ImageSource.camera, + ); + + if (file != null) { + image = File(file.path); + setState(() { + _uploading = false; + _photo = file.path; + }); + } else { + setState(() { + _uploading = false; + }); + } + + Navigator.pop(context); + } catch (e) { + rethrow; + } + } + + void _galleryPic() async { + try { + debugPrint('gallery pic'); + setState(() { + _uploading = true; + }); + + // picking Image from local storage + final file = await imgPicker.getImage( + source: ImageSource.gallery, + ); + + if (file != null) { + image = File(file.path); + setState(() { + _uploading = false; + _photo = file.path; + }); + } else { + setState(() { + _uploading = false; + }); + } + + Navigator.pop(context); + } catch (e) { + rethrow; + } + } +} diff --git a/packages/simplex_app/lib/views/scanInvitation/scan_invitation_view.dart b/packages/simplex_app/lib/views/scanInvitation/scan_invitation_view.dart index 265ef8691..cb9d4a6cc 100644 --- a/packages/simplex_app/lib/views/scanInvitation/scan_invitation_view.dart +++ b/packages/simplex_app/lib/views/scanInvitation/scan_invitation_view.dart @@ -4,7 +4,7 @@ import 'package:simplex_chat/constants.dart'; import 'package:simplex_chat/widgets/custom_btn.dart'; class ScanInvitationView extends StatelessWidget { - const ScanInvitationView({Key? key}) : super(key: key); + const ScanInvitationView({Key key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/packages/simplex_app/lib/views/setup_profile_view.dart b/packages/simplex_app/lib/views/setup_profile_view.dart index 03e66b232..18b2df2eb 100644 --- a/packages/simplex_app/lib/views/setup_profile_view.dart +++ b/packages/simplex_app/lib/views/setup_profile_view.dart @@ -8,7 +8,7 @@ import 'package:simplex_chat/views/home/home_view.dart'; import 'package:simplex_chat/widgets/custom_text_field.dart'; class SetupProfileView extends StatefulWidget { - const SetupProfileView({Key? key}) : super(key: key); + const SetupProfileView({Key key}) : super(key: key); @override _SetupProfileViewState createState() => _SetupProfileViewState(); @@ -22,7 +22,7 @@ class _SetupProfileViewState extends State { // Image Picker --> DP properties final imgPicker = ImagePicker(); - File? image; + File image; String photoUrl = ''; bool _uploading = false; bool _imageUploaded = false; @@ -63,7 +63,7 @@ class _SetupProfileViewState extends State { _imageUploaded ? CircleAvatar( radius: 100.0, - backgroundImage: FileImage(image!), + backgroundImage: FileImage(image), ) : const CircleAvatar( radius: 100.0, @@ -105,8 +105,8 @@ class _SetupProfileViewState extends State { textInputType: TextInputType.name, hintText: 'e.g John', validatorFtn: (value) { - if (value!.isEmpty) { - return 'Display name cannot be empty!'; + if (value.isEmpty) { + return 'Display name cannot be empty'; } return null; }, @@ -118,12 +118,6 @@ class _SetupProfileViewState extends State { textEditingController: _fullNameController, textInputType: TextInputType.name, hintText: 'e.g John Doe', - validatorFtn: (value) { - if (value!.isEmpty) { - return 'Full name cannot be empty!'; - } - return null; - }, ), const SizedBox(height: 25.0), const Text( @@ -142,7 +136,7 @@ class _SetupProfileViewState extends State { child: FloatingActionButton( heroTag: 'setup', onPressed: () async { - if (_formKey.currentState!.validate()) { + if (_formKey.currentState.validate()) { FocusScope.of(context).unfocus(); await _createProfile(); @@ -269,6 +263,7 @@ class _SetupProfileViewState extends State { void _galleryPic() async { try { + debugPrint('gallery pic'); setState(() { _uploading = true; }); diff --git a/packages/simplex_app/lib/views/splash_screen.dart b/packages/simplex_app/lib/views/splash_screen.dart index 24dbc57a8..fb07e5f10 100644 --- a/packages/simplex_app/lib/views/splash_screen.dart +++ b/packages/simplex_app/lib/views/splash_screen.dart @@ -1,14 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:progress_indicators/progress_indicators.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:simplex_chat/animations/entrance_fader.dart'; +import 'package:simplex_chat/app_routes.dart'; import 'package:simplex_chat/constants.dart'; -import 'package:simplex_chat/views/home/home_view.dart'; -import 'package:simplex_chat/views/onBoarding/intro_view.dart'; class SplashScreen extends StatefulWidget { - const SplashScreen({Key? key}) : super(key: key); + const SplashScreen({Key key}) : super(key: key); @override _SplashScreenState createState() => _SplashScreenState(); @@ -16,19 +14,11 @@ class SplashScreen extends StatefulWidget { class _SplashScreenState extends State { // logincheck - void _loginCheck() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - String? _name = prefs.getString('displayName'); + void _loginCheck() { Future.delayed(const Duration(seconds: 4), () { - Navigator.push( + Navigator.pushNamed( context, - MaterialPageRoute( - builder: (_) => _name == null - ? const IntroView() - : HomeView( - maxSlide: MediaQuery.of(context).size.width * 0.82, - ), - ), + AppRoutes.intro, ); }); } diff --git a/packages/simplex_app/lib/widgets/custom_btn.dart b/packages/simplex_app/lib/widgets/custom_btn.dart index 3fd347e9a..0a959fe5c 100644 --- a/packages/simplex_app/lib/widgets/custom_btn.dart +++ b/packages/simplex_app/lib/widgets/custom_btn.dart @@ -7,13 +7,13 @@ class CustomButton extends StatelessWidget { @required this.onPressed, @required this.color, @required this.child, - Key? key}) + Key key}) : super(key: key); - final double? width; - final double? height; - final void Function()? onPressed; - final Widget? child; - final Color? color; + final double width; + final double height; + final void Function() onPressed; + final Widget child; + final Color color; @override Widget build(BuildContext context) { diff --git a/packages/simplex_app/lib/widgets/custom_text_field.dart b/packages/simplex_app/lib/widgets/custom_text_field.dart index 9164056f9..4b5f0db34 100644 --- a/packages/simplex_app/lib/widgets/custom_text_field.dart +++ b/packages/simplex_app/lib/widgets/custom_text_field.dart @@ -1,27 +1,27 @@ import 'package:flutter/material.dart'; class CustomTextField extends StatefulWidget { - final TextEditingController? textEditingController; - final TextInputType? textInputType; - final FocusNode? node; + final TextEditingController textEditingController; + final TextInputType textInputType; + final FocusNode node; - final String? hintText; - final bool? isPassword; - final IconData? icon; - final Color? iconColor; - final Color? passIconColor; + final String hintText; + final bool isPassword; + final IconData icon; + final Color iconColor; + final Color passIconColor; - final IconData? trailing; - final void Function()? trailingCallBack; + final IconData trailing; + final void Function() trailingCallBack; - final Function(String)? onChangeFtn; - final void Function()? onEditComplete; - final String? Function(String?)? validatorFtn; - final Function(String)? onFieldSubmit; - final String? errorText; + final Function(String) onChangeFtn; + final void Function() onEditComplete; + final String Function(String) validatorFtn; + final Function(String) onFieldSubmit; + final String errorText; const CustomTextField({ - Key? key, + Key key, @required this.textEditingController, @required this.textInputType, this.trailing, diff --git a/packages/simplex_app/lib/widgets/message_bubble.dart b/packages/simplex_app/lib/widgets/message_bubble.dart index 78863c15e..3536dfaf1 100644 --- a/packages/simplex_app/lib/widgets/message_bubble.dart +++ b/packages/simplex_app/lib/widgets/message_bubble.dart @@ -3,14 +3,14 @@ import 'package:simplex_chat/constants.dart'; class MessageBubble extends StatefulWidget { const MessageBubble({ - Key? key, + Key key, this.sender, this.text, this.isUser, }) : super(key: key); - final String? sender; - final String? text; - final bool? isUser; + final String sender; + final String text; + final bool isUser; @override _MessageBubbleState createState() => _MessageBubbleState(); @@ -23,15 +23,15 @@ class _MessageBubbleState extends State { padding: const EdgeInsets.all(10), child: Column( crossAxisAlignment: - widget.isUser! ? CrossAxisAlignment.end : CrossAxisAlignment.start, + widget.isUser ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ Text( - widget.sender!, + widget.sender, style: const TextStyle(fontSize: 12, color: Colors.grey), ), const SizedBox(height: 2.0), Material( - borderRadius: widget.isUser! + borderRadius: widget.isUser ? const BorderRadius.only( topLeft: Radius.circular(10), bottomLeft: Radius.circular(10), @@ -41,11 +41,11 @@ class _MessageBubbleState extends State { bottomLeft: Radius.circular(10), bottomRight: Radius.circular(10)), elevation: 1.0, - color: widget.isUser! ? Colors.teal : kPrimaryColor, + color: widget.isUser ? Colors.teal : kPrimaryColor, child: Padding( padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15), child: Text( - widget.text!, + widget.text, style: const TextStyle(fontSize: 15, color: Colors.white), ), ), diff --git a/packages/simplex_app/pubspec.yaml b/packages/simplex_app/pubspec.yaml index 15aacfb1a..6b4c6ff57 100644 --- a/packages/simplex_app/pubspec.yaml +++ b/packages/simplex_app/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.10.0 <3.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions