MIT License GitHub stars pub version

Buy Me A Coffee


🧩 Flutter Chat Pagination

A lightweight and efficient chat pagination system for Flutter β€” built with Riverpod and FlutterListView for seamless infinite scrolling, smooth state handling, and full UI flexibility.


🌟 Features

  • ⚑ Infinite scrolling β€” load messages in pages (up or down)
  • πŸ’¬ Customizable message builder β€” you control the UI
  • 🧠 Riverpod-powered state management β€” reactive and clean
  • πŸ”„ Smart preload thresholds β€” efficient, automatic page requests
  • 🎨 Composable design β€” works with any message bubble layout
  • πŸ“¦ Simple controller API β€” easy to integrate and extend

πŸš€ Getting Started

1. Install the package

Add the dependency in your pubspec.yaml:

dependencies:
  flutter_chat_pagination:
    git:
      url: https://github.com/YimaPhilemon/chat_pagination.git

Or

dependencies:
  flutter_chat_pagination: ^0.0.2

Then run:

flutter pub get

🧱 Architecture Overview This package is built around three core layers:

Component Type Responsibility ChatPaginationView Widget Displays the chat list and handles scroll detection ChatPaginationController Class Controls pagination requests, scrolling, and triggers ChatPaginationNotifier StateNotifier Manages message state, loading, and pagination flags

πŸ’‘ Basic Usage

  1. Import dependencies
import 'package:flutter_chat_paginator/flutter_chat_paginator.dart';
  1. Initialize in your main app
void main() {
  runApp(const ProviderScope(child: ChatApp()));
}
  1. Create the Chat Screen
class ChatApp extends ConsumerStatefulWidget {
  const ChatApp({super.key});

  @override
  ConsumerState<ChatApp> createState() => _ChatAppState();
}

class _ChatAppState extends ConsumerState<ChatApp> {
  late final ChatPaginationController controller;

  @override
  void initState() {
    super.initState();
    controller = ChatPaginationController(
      ref: ref,
      onPageRequestCallback: (pageIndex, pageSize) async {
        // Simulate API call
        await Future.delayed(const Duration(seconds: 1));
        final messages = List.generate(
          pageSize,
          (i) => "Message ${(pageIndex * pageSize) + i + 1}",
        );
        controller.addMessages(messages, prepend: true);
      },
    );

    controller.loadFirstPage();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Chat Pagination Example')),
        body: ChatPaginationView(
          controller: controller,
          itemBuilder: (context, index, message) {
            return Container(
              padding: const EdgeInsets.all(8),
              margin: const EdgeInsets.symmetric(vertical: 4),
              decoration: BoxDecoration(
                color: Colors.orange.shade50,
                borderRadius: BorderRadius.circular(12),
              ),
              child: Text(message),
            );
          },
        ),
      ),
    );
  }
}

βš™οΈ Configuration Options You can tweak scrolling behavior and thresholds easily:

Parameter Default Description pageMinTriggerOffset 200.0 Minimum scroll offset to trigger next page pageMaxTriggerOffset 800.0 Maximum threshold to cap trigger distance disableCacheItems true Disable item caching for dynamic lists keepPosition true Maintain scroll position after updates firstItemAlign FirstItemAlign.start Initial alignment of the list padding EdgeInsets.all(16) List padding

πŸ” Controller API Reference Method Description loadFirstPage() Loads the first page after initialization requestNextPage() Manually load the next page addMessages(List messages, {bool prepend = false}) Add a list of messages addMessage(dynamic message, {bool prepend = false}) Add a single message reset() Clears all messages and resets pagination scrollToBottom({bool animated = true}) Scrolls to the newest message

🧠 State Notifier Reference ChatPaginationNotifier extends StateNotifier

Property Type Description messages List

🧩 Example UI with FlutterListView The package uses FlutterListView under the hood to handle efficient scrolling with thousands of messages. You can safely append or prepend messages without losing scroll position.

FlutterListView(
  controller: controller.listController,
  delegate: FlutterListViewDelegate(
    (context, index) {
      final message = state.messages[index];
      return ChatBubble(message: message);
    },
    childCount: state.messages.length,
  ),
);

🧰 Advanced Example: Preloading Logic You can enable preload offset to stop pagination after a specific page count:

controller = ChatPaginationController(
  ref: ref,
  preloadOffset: 3, // after 3 pages, stop auto-loading
  onPageRequestCallback: (pageIndex, pageSize) async {
    ...
  },
);

🧼 Resetting the Chat

controller.reset(); // Clears messages and resets the current page

πŸ“¦ Folder Structure

lib/
β”œβ”€β”€ chat_pagination_controller.dart
β”œβ”€β”€ chat_pagination_notifier.dart
└── chat_pagination_view.dart

πŸ’¬ Future Plans βœ… Bidirectional pagination (load older & newer messages)

βœ… Auto-scroll during live message streaming

πŸ”œ Scroll anchor restoration across sessions

πŸ”œ Integration with popular chat APIs (Firebase, Supabase, etc.)

πŸ”œ Built-in message group headers (date separators)

πŸ§‘β€πŸ’» Contributing Pull requests are welcome! If you find a bug or want to suggest an improvement, open an issue.

πŸͺͺ License This project is licensed under the MIT License. See the LICENSE file for details.

❀️ Credits Developed with πŸ’™ for the Flutter community.