From 09fa0a021606cef41ceb67495bf7f71961c3e847 Mon Sep 17 00:00:00 2001 From: Florian Griffon Date: Sun, 15 Dec 2024 18:42:23 +0000 Subject: [PATCH] favorite-page (#12) Feat: favorite page Reviewed-on: https://git.gmoker.com/icing/G-EIP-700-TLS-7-1-eip-stephane.corbiere/pulls/12 Co-authored-by: Florian Griffon Co-committed-by: Florian Griffon --- .../lib/features/composition/composition.dart | 59 +++++++------------ .../lib/features/contacts/contact_page.dart | 6 +- .../lib/features/contacts/contact_state.dart | 46 ++++++++++----- .../widgets/alphabet_scroll_page.dart | 15 +++-- .../contacts/widgets/contact_modal.dart | 1 - .../features/favorites/favorites_page.dart | 31 ++++++---- dialer/lib/features/home/home_page.dart | 2 +- 7 files changed, 86 insertions(+), 74 deletions(-) diff --git a/dialer/lib/features/composition/composition.dart b/dialer/lib/features/composition/composition.dart index b224f05..783fcf9 100644 --- a/dialer/lib/features/composition/composition.dart +++ b/dialer/lib/features/composition/composition.dart @@ -22,9 +22,11 @@ class _CompositionPageState extends State { } Future _fetchContacts() async { - _allContacts = await _contactService.fetchContacts(); - _filteredContacts = _allContacts; - setState(() {}); + if (await FlutterContacts.requestPermission()) { + _allContacts = await _contactService.fetchContacts(); + _filteredContacts = _allContacts; + setState(() {}); + } } void _filterContacts() { @@ -79,9 +81,9 @@ class _CompositionPageState extends State { // Top half: Display contacts matching dialed number Expanded( flex: 2, - child: Container( - padding: const EdgeInsets.only( - top: 42.0, left: 16.0, right: 16.0, bottom: 16.0), + child: + Container( + padding: const EdgeInsets.only(top: 42.0, left: 16.0, right: 16.0, bottom: 16.0), color: Colors.black, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -93,14 +95,12 @@ class _CompositionPageState extends State { return ListTile( title: Text( contact.displayName, - style: - const TextStyle(color: Colors.white), + style: const TextStyle(color: Colors.white), ), subtitle: contact.phones.isNotEmpty ? Text( contact.phones.first.number, - style: const TextStyle( - color: Colors.grey), + style: const TextStyle(color: Colors.grey), ) : null, trailing: Row( @@ -108,22 +108,16 @@ class _CompositionPageState extends State { children: [ // Call button IconButton( - icon: Icon(Icons.phone, - color: Colors.green[300], - size: 20), + icon: Icon(Icons.phone, color: Colors.green[300], size: 20), onPressed: () { - print( - 'Calling ${contact.displayName}'); + print('Calling ${contact.displayName}'); }, ), // Text button IconButton( - icon: Icon(Icons.message, - color: Colors.blue[300], - size: 20), + icon: Icon(Icons.message, color: Colors.blue[300], size: 20), onPressed: () { - print( - 'Texting ${contact.displayName}'); + print('Texting ${contact.displayName}'); }, ), ], @@ -133,12 +127,7 @@ class _CompositionPageState extends State { }, ); }).toList() - : [ - Center( - child: Text('No contacts found', - style: - TextStyle(color: Colors.white))) - ], + : [Center(child: Text('No contacts found', style: TextStyle(color: Colors.white)))], ), ), ], @@ -163,16 +152,14 @@ class _CompositionPageState extends State { alignment: Alignment.center, child: Text( dialedNumber, - style: const TextStyle( - fontSize: 24, color: Colors.white), + style: const TextStyle(fontSize: 24, color: Colors.white), overflow: TextOverflow.ellipsis, ), ), ), IconButton( onPressed: _onClearPress, - icon: const Icon(Icons.backspace, - color: Colors.white), + icon: const Icon(Icons.backspace, color: Colors.white), ), ], ), @@ -185,8 +172,7 @@ class _CompositionPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('1'), _buildDialButton('2'), @@ -194,8 +180,7 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('4'), _buildDialButton('5'), @@ -203,8 +188,7 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('7'), _buildDialButton('8'), @@ -212,8 +196,7 @@ class _CompositionPageState extends State { ], ), Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildDialButton('*'), _buildDialButton('0'), diff --git a/dialer/lib/features/contacts/contact_page.dart b/dialer/lib/features/contacts/contact_page.dart index 93acc45..9f09490 100644 --- a/dialer/lib/features/contacts/contact_page.dart +++ b/dialer/lib/features/contacts/contact_page.dart @@ -17,8 +17,10 @@ class _ContactPageState extends State { return Scaffold( body: contactState.loading ? const LoadingIndicatorWidget() - // : ContactListWidget(contacts: contactState.contacts), - : AlphabetScrollPage(scrollOffset: contactState.scrollOffset), + : AlphabetScrollPage( + scrollOffset: contactState.scrollOffset, + contacts: contactState.contacts, // Use all contacts here + ), ); } } diff --git a/dialer/lib/features/contacts/contact_state.dart b/dialer/lib/features/contacts/contact_state.dart index 75e70d8..82e21c2 100644 --- a/dialer/lib/features/contacts/contact_state.dart +++ b/dialer/lib/features/contacts/contact_state.dart @@ -19,12 +19,15 @@ class ContactState extends StatefulWidget { class _ContactStateState extends State { final ContactService _contactService = ContactService(); - List _contacts = []; + List _allContacts = []; + List _favoriteContacts = []; bool _loading = true; double _scrollOffset = 0.0; Contact? _selfContact = Contact(); - List get contacts => _contacts; + // Getters for all contacts and favorites + List get contacts => _allContacts; + List get favoriteContacts => _favoriteContacts; bool get loading => _loading; double get scrollOffset => _scrollOffset; Contact? get selfContact => _selfContact; @@ -32,9 +35,7 @@ class _ContactStateState extends State { @override void initState() { super.initState(); - fetchContacts(); - - // Add listener for contact changes + fetchContacts(); // Fetch all contacts by default FlutterContacts.addListener(_onContactChange); } @@ -42,20 +43,33 @@ class _ContactStateState extends State { @override void dispose() { - // Remove listener FlutterContacts.removeListener(_onContactChange); super.dispose(); } - Future fetchContacts({bool onlyStarred = false}) async { - List contacts = onlyStarred - ? await _contactService.fetchFavoriteContacts() - : await _contactService.fetchContacts(); + // Fetch all contacts + Future fetchContacts() async { + setState(() => _loading = true); + try { + List contacts = await _contactService.fetchContacts(); + _processContacts(contacts); + } finally { + setState(() => _loading = false); + } + } - debugPrint( - "Fetched ${contacts.length} ${onlyStarred ? 'favorite' : ''} contacts"); + // Fetch only favorite contacts + Future fetchFavoriteContacts() async { + setState(() => _loading = true); + try { + List contacts = await _contactService.fetchFavoriteContacts(); + setState(() => _favoriteContacts = contacts); + } finally { + setState(() => _loading = false); + } + } - // Find selfContact before filtering + void _processContacts(List contacts) { _selfContact = contacts.firstWhere( (contact) => contact.displayName.toLowerCase() == "user", orElse: () => Contact(), @@ -70,8 +84,9 @@ class _ContactStateState extends State { contacts.sort((a, b) => a.displayName.compareTo(b.displayName)); setState(() { - _contacts = contacts; - _loading = false; + _allContacts = contacts; + _favoriteContacts = + contacts.where((contact) => contact.isStarred).toList(); _selfContact = _selfContact; }); } @@ -96,6 +111,7 @@ class _ContactStateState extends State { } } + class _InheritedContactState extends InheritedWidget { final _ContactStateState data; diff --git a/dialer/lib/features/contacts/widgets/alphabet_scroll_page.dart b/dialer/lib/features/contacts/widgets/alphabet_scroll_page.dart index 7453181..c144084 100644 --- a/dialer/lib/features/contacts/widgets/alphabet_scroll_page.dart +++ b/dialer/lib/features/contacts/widgets/alphabet_scroll_page.dart @@ -9,8 +9,13 @@ import 'share_own_qr.dart'; class AlphabetScrollPage extends StatefulWidget { final double scrollOffset; + final List contacts; - const AlphabetScrollPage({super.key, required this.scrollOffset}); + const AlphabetScrollPage({ + super.key, + required this.scrollOffset, + required this.contacts, + }); @override _AlphabetScrollPageState createState() => _AlphabetScrollPageState(); @@ -22,8 +27,7 @@ class _AlphabetScrollPageState extends State { @override void initState() { super.initState(); - _scrollController = - ScrollController(initialScrollOffset: widget.scrollOffset); + _scrollController = ScrollController(initialScrollOffset: widget.scrollOffset); _scrollController.addListener(_onScroll); } @@ -71,9 +75,8 @@ class _AlphabetScrollPageState extends State { @override Widget build(BuildContext context) { - final contactState = ContactState.of(context); - final contacts = contactState.contacts; - final selfContact = contactState.selfContact; + final contacts = widget.contacts; + final selfContact = ContactState.of(context).selfContact; Map> alphabetizedContacts = {}; for (var contact in contacts) { diff --git a/dialer/lib/features/contacts/widgets/contact_modal.dart b/dialer/lib/features/contacts/widgets/contact_modal.dart index 6514500..2d7d395 100644 --- a/dialer/lib/features/contacts/widgets/contact_modal.dart +++ b/dialer/lib/features/contacts/widgets/contact_modal.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:dialer/widgets/username_color_generator.dart'; -import 'package:flutter/material.dart'; class ContactModal extends StatelessWidget { final Contact contact; diff --git a/dialer/lib/features/favorites/favorites_page.dart b/dialer/lib/features/favorites/favorites_page.dart index 48227c5..47f74ec 100644 --- a/dialer/lib/features/favorites/favorites_page.dart +++ b/dialer/lib/features/favorites/favorites_page.dart @@ -1,23 +1,32 @@ +import 'package:dialer/features/contacts/contact_state.dart'; +import 'package:dialer/features/contacts/widgets/alphabet_scroll_page.dart'; import 'package:flutter/material.dart'; +import 'package:dialer/widgets/loading_indicator.dart'; -class FavoritePage extends StatefulWidget { - const FavoritePage({super.key}); +class FavoritesPage extends StatefulWidget { + const FavoritesPage({super.key}); @override - _FavoritePageState createState() => _FavoritePageState(); + _FavoritesPageState createState() => _FavoritesPageState(); } -class _FavoritePageState extends State { +class _FavoritesPageState extends State { + @override + void initState() { + super.initState(); + } + @override Widget build(BuildContext context) { + final contactState = ContactState.of(context); return Scaffold( - backgroundColor: Colors.black, - body: Center( // Center the text within the body - child: Text( - "Hello", - style: TextStyle(color: Colors.white), // Change text color for visibility - ), - ), + body: contactState.loading + ? const LoadingIndicatorWidget() + : AlphabetScrollPage( + scrollOffset: contactState.scrollOffset, + contacts: + contactState.favoriteContacts, // Use only favorites here + ), ); } } diff --git a/dialer/lib/features/home/home_page.dart b/dialer/lib/features/home/home_page.dart index 5552388..99328cb 100644 --- a/dialer/lib/features/home/home_page.dart +++ b/dialer/lib/features/home/home_page.dart @@ -140,7 +140,7 @@ class _MyHomePageState extends State TabBarView( controller: _tabController, children: const [ - FavoritePage(), + FavoritesPage(), HistoryPage(), ContactPage(), SettingsPage(), // Add your SettingsPage here