null safe code + latest dart SDK
This commit is contained in:
parent
368f9ef617
commit
6b5d4c3958
@ -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<Animator>
|
||||
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<Animator>
|
||||
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<Animator>
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
@ -69,7 +69,7 @@ Duration wait() {
|
||||
class WidgetAnimator extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const WidgetAnimator({this.child, Key key}) : super(key: key);
|
||||
const WidgetAnimator({required this.child, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -14,8 +14,8 @@ class EntranceFader extends StatefulWidget {
|
||||
final Offset offset;
|
||||
|
||||
const EntranceFader({
|
||||
Key key,
|
||||
this.child,
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.delay = const Duration(milliseconds: 0),
|
||||
this.duration = const Duration(milliseconds: 400),
|
||||
this.offset = const Offset(0.0, 32.0),
|
||||
@ -29,39 +29,39 @@ class EntranceFader extends StatefulWidget {
|
||||
|
||||
class EntranceFaderState extends State<EntranceFader>
|
||||
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,
|
||||
),
|
||||
),
|
||||
|
@ -14,6 +14,5 @@ class ScrollBehaviorModified extends ScrollBehavior {
|
||||
case TargetPlatform.windows:
|
||||
return const ClampingScrollPhysics();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -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,7 +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: <String, WidgetBuilder>{
|
||||
|
@ -7,8 +7,8 @@ class Contact {
|
||||
final bool isGroup;
|
||||
|
||||
Contact({
|
||||
this.name,
|
||||
this.subtitle,
|
||||
required this.name,
|
||||
required this.subtitle,
|
||||
this.photo = '',
|
||||
this.isGroup = false,
|
||||
});
|
||||
|
@ -8,8 +8,8 @@ class Group {
|
||||
final bool isGroup;
|
||||
|
||||
Group({
|
||||
this.name,
|
||||
this.subtitle,
|
||||
required this.name,
|
||||
required this.subtitle,
|
||||
this.photo = '',
|
||||
this.isGroup = true,
|
||||
this.members = const [],
|
||||
|
@ -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<AddContactView> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ class _AddContactViewState extends State<AddContactView> {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => QRCodeDetailsView(
|
||||
barcode: result,
|
||||
barcode: result!,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,28 +1,23 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:simplex_chat/animations/bottom_animation.dart';
|
||||
import 'package:simplex_chat/app_routes.dart';
|
||||
import 'package:simplex_chat/constants.dart';
|
||||
import 'package:simplex_chat/model/contact.dart';
|
||||
import 'package:simplex_chat/model/group.dart';
|
||||
import 'package:simplex_chat/providers/drawer_providers.dart';
|
||||
import 'package:simplex_chat/views/conversation/conversation_view.dart';
|
||||
|
||||
class Conversations extends StatefulWidget {
|
||||
const Conversations({Key key}) : super(key: key);
|
||||
const Conversations({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ConversationsState createState() => _ConversationsState();
|
||||
}
|
||||
|
||||
class _ConversationsState extends State<Conversations> {
|
||||
bool _eraseMedia = false;
|
||||
|
||||
String _photo = '';
|
||||
String _displayName = '';
|
||||
bool? _eraseMedia = false;
|
||||
|
||||
List<dynamic> _conversations = [];
|
||||
|
||||
@ -38,7 +33,7 @@ class _ConversationsState extends State<Conversations> {
|
||||
// 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');
|
||||
if (_contacts != null) {
|
||||
setState(() {
|
||||
_contactsList = List.from(Contact.decode(_contacts));
|
||||
@ -49,7 +44,7 @@ class _ConversationsState extends State<Conversations> {
|
||||
// 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));
|
||||
@ -59,14 +54,6 @@ class _ConversationsState extends State<Conversations> {
|
||||
_gettingGroupContactsChats();
|
||||
}
|
||||
|
||||
void _getUserData() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
setState(() {
|
||||
_displayName = prefs.getString('displayName');
|
||||
_photo = prefs.getString('photo$_displayName');
|
||||
});
|
||||
}
|
||||
|
||||
void _gettingGroupContactsChats() {
|
||||
setState(() {
|
||||
_conversations = List.from(_contactsList);
|
||||
@ -76,7 +63,6 @@ class _ConversationsState extends State<Conversations> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_getUserData();
|
||||
_getContacts();
|
||||
_getGroups();
|
||||
super.initState();
|
||||
@ -84,7 +70,6 @@ class _ConversationsState extends State<Conversations> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _drawerProviders = Provider.of<DrawerProvider>(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SingleChildScrollView(
|
||||
@ -93,42 +78,19 @@ class _ConversationsState extends State<Conversations> {
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: _addNewContacts,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text('Hi! $_displayName', style: kSmallHeadingStyle),
|
||||
const Text('Good day!'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
_drawerProviders.currentIndex = 0;
|
||||
},
|
||||
child: CircleAvatar(
|
||||
backgroundImage: _photo.isEmpty
|
||||
? const AssetImage('assets/dp.png') as ImageProvider
|
||||
: FileImage(File(_photo)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15.0),
|
||||
Row(
|
||||
children: const [
|
||||
Icon(Icons.chat, color: kPrimaryColor),
|
||||
SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Conversations',
|
||||
style: kHeadingStyle,
|
||||
)
|
||||
],
|
||||
const SizedBox(height: 40.0),
|
||||
GestureDetector(
|
||||
onTap: _addNewContacts,
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.chat, color: kPrimaryColor),
|
||||
SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Conversations',
|
||||
style: kHeadingStyle,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
_contactsList.isEmpty
|
||||
@ -219,7 +181,7 @@ class _ConversationsState extends State<Conversations> {
|
||||
await Navigator.pushNamed(context, AppRoutes.addContact);
|
||||
} else {
|
||||
var value = await Navigator.pushNamed(context, AppRoutes.addGroup);
|
||||
if (value) {
|
||||
if (value == true) {
|
||||
_getGroups();
|
||||
}
|
||||
}
|
||||
@ -414,7 +376,7 @@ class _ConversationsState extends State<Conversations> {
|
||||
|
||||
// adding dummy contact
|
||||
List<Contact> _localList = [];
|
||||
final String _local = prefs.getString('contacts');
|
||||
final String? _local = prefs.getString('contacts');
|
||||
if (_local != null) {
|
||||
_localList = List.from(Contact.decode(_local));
|
||||
}
|
||||
@ -434,9 +396,9 @@ class _ConversationsState extends State<Conversations> {
|
||||
|
||||
// adding dummy contact
|
||||
List<Group> _localListGroup = [];
|
||||
final String _localGroups = prefs.getString('groups');
|
||||
final String? _localGroups = prefs.getString('groups');
|
||||
if (_local != null) {
|
||||
_localListGroup = List.from(Group.decode(_localGroups));
|
||||
_localListGroup = List.from(Group.decode(_localGroups!));
|
||||
}
|
||||
|
||||
List<Group> _newGroups = [
|
||||
|
@ -6,8 +6,8 @@ import 'package:simplex_chat/widgets/custom_btn.dart';
|
||||
class QRCodeDetailsView extends StatelessWidget {
|
||||
final Barcode barcode;
|
||||
const QRCodeDetailsView({
|
||||
Key key,
|
||||
this.barcode,
|
||||
Key? key,
|
||||
required this.barcode,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -4,7 +4,8 @@ import 'package:simplex_chat/model/contact.dart';
|
||||
|
||||
class ContactDetailsConversation extends StatelessWidget {
|
||||
final Contact contact;
|
||||
const ContactDetailsConversation({Key key, this.contact}) : super(key: key);
|
||||
const ContactDetailsConversation({Key? key, required this.contact})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -6,8 +6,9 @@ import 'package:simplex_chat/views/conversation/group_detail_conversation.dart';
|
||||
import 'package:simplex_chat/widgets/message_bubble.dart';
|
||||
|
||||
class ConversationView extends StatefulWidget {
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
final data;
|
||||
const ConversationView({Key key, this.data}) : super(key: key);
|
||||
const ConversationView({Key? key, this.data}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ConversationViewState createState() => _ConversationViewState();
|
||||
@ -17,16 +18,16 @@ class _ConversationViewState extends State<ConversationView> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
final TextEditingController _messageFieldController = TextEditingController();
|
||||
|
||||
FocusNode _focus;
|
||||
FocusNode? _focus;
|
||||
bool _fieldEnabled = false;
|
||||
final List<Widget> _chatMessages = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_focus = FocusNode();
|
||||
_focus.addListener(() {
|
||||
debugPrint('FOCUS ${_focus.hasFocus}');
|
||||
_fieldEnabled = _focus.hasFocus;
|
||||
_focus!.addListener(() {
|
||||
debugPrint('FOCUS ${_focus!.hasFocus}');
|
||||
_fieldEnabled = _focus!.hasFocus;
|
||||
debugPrint('MESSAGE ENABLED $_fieldEnabled');
|
||||
});
|
||||
super.initState();
|
||||
@ -36,7 +37,7 @@ class _ConversationViewState extends State<ConversationView> {
|
||||
void dispose() {
|
||||
_messageFieldController.dispose();
|
||||
_scrollController.dispose();
|
||||
_focus.dispose();
|
||||
_focus!.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@ -81,7 +82,7 @@ class _ConversationViewState extends State<ConversationView> {
|
||||
radius: 15,
|
||||
// ignore: avoid_dynamic_calls
|
||||
backgroundImage: widget.data.photo == ''
|
||||
? const AssetImage('assets/dp.png')
|
||||
? const AssetImage('assets/dp.png') as ImageProvider
|
||||
: FileImage(
|
||||
// ignore: avoid_dynamic_calls
|
||||
File(widget.data.photo),
|
||||
@ -175,7 +176,7 @@ class _ConversationViewState extends State<ConversationView> {
|
||||
));
|
||||
});
|
||||
_messageFieldController.clear();
|
||||
_focus.unfocus();
|
||||
_focus!.unfocus();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.send_rounded,
|
||||
|
@ -8,7 +8,8 @@ import 'package:simplex_chat/model/group.dart';
|
||||
|
||||
class GroupDetailsConversation extends StatefulWidget {
|
||||
final Group group;
|
||||
const GroupDetailsConversation({Key key, this.group}) : super(key: key);
|
||||
const GroupDetailsConversation({Key? key, required this.group})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_GroupDetailsConversationState createState() =>
|
||||
@ -33,7 +34,7 @@ class _GroupDetailsConversationState extends State<GroupDetailsConversation> {
|
||||
// getting groups
|
||||
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));
|
||||
@ -44,9 +45,9 @@ class _GroupDetailsConversationState extends State<GroupDetailsConversation> {
|
||||
// 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));
|
||||
_contactsList = List.from(Contact.decode(_contacts!));
|
||||
});
|
||||
}
|
||||
|
||||
@ -75,7 +76,7 @@ class _GroupDetailsConversationState extends State<GroupDetailsConversation> {
|
||||
child: CircleAvatar(
|
||||
radius: 70,
|
||||
backgroundImage: widget.group.photo == ''
|
||||
? const AssetImage('assets/dp.png')
|
||||
? const AssetImage('assets/dp.png') as ImageProvider
|
||||
: FileImage(File(widget.group.photo)),
|
||||
),
|
||||
),
|
||||
@ -197,8 +198,7 @@ class _GroupDetailsConversationState extends State<GroupDetailsConversation> {
|
||||
// get index of group in local
|
||||
int index = 0;
|
||||
|
||||
index = _groupList
|
||||
.indexWhere((group) => group.name == widget.group.name);
|
||||
index = _groupList.indexWhere((group) => group.name == widget.group.name);
|
||||
|
||||
// add the full _members list to the group
|
||||
Group _updatedGroup = Group(
|
||||
@ -235,8 +235,7 @@ class _GroupDetailsConversationState extends State<GroupDetailsConversation> {
|
||||
// get index of group in local
|
||||
int index = 0;
|
||||
|
||||
index = _groupList
|
||||
.indexWhere((group) => group.name == widget.group.name);
|
||||
index = _groupList.indexWhere((group) => group.name == widget.group.name);
|
||||
|
||||
// new instance of group (updated)
|
||||
Group _updatedGroup = Group(
|
||||
|
@ -9,7 +9,7 @@ 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();
|
||||
@ -18,7 +18,7 @@ class AddGroupView extends StatefulWidget {
|
||||
class _AddGroupViewState extends State<AddGroupView> {
|
||||
// Image Picker --> DP properties
|
||||
final imgPicker = ImagePicker();
|
||||
File image;
|
||||
File? image;
|
||||
String _groupPhotoPath = '';
|
||||
bool _uploading = false;
|
||||
bool _imageUploaded = false;
|
||||
@ -43,16 +43,16 @@ class _AddGroupViewState extends State<AddGroupView> {
|
||||
// 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));
|
||||
_contactsList = List.from(Contact.decode(_contacts!));
|
||||
});
|
||||
}
|
||||
|
||||
String _userPhotoPath = '';
|
||||
void _getUserPhoto() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String _photo = prefs.getString('photo${prefs.getString('displayName')}');
|
||||
String? _photo = prefs.getString('photo${prefs.getString('displayName')}');
|
||||
if (_photo != null) {
|
||||
setState(() {
|
||||
_userPhotoPath = _photo;
|
||||
@ -147,8 +147,8 @@ class _AddGroupViewState extends State<AddGroupView> {
|
||||
textEditingController: _displayNameController,
|
||||
textInputType: TextInputType.name,
|
||||
hintText: 'e.g College friends',
|
||||
validatorFtn: (value) {
|
||||
if (value.isEmpty) {
|
||||
validatorFtn: (String? value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Group name cannot be empty';
|
||||
}
|
||||
return null;
|
||||
@ -249,10 +249,9 @@ class _AddGroupViewState extends State<AddGroupView> {
|
||||
child: FloatingActionButton(
|
||||
heroTag: 'setup',
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState.validate()) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
FocusScope.of(context).unfocus();
|
||||
_addNewGroup(
|
||||
_displayNameController.text.trim(),
|
||||
_addNewGroup(_displayNameController.text.trim(),
|
||||
_descController.text.trim());
|
||||
_descController.clear();
|
||||
_displayNameController.clear();
|
||||
@ -400,7 +399,7 @@ class _AddGroupViewState extends State<AddGroupView> {
|
||||
void _addNewGroup(String name, String desc) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
List<Group> _localList = [];
|
||||
final String _local = prefs.getString('groups');
|
||||
final String? _local = prefs.getString('groups');
|
||||
if (_local != null) {
|
||||
_localList = List.from(Group.decode(_local));
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:simplex_chat/app_routes.dart';
|
||||
import 'package:simplex_chat/constants.dart';
|
||||
import 'package:simplex_chat/providers/drawer_providers.dart';
|
||||
|
||||
class MyDrawer extends StatelessWidget {
|
||||
const MyDrawer({Key key}) : super(key: key);
|
||||
const MyDrawer({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -100,7 +99,7 @@ class MyDrawer extends StatelessWidget {
|
||||
|
||||
int _count = 0;
|
||||
Navigator.of(context).popUntil((route) => _count++ >= 2);
|
||||
String _name = prefs.getString('displayName');
|
||||
String? _name = prefs.getString('displayName');
|
||||
await prefs.remove('displayName');
|
||||
await prefs.remove('fullName');
|
||||
await prefs.remove('photo$_name');
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:simplex_chat/constants.dart';
|
||||
import 'package:simplex_chat/providers/drawer_providers.dart';
|
||||
import 'package:simplex_chat/views/contacts/conversations.dart';
|
||||
@ -11,13 +14,16 @@ 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);
|
||||
const HomeView({Key? key, required this.maxSlide}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HomeViewState createState() => _HomeViewState();
|
||||
}
|
||||
|
||||
class _HomeViewState extends State<HomeView> {
|
||||
String? _photo = '';
|
||||
String? _displayName = '';
|
||||
|
||||
// views
|
||||
final List<Widget> _views = [
|
||||
const ProfileView(),
|
||||
@ -25,43 +31,88 @@ class _HomeViewState extends State<HomeView> {
|
||||
const Invitations(),
|
||||
];
|
||||
|
||||
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) {
|
||||
final _drawerProviders = Provider.of<DrawerProvider>(context);
|
||||
return WillPopScope(
|
||||
onWillPop: _onWillPop,
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
drawer: const Drawer(
|
||||
child: MyDrawer(),
|
||||
),
|
||||
body: Builder(builder: (context) {
|
||||
child: Scaffold(
|
||||
drawer: const Drawer(
|
||||
child: MyDrawer(),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: 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: _drawerProviders.currentIndex == 0
|
||||
? InkWell(
|
||||
_drawerProviders.currentIndex == 0
|
||||
? Positioned(
|
||||
top: MediaQuery.of(context).size.height * 0.017,
|
||||
left: MediaQuery.of(context).size.width * 0.02,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_drawerProviders.currentIndex = 1;
|
||||
_getUserData();
|
||||
},
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Icon(Icons.arrow_back),
|
||||
),
|
||||
)
|
||||
: InkWell(
|
||||
onTap: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset('assets/menu.svg'),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SvgPicture.asset('assets/menu.svg'),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text('Hi! $_displayName',
|
||||
style: kSmallHeadingStyle),
|
||||
const Text('Good day!'),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
_drawerProviders.currentIndex = 0;
|
||||
},
|
||||
child: CircleAvatar(
|
||||
backgroundImage: _photo!.isEmpty
|
||||
? const AssetImage('assets/dp.png')
|
||||
as ImageProvider
|
||||
: FileImage(File(_photo!)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
@ -1,31 +1,16 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:simplex_chat/constants.dart';
|
||||
|
||||
class Invitations extends StatefulWidget {
|
||||
const Invitations({Key key}) : super(key: key);
|
||||
const Invitations({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Invitations> createState() => _InvitationsState();
|
||||
}
|
||||
|
||||
class _InvitationsState extends State<Invitations> {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -37,25 +22,7 @@ class _InvitationsState extends State<Invitations> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
|
||||
child: Column(
|
||||
children: [
|
||||
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),
|
||||
const SizedBox(height: 40.0),
|
||||
Row(
|
||||
children: const [
|
||||
Icon(Icons.inventory_outlined, color: kPrimaryColor),
|
||||
|
@ -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) {
|
@ -7,7 +7,7 @@ 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);
|
||||
const ProfileView({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ProfileViewState createState() => _ProfileViewState();
|
||||
@ -21,8 +21,8 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
|
||||
// Image Picker --> DP properties
|
||||
final imgPicker = ImagePicker();
|
||||
File image;
|
||||
String _photo = '';
|
||||
File? image;
|
||||
String? _photo = '';
|
||||
bool _uploading = false;
|
||||
|
||||
// image buttons options
|
||||
@ -34,8 +34,8 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
Icons.camera_alt_rounded
|
||||
];
|
||||
|
||||
String _displayName = '';
|
||||
String _fullName = '';
|
||||
String? _displayName = '';
|
||||
String? _fullName = '';
|
||||
|
||||
void _getUserData() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
@ -44,8 +44,8 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
_displayName = prefs.getString('displayName');
|
||||
_photo = prefs.getString('photo$_displayName');
|
||||
});
|
||||
_displayNameController.text = _displayName;
|
||||
if (_fullName != null) _fullNameController.text = _fullName;
|
||||
_displayNameController.text = _displayName!;
|
||||
if (_fullName != null) _fullNameController.text = _fullName!;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -85,7 +85,7 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
_photo != ''
|
||||
? CircleAvatar(
|
||||
radius: 100.0,
|
||||
backgroundImage: FileImage(File(_photo)),
|
||||
backgroundImage: FileImage(File(_photo!)),
|
||||
)
|
||||
: const CircleAvatar(
|
||||
radius: 100.0,
|
||||
@ -127,7 +127,7 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
textInputType: TextInputType.name,
|
||||
hintText: 'e.g John',
|
||||
validatorFtn: (value) {
|
||||
if (value.isEmpty) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Display name cannot be empty';
|
||||
}
|
||||
return null;
|
||||
@ -156,8 +156,8 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
heroTag: 'save',
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState.validate()) {
|
||||
FocusManager.instance.primaryFocus.unfocus();
|
||||
if (_formKey.currentState!.validate()) {
|
||||
FocusManager.instance.primaryFocus!.unfocus();
|
||||
await _createProfile();
|
||||
const snackBar = SnackBar(
|
||||
backgroundColor: Colors.green,
|
||||
@ -179,7 +179,7 @@ class _ProfileViewState extends State<ProfileView> {
|
||||
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);
|
||||
await prefs.setString('photo${_displayNameController.text.trim()}', _photo!);
|
||||
|
||||
debugPrint(prefs.getString('photo'));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<SetupProfileView> {
|
||||
|
||||
// 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<SetupProfileView> {
|
||||
_imageUploaded
|
||||
? CircleAvatar(
|
||||
radius: 100.0,
|
||||
backgroundImage: FileImage(image),
|
||||
backgroundImage: FileImage(image!),
|
||||
)
|
||||
: const CircleAvatar(
|
||||
radius: 100.0,
|
||||
@ -105,7 +105,7 @@ class _SetupProfileViewState extends State<SetupProfileView> {
|
||||
textInputType: TextInputType.name,
|
||||
hintText: 'e.g John',
|
||||
validatorFtn: (value) {
|
||||
if (value.isEmpty) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Display name cannot be empty';
|
||||
}
|
||||
return null;
|
||||
@ -136,7 +136,7 @@ class _SetupProfileViewState extends State<SetupProfileView> {
|
||||
child: FloatingActionButton(
|
||||
heroTag: 'setup',
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState.validate()) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
FocusScope.of(context).unfocus();
|
||||
|
||||
await _createProfile();
|
||||
|
@ -5,7 +5,7 @@ import 'package:simplex_chat/app_routes.dart';
|
||||
import 'package:simplex_chat/constants.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({Key key}) : super(key: key);
|
||||
const SplashScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SplashScreenState createState() => _SplashScreenState();
|
||||
|
@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class CustomButton extends StatelessWidget {
|
||||
const CustomButton(
|
||||
{@required this.width,
|
||||
@required this.height,
|
||||
@required this.onPressed,
|
||||
@required this.color,
|
||||
@required this.child,
|
||||
Key key})
|
||||
{required this.width,
|
||||
required this.height,
|
||||
required this.onPressed,
|
||||
required this.color,
|
||||
required this.child,
|
||||
Key? key})
|
||||
: super(key: key);
|
||||
final double width;
|
||||
final double height;
|
||||
|
@ -3,40 +3,17 @@ import 'package:flutter/material.dart';
|
||||
class CustomTextField extends StatefulWidget {
|
||||
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 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 String? Function(String?)? validatorFtn;
|
||||
|
||||
const CustomTextField({
|
||||
Key key,
|
||||
@required this.textEditingController,
|
||||
@required this.textInputType,
|
||||
this.trailing,
|
||||
this.trailingCallBack,
|
||||
this.node,
|
||||
@required this.hintText,
|
||||
this.icon,
|
||||
this.iconColor,
|
||||
this.passIconColor,
|
||||
this.isPassword = false,
|
||||
this.onChangeFtn,
|
||||
this.onEditComplete,
|
||||
Key? key,
|
||||
required this.textEditingController,
|
||||
required this.textInputType,
|
||||
required this.hintText,
|
||||
this.validatorFtn,
|
||||
this.onFieldSubmit,
|
||||
this.errorText,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -64,10 +41,7 @@ class _CustomTextFieldState extends State<CustomTextField> {
|
||||
controller: widget.textEditingController,
|
||||
textInputAction: TextInputAction.done,
|
||||
keyboardType: widget.textInputType,
|
||||
onChanged: widget.onChangeFtn,
|
||||
onEditingComplete: widget.onEditComplete,
|
||||
decoration: InputDecoration(
|
||||
errorText: widget.errorText,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 15.0),
|
||||
hintText: widget.hintText,
|
||||
hintStyle: Theme.of(context).textTheme.caption,
|
||||
@ -86,7 +60,6 @@ class _CustomTextFieldState extends State<CustomTextField> {
|
||||
),
|
||||
),
|
||||
validator: widget.validatorFtn,
|
||||
onFieldSubmitted: widget.onFieldSubmit,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ import 'package:simplex_chat/constants.dart';
|
||||
|
||||
class MessageBubble extends StatefulWidget {
|
||||
const MessageBubble({
|
||||
Key key,
|
||||
this.sender,
|
||||
this.text,
|
||||
this.isUser,
|
||||
Key? key,
|
||||
required this.sender,
|
||||
required this.text,
|
||||
required this.isUser,
|
||||
}) : super(key: key);
|
||||
final String sender;
|
||||
final String text;
|
||||
|
@ -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.10.0 <3.0.0"
|
||||
sdk: ">=2.12.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
|
||||
|
Loading…
Reference in New Issue
Block a user