Skip to content

Instantly share code, notes, and snippets.

@OberdanBrito
Created December 27, 2022 10:46
Show Gist options
  • Save OberdanBrito/a66098cb935052877adf77cdbc8389b5 to your computer and use it in GitHub Desktop.
Save OberdanBrito/a66098cb935052877adf77cdbc8389b5 to your computer and use it in GitHub Desktop.
Lista de contatos
// ignore_for_file: depend_on_referenced_packages
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:gestor_commons/data/data.dart';
import 'package:gestor_commons/theme.dart';
import 'package:gestor_commons/images.dart';
import 'package:intl/intl.dart';
import 'package:quicasa_contacts/data/schedule.dart';
import 'package:quicasa_contacts/types.dart';
import 'contact_view.dart';
import 'groups_list.dart';
import 'data/contacts.dart';
import 'data/groups.dart';
import 'data/groups_itens.dart';
import 'data/profile_type.dart';
import 'sync.dart';
class MultipleData {
List<ApContact> contacts;
List<Groups> groups;
MultipleData({
required this.contacts,
required this.groups
});
}
class ContactsListPage extends StatefulWidget {
final Map<String, dynamic> client;
final AppTheme theme;
const ContactsListPage(
{super.key, required this.client, required this.theme});
@override
ContactsListState createState() => ContactsListState();
}
class ContactsListState extends State<ContactsListPage> {
final db = DataBaseHelper.db;
late AppWidgets global = AppWidgets(theme: widget.theme);
late final Widget _defaulttitle = global.titlePage(leftText: 'Meus ', centerText: 'Contatos');
late Widget _title = _defaulttitle;
late Widget _list = _awaitLoadStart();
late Icon _searchicon = const Icon(Icons.search);
late MultipleData multipleData;
TextEditingController searchController = TextEditingController();
void _setSearchResult(MultipleData multipleData) {
setState(() {
_list = _makeListContent(multipleData);
});
}
void _search(String query) {
List<ApContact> dummySearchList = <ApContact>[];
dummySearchList.addAll(multipleData.contacts);
if (query.isNotEmpty) {
List<ApContact> dummyListData = multipleData.contacts
.where((element) => element.displayname.toLowerCase().contains(query.toLowerCase()))
.toList();
MultipleData newmultiple = MultipleData(contacts: dummyListData, groups: multipleData.groups);
_setSearchResult(newmultiple);
return;
} else {
_setSearchResult(multipleData);
}
}
Widget _listMenu() {
return PopupMenuButton(itemBuilder: (context) {
return [
PopupMenuItem<String>(
value: 'contactgroups',
child: global.iconText('Convidar pessoas', const Icon(FontAwesomeIcons.peopleGroup), Colors.black54)
),
];
}, onSelected: (value) async {
if (value == 'contactgroups') {
List<Map<String, dynamic>> contactrows = await db.queryAllRows('contacts');
List<ApContact> contacts = [];
Future.forEach(contactrows, (contact) => {
contacts.add(ApContact.fromMap(contact))
});
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => ContactsGroupsPage(
onSetGroup: () {},
contacts: contacts,
client: widget.client,
theme: widget.theme,
)
)
);
}
});
}
Widget _searchBar() {
return ListTile(
title: TextField(
onChanged: (value) {
_search(value);
},
controller: searchController,
decoration: const InputDecoration(hintText: 'pesquisar...'),
),
);
}
Widget _toggleBar() {
return Padding(
padding: const EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {
setState(() {
if (_searchicon.icon == Icons.search) {
_searchicon = const Icon(Icons.cancel);
_title = _searchBar();
_list = _makeListContent(multipleData);
} else {
_searchicon = const Icon(Icons.search);
_title = _defaulttitle;
_list = _makeListContent(multipleData);
}
});
},
child: _searchicon,
));
}
Widget _showPhoto(photo) {
Widget contactphoto = Icon(FontAwesomeIcons.user, size: 24, color: widget.theme.grey);
if (photo != "") {
contactphoto = Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: MemoryImage(Images.dataFromBase64String(photo)),
fit: BoxFit.cover,
),
));
}
return CircleAvatar(
backgroundColor: Colors.grey[300],
child: Center(
child: contactphoto,
),
);
}
Widget _showName(String name, Color color) {
return Row(
children: <Widget>[
Expanded(
child: Text(name,
style: TextStyle(color: color),
softWrap: false,
maxLines: 1,
overflow: TextOverflow.ellipsis))
],
);
}
Widget _showType(contactType) {
ContactProfileType peopleType = Types.list.where((element) => element.id == contactType).first;
return global.iconText(peopleType.text, Icon(peopleType.icon), peopleType.color);
}
Widget _showAccess(String? date) {
String nextaccess = '';
if (date != null) {
nextaccess = DateFormat.yMd().format(DateTime.parse(date).toLocal());
}
return Text(nextaccess);
}
Widget _listContacts(List<ApContact> list) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
ApContact contact = list[index];
Color? background = Colors.white;
Color color = Colors.black54;
if (contact.blocked == 'true') {
background = Colors.red[50];
color = Colors.red;
}
return ListTile(
onTap: () => _onSelectItem(context, contact, index),
tileColor: background,
leading: _showPhoto(contact.photo),
title: _showName(contact.displayname, color),
subtitle: _showType(contact.peopletype),
trailing: _showAccess(contact.scheduleto),
);
},
childCount: list.length,
),
);
}
Widget _listGroups(List<Groups> list) {
return Container(
padding: const EdgeInsets.only(top: 80),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (context, index) {
Groups group = list[index];
return Container(
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width * 0.3,
),
child: Card(
color: Colors.white,
elevation: 0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {},
child: global.columnButtonIcon(
Icon(FontAwesomeIcons.users, color: widget.theme.grey), group.name)
)
]
),
),
);
}),
);
}
Widget _makeListContent(MultipleData multipleData) {
return Container(
color: Colors.white,
child: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
snap: false,
floating: true,
expandedHeight: multipleData.groups.isNotEmpty ? 150.0 : 0,
backgroundColor: Colors.white,
title: _title,
actions: <Widget>[_toggleBar(), _listMenu()],
leading: global.backButton(context),
flexibleSpace: FlexibleSpaceBar(
background: _listGroups(multipleData.groups),
),
),
_listContacts(multipleData.contacts)
],
),
);
}
Widget _makeListEmpty() {
return Center(
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Padding(
padding: const EdgeInsets.all(10),
child: Icon(FontAwesomeIcons.heart, size: 32, color: widget.theme.secundary),
),
const Text(
'Sua lista de contatos\nestá vazia!',
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 24),
textAlign: TextAlign.center,
),
const Padding(
padding: EdgeInsets.only(top: 20, left: 30, right: 30),
child: Text(
'Para o seu conforto, você pode sincronizar os contatos do seu celular aqui mesmo!',
style: TextStyle(fontSize: 18),
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.only(top: 20),
child: TextButton.icon(
onPressed: () {
setState(() {
_list = _prepareList(_getDeviceList());
});
},
icon: const Icon(Icons.sync),
label: const Text(
"Sincronizar meus contatos",
style: TextStyle(fontSize: 15),
)))
]),
);
}
Widget _awaitLoadStart() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Aguarde enquanto\nbuscamos os seus contatos',
textAlign: TextAlign.center,),
SizedBox(
width: 100,
height: 100,
child: Stack(
alignment: Alignment.center,
children: [
Icon(FontAwesomeIcons.heart, size: 32, color: widget.theme.secundary),
SizedBox(
height: 50,
width: 50,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(widget.theme.primary),
strokeWidth: 5,
),
)
],
),
)
],
),
);
}
Widget _prepareList(Future<MultipleData>? future) {
return FutureBuilder<MultipleData>(
future: future,
builder: (BuildContext context, AsyncSnapshot<MultipleData> snapshot) {
if (snapshot.hasData) {
return _makeListContent(snapshot.data!);
} else {
return _awaitLoadStart();
}
},
);
}
Future _onSelectItem(context, contact, index) async {
var schendule = await db.queryRow('schedule', 'contact', contact.id);
if (schendule.isNotEmpty) {
contact.schedule = Schedule.fromMap(schendule);
}
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => ContactPage(
contact: contact,
client: widget.client,
theme: widget.theme,
)
)
).then((val) => _checkLocalData());
}
Future<MultipleData> _getDeviceList() async {
await db.create('contacts', ApContact.model);
await db.create('schedule', Schedule.model);
await db.create('groups', Groups.model);
await db.create('groupsitens', GroupsItens.model);
List<ApContact> contacts = [];
List<Map<String, dynamic>> devicecontacts = await DeviceContacts.fetchContacts();
await Future.forEach(devicecontacts, (row) async {
await db.insert('contacts', row);
contacts.add(ApContact.fromMap(row));
});
return MultipleData(contacts: contacts, groups: []);
}
Future<MultipleData> _getContacts() async {
List<ApContact> contacts = [];
List<Groups> groups = [];
List<Map<String, dynamic>> contactrows = await db.queryAllRows('contacts');
Future.forEach(contactrows, (row) => {
contacts.add(ApContact.fromMap(row))
});
List<Map<String, dynamic>> grouprows = await db.queryAllRows('groups');
Future.forEach(grouprows, (rows) => {
groups.add(Groups.fromMap(rows))
});
return MultipleData(contacts: contacts, groups: groups);
}
Future _checkLocalData() async {
bool exists = await db.tableExist('contacts');
if (exists == false) {
setState(() {
_list = _makeListEmpty();
});
} else {
setState(() {
_list = _prepareList(_getContacts());
});
}
}
@override
void initState() {
super.initState();
_checkLocalData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _list
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment