vedartm / paginate_firestore

A flutter package to simplify pagination with firestore data 🗃
https://pub.dev/packages/paginate_firestore
MIT License
113 stars 138 forks source link

Adding option for PageView + Discussion about initial index #75

Closed jslattery26 closed 3 years ago

jslattery26 commented 3 years ago

Here is a class you can use that I set up to test the issue that I'm talking about. The initialPage in the initState simulates if someone was clicking the index of 15. Note the itemsPerPage is less at only 10.

class ProfileFeed extends StatefulWidget {
  @override
  _ProfileFeedState createState() => _ProfileFeedState();
}

class _ProfileFeedState extends State<ProfileFeed> {
  late PreloadPageController pageController;
  late DocumentSnapshot initialDocument;
  @override
  void initState() {
    //Here's where you can mess with the initial page to see the problem
    pageController = PreloadPageController(initialPage: 15);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return PaginateFirestore(
      itemsPerPage: 10,
      onLoaded: (PaginationLoaded) {},
      itemBuilderType: PaginateBuilderType.pageView,
      pageController: pageController,
      emptyDisplay: const Center(child: Text('No posts..')),
      onError: (dynamic error) => Center(
        child: Text('Some error occured'),
      ),
      bottomLoader: Center(
        // optional
        child: CircularProgressIndicator(),
      ),
      itemBuilder: (
        index,
        context,
        documentSnapshot,
      ) {
        return Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.width,
          child: Center(
            child: Text(
              index.toString(),
              style: TextStyle(fontSize: 50),
            ),
          ),
        );
      },
      // orderBy is compulsary to enable pagination
      query: FirebaseFirestore.instance
          .collection('posts')
          .orderBy('dateAdded', descending: true),
    );
  }
}
vedartm commented 3 years ago

Sorry for taking some time to merge this @jslattery26. There is one small thing. We don't need a custom scroll view if we do not have a header or footer.

This worked for me,

  Widget _buildPageView(PaginationLoaded loadedState) {
    var pageView = PreloadPageView.custom(
      reverse: widget.reverse,
      controller: widget.pageController,
      scrollDirection: widget.scrollDirection,
      physics: widget.physics,
      childrenDelegate: SliverChildBuilderDelegate(
        (context, index) {
          if (index >= loadedState.documentSnapshots.length) {
            _cubit!.fetchPaginatedList();
            return widget.bottomLoader;
          }
          return widget.itemBuilder(
            index,
            context,
            loadedState.documentSnapshots[index],
          );
        },
        childCount: loadedState.hasReachedEnd
            ? loadedState.documentSnapshots.length
            : loadedState.documentSnapshots.length + 1,
      ),
    );

    if (widget.listeners != null && widget.listeners!.isNotEmpty) {
      return MultiProvider(
        providers: widget.listeners!
            .map((_listener) => ChangeNotifierProvider(
                  create: (context) => _listener,
                ))
            .toList(),
        child: pageView,
      );
    }

    return pageView;
  }
jslattery26 commented 3 years ago

Sorry for taking some time to merge this @jslattery26. There is one small thing. We don't need a custom scroll view if we do not have a header or footer.

This worked for me,

  Widget _buildPageView(PaginationLoaded loadedState) {
    var pageView = PreloadPageView.custom(
      reverse: widget.reverse,
      controller: widget.pageController,
      scrollDirection: widget.scrollDirection,
      physics: widget.physics,
      childrenDelegate: SliverChildBuilderDelegate(
        (context, index) {
          if (index >= loadedState.documentSnapshots.length) {
            _cubit!.fetchPaginatedList();
            return widget.bottomLoader;
          }
          return widget.itemBuilder(
            index,
            context,
            loadedState.documentSnapshots[index],
          );
        },
        childCount: loadedState.hasReachedEnd
            ? loadedState.documentSnapshots.length
            : loadedState.documentSnapshots.length + 1,
      ),
    );

    if (widget.listeners != null && widget.listeners!.isNotEmpty) {
      return MultiProvider(
        providers: widget.listeners!
            .map((_listener) => ChangeNotifierProvider(
                  create: (context) => _listener,
                ))
            .toList(),
        child: pageView,
      );
    }

    return pageView;
  }

I agree. This is good on my end too. I also realized PreloadPageView is not really necessary and I reverted to Flutter's PageView. I'll put up another commit here soon.

vedartm commented 3 years ago

Really appreciate your contribution @jslattery26 🎉 @all-contributors please add @jslattery26 for code

allcontributors[bot] commented 3 years ago

@excogitatr

I've put up a pull request to add @jslattery26! :tada: