WIP: fixSearchBar #28

Closed
florian wants to merge 6 commits from fixSearchBar into dev
Showing only changes of commit d925717fc2 - Show all commits

View File

@ -6,6 +6,7 @@ import 'package:dialer/features/composition/composition.dart';
import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:dialer/features/settings/settings.dart'; import 'package:dialer/features/settings/settings.dart';
import '../../widgets/contact_service.dart'; import '../../widgets/contact_service.dart';
import '../contacts/widgets/contact_modal.dart'; // Import the ContactModal widget
class _MyHomePageState extends State<MyHomePage> class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
@ -13,6 +14,7 @@ class _MyHomePageState extends State<MyHomePage>
List<Contact> _allContacts = []; List<Contact> _allContacts = [];
List<Contact> _contactSuggestions = []; List<Contact> _contactSuggestions = [];
final ContactService _contactService = ContactService(); final ContactService _contactService = ContactService();
final SearchController _searchController = SearchController();
@override @override
void initState() { void initState() {
@ -30,7 +32,7 @@ class _MyHomePageState extends State<MyHomePage>
void _onSearchChanged(String query) { void _onSearchChanged(String query) {
setState(() { setState(() {
if (query.isEmpty) { if (query.isEmpty) {
_contactSuggestions = List.from(_allContacts); _contactSuggestions = List.from(_allContacts); // Reset suggestions
} else { } else {
_contactSuggestions = _allContacts.where((contact) { _contactSuggestions = _allContacts.where((contact) {
return contact.displayName return contact.displayName
@ -41,10 +43,14 @@ class _MyHomePageState extends State<MyHomePage>
}); });
} }
void _clearSearch() {
_searchController.text = '';
_onSearchChanged('');
}
@override @override
void dispose() { void dispose() {
_tabController.removeListener(_handleTabIndex); _searchController.dispose();
_tabController.dispose();
super.dispose(); super.dispose();
} }
@ -52,6 +58,35 @@ class _MyHomePageState extends State<MyHomePage>
setState(() {}); setState(() {});
} }
// New method to handle toggling favorites
void _toggleFavorite(Contact contact) async {
try {
if (await FlutterContacts.requestPermission()) {
Contact? fullContact = await FlutterContacts.getContact(contact.id,
withProperties: true,
withAccounts: true,
withPhoto: true,
withThumbnail: true);
if (fullContact != null) {
fullContact.isStarred = !fullContact.isStarred;
await FlutterContacts.updateContact(fullContact);
setState(() {
// Updating the contact list after toggling the favorite
_fetchContacts();
});
}
} else {
print("Could not fetch contact details");
}
} catch (e) {
print("Error updating favorite status: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to update contact favorite status')),
);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -72,12 +107,11 @@ class _MyHomePageState extends State<MyHomePage>
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromARGB(255, 30, 30, 30), color: const Color.fromARGB(255, 30, 30, 30),
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
border: border: Border.all(color: Colors.grey.shade800, width: 1),
Border.all(color: Colors.grey.shade800, width: 1),
), ),
child: SearchAnchor( child: SearchAnchor(
builder: (BuildContext context, builder:
SearchController controller) { (BuildContext context, SearchController controller) {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
controller.openView(); // Open the search view controller.openView(); // Open the search view
@ -92,38 +126,96 @@ class _MyHomePageState extends State<MyHomePage>
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 12.0, horizontal: 16.0), vertical: 12.0, horizontal: 16.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, children: [
children: const [ const Icon(Icons.search,
Icon(Icons.search,
color: Colors.grey, size: 24.0), color: Colors.grey, size: 24.0),
SizedBox(width: 8.0), const SizedBox(width: 8.0),
Text( Text(
'Search contacts', _searchController.text.isEmpty
style: TextStyle( ? 'Search contacts'
: _searchController.text,
style: const TextStyle(
color: Colors.grey, fontSize: 16.0), color: Colors.grey, fontSize: 16.0),
), ),
const Spacer(),
if (_searchController.text.isNotEmpty)
GestureDetector(
onTap: _clearSearch,
child: const Icon(
Icons.clear,
color: Colors.grey,
size: 24.0,
),
),
], ],
), ),
), ),
); );
}, },
viewOnChanged: (query) { viewOnChanged: (query) {
_onSearchChanged(query); _onSearchChanged(query); // Update immediately
}, },
suggestionsBuilder: (BuildContext context, suggestionsBuilder:
SearchController controller) { (BuildContext context, SearchController controller) {
return _contactSuggestions.map((contact) { return _contactSuggestions.map((contact) {
return ListTile( return ListTile(
key: ValueKey(contact.id), key: ValueKey(contact.id),
title: Text(contact.displayName, title: Text(contact.displayName,
style: const TextStyle(color: Colors.white)), style: const TextStyle(color: Colors.white)),
onTap: () { onTap: () {
controller.closeView(contact.displayName); // Clear the search text input
// controller.text = '';
// Close the search view
// controller.closeView(contact.displayName);
// Show the ContactModal when a contact is tapped
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return ContactModal(
contact: contact,
onEdit: () async {
if (await FlutterContacts
.requestPermission()) {
final updatedContact =
await FlutterContacts
.openExternalEdit(contact.id);
if (updatedContact != null) {
_fetchContacts();
Navigator.of(context).pop();
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: Text(
'${contact.displayName} updated successfully!'),
),
);
} else {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: Text(
'Edit canceled or failed.'),
),
);
}
}
},
onToggleFavorite: () =>
_toggleFavorite(contact),
isFavorite: contact.isStarred,
);
},
);
}, },
); );
}).toList(); }).toList();
}, },
)), ),
),
), ),
PopupMenuButton<String>( PopupMenuButton<String>(
icon: const Icon(Icons.more_vert, color: Colors.white), icon: const Icon(Icons.more_vert, color: Colors.white),
@ -146,7 +238,6 @@ class _MyHomePageState extends State<MyHomePage>
], ],
), ),
), ),
// Main content with TabBarView
Expanded( Expanded(
child: Stack( child: Stack(
children: [ children: [