Skip to content

Instantly share code, notes, and snippets.

@zerebral
Created December 23, 2022 00:46
Show Gist options
  • Save zerebral/d934622f6c0ad87f2ba2e35ceea21144 to your computer and use it in GitHub Desktop.
Save zerebral/d934622f6c0ad87f2ba2e35ceea21144 to your computer and use it in GitHub Desktop.
Infinite Scroll Widget + Algolia + FlutterFlow
// 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']);
}
}
@zerebral
Copy link
Author

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