import 'package:Envelope/database/repositories/friends_repository.dart'; import 'package:Envelope/services/friends_service.dart'; import 'package:flutter/material.dart'; import '/components/custom_title_bar.dart'; import '/components/qr_reader.dart'; import '/components/custom_expandable_fab.dart'; import '/database/models/friends.dart'; import '/views/main/friend/list_item.dart'; import '/views/main/friend/add_search.dart'; import '/views/main/friend/request_list_item.dart'; class FriendList extends StatefulWidget { final List friends; final Function callback; const FriendList({ Key? key, required this.friends, required this.callback, }) : super(key: key); @override State createState() => _FriendListState(); } class _FriendListState extends State { final GlobalKey _refreshIndicatorKey = GlobalKey(); late ScrollController _scrollController; List friends = []; List friendsDuplicate = []; @override Widget build(BuildContext context) { return Scaffold( appBar: const CustomTitleBar( title: Text( 'Friends', style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold ) ), showBack: false, backgroundColor: Colors.transparent, ), body: Padding( padding: const EdgeInsets.only(top: 16,left: 16,right: 16, bottom: 65), child: Stack( children: [ Padding( padding: const EdgeInsets.only(top: 50), child: RefreshIndicator( key: _refreshIndicatorKey, onRefresh: _refresh, child: list(), ) ), TextField( decoration: const InputDecoration( hintText: 'Search...', prefixIcon: Icon( Icons.search, size: 20 ), ), onChanged: (value) => filterSearchResults(value.toLowerCase()) ), ], ), ), floatingActionButton: Padding( padding: const EdgeInsets.only(right: 10, bottom: 60), child: ExpandableFab( icon: Icon( Icons.add, size: 30, color: Theme.of(context).colorScheme.onPrimary, ), distance: 90.0, children: [ ActionButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const QrReader()) );//.then(onGoBack); // TODO }, icon: const Icon(Icons.qr_code_2, size: 25), ), ActionButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const FriendAddSearch()) );//.then(onGoBack); // TODO }, icon: const Icon(Icons.search, size: 25), ), ], ) ) ); } void filterSearchResults(String query) { List dummyFriendsList = []; dummyFriendsList.addAll(friends); if (query.isNotEmpty) { List dummyFriendData = []; for (Friend item in dummyFriendsList) { if(item.username.toLowerCase().contains(query)) { dummyFriendData.add(item); } } setState(() { friends.clear(); friends.addAll(dummyFriendData); }); return; } setState(() { friends.clear(); friends.addAll(widget.friends); }); } @override void initState() { _scrollController = ScrollController(); _scrollController.addListener(_scrollListener); super.initState(); friends.addAll(widget.friends); } Future initFriends() async { friends = await FriendsRepository.getFriends(); setState(() {}); widget.callback(); } Widget _heading(String heading) { return Padding( padding: const EdgeInsets.only(top: 5, bottom: 10), child: Align( alignment: Alignment.centerLeft, child: Text( heading, style: TextStyle( fontSize: 16, color: Theme.of(context).hintColor, ), ), ) ); } Widget list() { if (friends.isEmpty) { return const Center( child: Text('No Friends'), ); } return ListView.separated( controller: _scrollController, itemCount: friends.length, shrinkWrap: false, physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.only(top: 10), separatorBuilder: (context, i) { if (friends[i].acceptedAt == null) { return FriendRequestListItem( friend: friends[i], callback: initFriends, ); } return FriendListItem( friend: friends[i], ); }, itemBuilder: (context, i) { if (i == 0 && friends[i].acceptedAt == null) { return _heading('Friend Requests'); } if ((i == 0 || friends[i - 1].acceptedAt == null) && friends[i].acceptedAt != null) { return _heading('Friends'); } return const SizedBox.shrink(); }, ); } Future _refresh() async { DateTime? acceptedAt = await FriendsRepository.getLatestAcceptedAt(); if (acceptedAt == null) { return; } FriendsService.updateFriends(acceptedAt: acceptedAt); friends = await FriendsRepository.getFriends(); setState(() {}); } Future _scrollListener() async { if (!(_scrollController.offset >= _scrollController.position.maxScrollExtent)) { return; } int page = 0; if (friends.length > 19) { page = friends.length ~/ 20; } await FriendsService.updateFriends(page: page); friends = await FriendsRepository.getFriends(); setState(() {}); } }