Created
December 23, 2022 00:46
-
-
Save zerebral/d934622f6c0ad87f2ba2e35ceea21144 to your computer and use it in GitHub Desktop.
Infinite Scroll Widget + Algolia + FlutterFlow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Automatic FlutterFlow imports | |
import '../../backend/backend.dart'; | |
import '../../flutter_flow/flutter_flow_theme.dart'; | |
import '../../flutter_flow/flutter_flow_util.dart'; | |
import '../widgets/index.dart'; // Imports other custom widgets | |
import '../actions/index.dart'; // Imports custom actions | |
import '../../flutter_flow/custom_functions.dart'; // Imports custom functions | |
import 'package:flutter/material.dart'; | |
// Begin custom widget code | |
// DO NOT REMOVE OR MODIFY THE CODE ABOVE! | |
//import 'index.dart'; // Imports other custom widgets | |
import 'package:provider/provider.dart'; | |
import 'dart:convert'; | |
import 'package:around/components/user_post_card_widget.dart'; | |
import '../../flutter_flow/custom_functions.dart' as functions; | |
import 'package:http/http.dart' as http; | |
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | |
class CustomPostList extends StatefulWidget { | |
const CustomPostList( | |
{Key? key, | |
this.width = double.infinity, | |
this.height = double.infinity, | |
this.strokeWidth = 2}) | |
: super(key: key); | |
final double width; | |
final double height; | |
final double strokeWidth; | |
// final String location; | |
// final String searchQuery; | |
// final int radius; | |
@override | |
_CustomPostListState createState() => _CustomPostListState(); | |
} | |
class _CustomPostListState extends State<CustomPostList> { | |
ValueNotifier<String> _searchQuery = | |
ValueNotifier<String>(FFAppState().postsearch); | |
ValueNotifier<String> _location = | |
ValueNotifier<String>(FFAppState().searchLocation); | |
ValueNotifier<int> _radius = ValueNotifier<int>(FFAppState().searchRadius); | |
static const _pageSize = 10; | |
final PagingController<int, Post> _pagingController = | |
PagingController(firstPageKey: 0); | |
@override | |
void initState() { | |
_pagingController.addPageRequestListener((pageKey) { | |
_fetchPage(pageKey); | |
}); | |
_searchQuery.addListener(() => {_pagingController.refresh()}); | |
_location.addListener(() => {_pagingController.refresh()}); | |
_radius.addListener(() => {_pagingController.refresh()}); | |
super.initState(); | |
} | |
Future<List<Post>> fetch(page) async { | |
List<Post> posts = []; | |
var url = "https://<your-algolia-app-id>-dsn.algolia.net/1/indexes/userposts/query"; | |
final response = await http.post(Uri.parse(url), | |
body: jsonEncode({ | |
"params": | |
"hitsPerPage=${_pageSize}&page=${page}&query=${FFAppState().postsearch}&aroundLatLng=${FFAppState().searchLocation}&aroundRadius=25000" | |
}), | |
headers: { | |
'X-Algolia-API-Key': '<your-algolia-api-key>', | |
'X-Algolia-Application-Id': '<your-algolia-app-id>' | |
}); | |
if (response.statusCode == 200) { | |
Map<String, dynamic> jsonMap = json.decode(response.body); | |
(jsonMap['hits'] as List).forEach((x) => {posts.add(Post.fromJson(x))}); | |
return posts; | |
} else { | |
//throw Exception('Failed to load posts'); | |
return posts; | |
} | |
} | |
Future<void> _fetchPage(int pageKey) async { | |
try { | |
double page = pageKey / _pageSize; | |
List<Post> newItems = await fetch(page); | |
print(newItems.length); | |
final isLastPage = newItems.length < _pageSize; | |
if (isLastPage) { | |
_pagingController.appendLastPage(newItems); | |
} else { | |
final nextPageKey = pageKey + newItems.length; | |
_pagingController.appendPage(newItems, nextPageKey); | |
} | |
} catch (error) { | |
_pagingController.error = error; | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
context.watch<FFAppState>(); | |
_searchQuery.value = FFAppState().postsearch; | |
_location.value = FFAppState().searchLocation; | |
_radius.value = FFAppState().searchRadius; | |
return PagedListView<int, Post>( | |
pagingController: _pagingController, | |
builderDelegate: PagedChildBuilderDelegate<Post>( | |
itemBuilder: (context, item, index) => UserPostCardWidget( | |
postRef: functions.getUserPostsDocRef(item.objectId)), | |
)); | |
} | |
@override | |
void dispose() { | |
_pagingController.dispose(); | |
super.dispose(); | |
} | |
} | |
class Post { | |
final String objectId; | |
const Post({required this.objectId}); | |
factory Post.fromJson(Map<String, dynamic> json) { | |
return Post(objectId: json['objectID']); | |
} | |
} |
Thanks for the advice!
Regarding the path in your import on line 16. Have you ever gotten this error?
"Target of URI doesn't exist: package:{name}/components/{component_name}.dart
It's weird that FF can't compile the component although if I download the code and run it locally from my own flutter installation on vscode it works just fine :/
You should reach out to FF support.. I ditched it, as like these there were many instances where I needed help and very little of it was available.. The FF support experience was average too throughout! Its much easier and faster to develop with VSC and few Flutter plugins there (along with FF used just to build the UI)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also you may want to wrap your row widget inside KeepAliveWidgetWrapper so that the list does not flicker, especially when you scroll up.