Florian Griffon
fca1eea1c9
All checks were successful
/ mirror (push) Successful in 4s
Feat: contact-modal et refonte du contact-state pour la page de favori et possibilité de update les contacts. Aussi mis la composition page avec le service de contact, on évite de fetch dans la page directement Reviewed-on: #10 Co-authored-by: Florian Griffon <florian.griffon@epitech.eu> Co-committed-by: Florian Griffon <florian.griffon@epitech.eu>
211 lines
7.0 KiB
Dart
211 lines
7.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:dialer/features/contacts/contact_page.dart';
|
|
import 'package:dialer/features/favorites/favorites_page.dart';
|
|
import 'package:dialer/features/history/history_page.dart';
|
|
import 'package:dialer/features/composition/composition.dart';
|
|
import 'package:flutter_contacts/flutter_contacts.dart';
|
|
import 'package:dialer/features/settings/settings.dart';
|
|
import '../../widgets/contact_service.dart';
|
|
|
|
class _MyHomePageState extends State<MyHomePage>
|
|
with SingleTickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
List<Contact> _allContacts = [];
|
|
List<Contact> _contactSuggestions = [];
|
|
final ContactService _contactService = ContactService();
|
|
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_tabController = TabController(length: 4, vsync: this, initialIndex: 1);
|
|
_tabController.addListener(_handleTabIndex);
|
|
_fetchContacts();
|
|
}
|
|
|
|
void _fetchContacts() async {
|
|
_allContacts = await _contactService.fetchContacts();
|
|
setState(() {});
|
|
}
|
|
|
|
void _onSearchChanged(String query) {
|
|
print("Search query: $query");
|
|
|
|
setState(() {
|
|
if (query.isEmpty) {
|
|
_contactSuggestions = List.from(_allContacts);
|
|
} else {
|
|
_contactSuggestions = _allContacts.where((contact) {
|
|
return contact.displayName
|
|
.toLowerCase()
|
|
.contains(query.toLowerCase());
|
|
}).toList();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController.removeListener(_handleTabIndex);
|
|
_tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _handleTabIndex() {
|
|
setState(() {});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.black,
|
|
body: Column(
|
|
children: [
|
|
// Persistent Search Bar
|
|
Padding(
|
|
padding: const EdgeInsets.only(
|
|
top: 24.0,
|
|
bottom: 10.0,
|
|
left: 16.0,
|
|
right: 16.0,
|
|
),
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: const Color.fromARGB(255, 30, 30, 30),
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
border: Border(
|
|
top: BorderSide(color: Colors.grey.shade800, width: 1),
|
|
left: BorderSide(color: Colors.grey.shade800, width: 1),
|
|
right: BorderSide(color: Colors.grey.shade800, width: 1),
|
|
bottom: BorderSide(color: Colors.grey.shade800, width: 2),
|
|
),
|
|
),
|
|
child: SearchAnchor(
|
|
builder: (BuildContext context, SearchController controller) {
|
|
return SearchBar(
|
|
controller: controller,
|
|
padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
|
|
const EdgeInsets.only(
|
|
top: 6.0,
|
|
bottom: 6.0,
|
|
left: 16.0,
|
|
right: 16.0,
|
|
),
|
|
),
|
|
onTap: () {
|
|
controller.openView();
|
|
_onSearchChanged('');
|
|
},
|
|
backgroundColor: MaterialStateProperty.all(
|
|
const Color.fromARGB(255, 30, 30, 30)),
|
|
hintText: 'Search contacts',
|
|
hintStyle: MaterialStateProperty.all(
|
|
const TextStyle(color: Colors.grey, fontSize: 16.0),
|
|
),
|
|
leading: const Icon(
|
|
Icons.search,
|
|
color: Colors.grey,
|
|
size: 24.0,
|
|
),
|
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
|
RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
viewOnChanged: (query) {
|
|
_onSearchChanged(query);
|
|
},
|
|
suggestionsBuilder:
|
|
(BuildContext context, SearchController controller) {
|
|
return _contactSuggestions.map((contact) {
|
|
return ListTile(
|
|
key: ValueKey(contact.id),
|
|
title: Text(contact.displayName,
|
|
style: const TextStyle(color: Colors.white)),
|
|
onTap: () {
|
|
controller.closeView(contact.displayName);
|
|
},
|
|
);
|
|
}).toList();
|
|
},
|
|
),
|
|
),
|
|
),
|
|
// Main content with TabBarView
|
|
Expanded(
|
|
child: Stack(
|
|
children: [
|
|
TabBarView(
|
|
controller: _tabController,
|
|
children: const [
|
|
FavoritePage(),
|
|
HistoryPage(),
|
|
ContactPage(),
|
|
SettingsPage(), // Add your SettingsPage here
|
|
],
|
|
),
|
|
Positioned(
|
|
right: 20,
|
|
bottom: 20,
|
|
child: FloatingActionButton(
|
|
onPressed: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => const CompositionPage(),
|
|
),
|
|
);
|
|
},
|
|
backgroundColor: Colors.blue,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(45),
|
|
),
|
|
child: const Icon(Icons.dialpad, color: Colors.white),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
bottomNavigationBar: Container(
|
|
color: Colors.black,
|
|
child: TabBar(
|
|
controller: _tabController,
|
|
tabs: [
|
|
Tab(
|
|
icon: Icon(_tabController.index == 0
|
|
? Icons.star
|
|
: Icons.star_border)),
|
|
Tab(
|
|
icon: Icon(_tabController.index == 1
|
|
? Icons.access_time_filled
|
|
: Icons.access_time_outlined)),
|
|
Tab(
|
|
icon: Icon(_tabController.index == 2
|
|
? Icons.contacts
|
|
: Icons.contacts_outlined)),
|
|
Tab(
|
|
icon: Icon(_tabController.index == 3 // Corrected index
|
|
? Icons.settings
|
|
: Icons.settings_outlined)),
|
|
],
|
|
labelColor: Colors.white,
|
|
unselectedLabelColor: const Color.fromARGB(255, 158, 158, 158),
|
|
indicatorSize: TabBarIndicatorSize.label,
|
|
indicatorColor: Colors.white,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
const MyHomePage({super.key});
|
|
|
|
@override
|
|
_MyHomePageState createState() => _MyHomePageState();
|
|
}
|