i want you to help me with this one I'm develepen a flutter app that scrape novels from a website the problem is the website shows the data in pages like page 1 have 8 novels if you want more you have to go to the page 2 and so on , now when create the function that scrape novels add the parametar  int page to load the data from page 1 then page 2 and so on , NovelCubit(
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
        )..getHotNovels(1),
        child: const HomeScreen(), you see the issue here that I want to load the data in page 1 then change it to 2 when the user scroll down or click in a specific button for more novels and 3 and so on how to make it work , import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:learning/Core/Services/services_locator.dart';
import 'package:learning/Core/Utils/size.dart';
import 'package:learning/Presentation/Controller/Novel/novel_cubit.dart';
import 'package:learning/Presentation/Controller/Search/search_cubit.dart';

import 'package:learning/Presentation/Resources/Colors/color_manger.dart';
import 'package:learning/Presentation/Screens/bookmark_screen.dart';
import 'package:learning/Presentation/Screens/home_screen.dart';
import 'package:learning/Presentation/Screens/search_screen.dart';
import 'package:learning/Presentation/Screens/setting_screen.dart';

import '../Controller/Navigation/Navigation_state.dart';
import '../Controller/Navigation/navigation_cubit.dart';

class MainScreen extends StatelessWidget {
  const MainScreen({super.key});

  @override
  Widget build(BuildContext context) {
    SizeConfig.init(context);
    return const MainScreenContent();
  }
}

class MainScreenContent extends StatelessWidget {
  const MainScreenContent({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<NavigationCubit, NavigationState>(
      listener: (context, state) {
        // If there's no action to be taken on state change, this can be removed.
      },
      builder: (context, state) {
        return Stack(
          children: [
            _buildBody(state.selectedIndex),
            Positioned(
              right: 20,
              left: 20,
              bottom: 10,
              child: _buildBottomNavigationBar(context, state.selectedIndex),
            ),
          ],
        );
      },
    );
  }

  Widget _buildBody(int currentIndex) {
    List<Widget> navigationScreens = [
      BlocProvider(
        create: (context) => NovelCubit(
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
          serverLocator(),
        )..getHotNovels(1),
        child: const HomeScreen(),
      ),
      const BookmarkScreen(),
      BlocProvider(
        create: (context) => SearchCubit(),
        child: const SearchScreen(),
      ),
      const SettingScreen(),
    ];
    return IndexedStack(
      index: currentIndex,
      children: navigationScreens,
    );
  }

  Widget _buildBottomNavigationBar(BuildContext context, int selectedIndex) {
    List<IconData> listOfIcons = [
      Icons.home,
      Icons.bookmark,
      Icons.search,
      Icons.settings,
    ];

    return Container(
      height: SizeConfig.size.height * 0.11,
      width: SizeConfig.size.width * 0.8,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(30),
        color: Theme.of(context).brightness == Brightness.dark
            ? ColorManger.blueColor.withOpacity(0.6)
            : ColorManger.bluelighteColor.withOpacity(0.3),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: List.generate(
          listOfIcons.length,
          (index) {
            return Material(
              color: ColorManger.transparent,
              child: InkWell(
                onTap: () => BlocProvider.of<NavigationCubit>(context)
                    .updateIndex(index),
                splashColor: ColorManger.transparent,
                highlightColor: ColorManger.transparent,
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    AnimatedContainer(
                      alignment: Alignment.center,
                      duration: const Duration(milliseconds: 150),
                      height: index == selectedIndex
                          ? SizeConfig.size.height * 0.0756
                          : 0,
                      width: index == selectedIndex
                          ? SizeConfig.size.height * 0.0756
                          : 0,
                      curve: Curves.easeInCirc,
                      decoration: BoxDecoration(
                        color: index == selectedIndex
                            ? ColorManger.readNowBottomColor
                            : ColorManger.transparent,
                        shape: BoxShape.circle,
                      ),
                    ),
                    Icon(
                      listOfIcons[index],
                      size: SizeConfig.size.width * .076,
                      color: index == selectedIndex
                          ? ColorManger.bluelighteColor
                          : ColorManger.unSelectedIconColor,
                    ),
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}
, import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:learning/App/Contanse/app_contanse.dart';
import 'package:learning/Core/Services/services_locator.dart';
import 'package:learning/Core/Utils/size.dart';
import 'package:learning/Domain/Entites/novel.dart';
import 'package:learning/Presentation/Controller/Novel/novel_cubit.dart';
import 'package:learning/Presentation/Resources/Fonts/style_manager.dart';
import 'package:skeletonizer/skeletonizer.dart';

import '../Resources/Colors/color_manger.dart';

import '../Resources/Strings/stings_manager.dart';
import '../Resources/Theme/theme_manager.dart';
import '../Resources/Values/values_manger.dart';
import 'detail_screen.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: Theme.of(context).brightness == Brightness.light
                ? ColorManger.homePageGradiantLight
                : ColorManger.homePageGradiantDark,
          ),
        ),
        child: SafeArea(
          child: CustomScrollView(
            slivers: [
              SliverToBoxAdapter(
                child: BlocBuilder<NovelCubit, NovelState>(
                  builder: (context, novelState) {
                    if (novelState is NovelLoading) {
                      return Skeletonizer(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Container(
                              height: SizeConfig.size.height * 0.30,
                              width: SizeConfig.size.width * 0.45,
                              decoration: BoxDecoration(
                                color:
                                    Colors.grey[800], // Placeholder for image
                                borderRadius: BorderRadius.circular(
                                    BorderRadiusManager.b16),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.symmetric(vertical: 8),
                              height: 20,
                              width: SizeConfig.size.width * 0.6,
                              color: Colors.grey[700], // Placeholder for title
                            ),
                            Container(
                              height: 16,
                              width: SizeConfig.size.width * 0.3,
                              color: Colors.grey[700], // Placeholder for author
                            ),
                            const SizedBox(height: 5),
                            Container(
                              height: 40,
                              width: SizeConfig.size.width * 0.3,
                              decoration: BoxDecoration(
                                color:
                                    Colors.grey[800], // Placeholder for button
                                borderRadius: BorderRadius.circular(
                                    BorderRadiusManager.b19),
                              ),
                            ),
                          ],
                        ),
                      );
                    } else if (novelState is NovelSuccessfullyLoaded) {
                      return CarouselSlider.builder(
                        itemCount: novelState.novels.length,
                        itemBuilder: (context, index, realIndex) {
                          final novel = novelState.novels[index];
                          return Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              imageSlider(novel),
                              novelTitle(novel, context),
                              authorName(novel, context),
                              const SizedBox(
                                height: 5,
                              ),
                              buttomReadNow(context, novel.id),
                            ],
                          );
                        },
                        options: CarouselOptions(
                          height: SizeConfig.size.height * 0.53,
                          autoPlay: true,
                          enlargeCenterPage: true,
                          viewportFraction: 0.8,
                        ),
                      );
                    } else if (novelState is NovelError) {
                      return Center(
                        child: Text(novelState.errorMessage),
                      );
                    }
                    return const SizedBox.shrink();
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Text authorName(Novel novel, BuildContext context) {
    return Text(
      novel.author,
      style: getLabelLargeStyle(
          color: Theme.of(context).brightness == Brightness.light
              ? ColorManger.authorNamedColorlight
              : ColorManger.authorNamedColordark),
    );
  }

  ElevatedButton buttomReadNow(context, id) {
    return ElevatedButton(
        style: buttonStyle(),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => BlocProvider(
                create: (context) => NovelCubit(
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                  serverLocator(),
                )..getNovelsDetails(id),
                child: const DetailScreen(),
              ),
            ),
          );
        },
        child: Text(
          StingsManager.readNow,
          style: getLabelLargeStyle(
            color: ColorManger.whiteColor,
          ),
        ));
  }

  Text novelTitle(Novel novel, BuildContext context) {
    return Text(
      novel.title,
      textAlign: TextAlign.center,
      style: getTitleLargeStyle(
        color: Theme.of(context).brightness == Brightness.light
            ? ColorManger.blackColor
            : ColorManger.whiteColor,
      ),
    );
  }

  Flexible imageSlider(Novel novel) {
    return Flexible(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(BorderRadiusManager.b16),
        child: Container(
          height: SizeConfig.size.height * 0.42,
          width: SizeConfig.size.width * 0.45,
          decoration: const BoxDecoration(),
          child: image(AppContanse.baseImageUrl + novel.image),
        ),
      ),
    );
  }
}

Widget image(String url) {
  return Image.network(
    url,
    fit: BoxFit.fitHeight,
  );
}
, import 'dart:developer';

import 'package:html/dom.dart' as dom;

import 'package:learning/Data/model/chapter_content_model.dart';
import 'package:learning/Data/model/novel_model.dart';
import 'package:http/http.dart' as http;
import 'package:html/parser.dart' show parse;

import '../App/Contanse/app_contanse.dart';

import 'Scraping Logic/chapter_content_logic.dart/get_chapter_content_page.dart';

import 'Scraping Logic/get_chapter_list.dart';
import 'Scraping Logic/get_total_pages.dart';

abstract class BaseNovelRemoteDataSource {
  Future<List<String>> getGenres();
  Future<List<NovelModel>> getCompletedNovels(int page);
  Future<List<NovelModel>> getHotNovels(int page);
  Future<List<NovelModel>> getLatestReleaseNovels(int page);
  Future<List<NovelModel>> getMostPopularNovels(int page);
  Future<NovelModel> getNovelsDetails(String id);
  Future<List<NovelModel>> getSearchedNovels(String query, page);
  Future<ChapterContentModel> getChapterContent(String href);
}

class NovelRemoteDataSource extends BaseNovelRemoteDataSource {
  @override
  Future<List<NovelModel>> getCompletedNovels(int page) async {
    // Get the total number of pages
    final url = "${AppContanse.completedNovelUrl}?page=$page";
    final totalPages = await getTotalPages(url);
    final response = await http.get(Uri.parse(url));

    if (page > totalPages) {
      return [];
    }

    if (response.statusCode == 200) {
      final document = parse(response.body);
      final novelEntries = document.querySelectorAll('div.row');

      List<NovelModel> novels = [];

      for (var entry in novelEntries) {
        try {
          final imgDiv = entry.querySelector('div.col-xs-3');
          final infoDiv = entry.querySelector('div.col-xs-7');
          if (imgDiv != null && infoDiv != null) {
            final imgTag = imgDiv.querySelector('img.cover.lazy');
            final imgSrc =
                imgTag?.attributes['data-src'] ?? "Image URL not found";
            final parsedUri = Uri.parse(imgSrc);
            final path = parsedUri.path;
            final img = path.split('/').last;

            // Extract the id by removing '.jpg'
            final id = img.replaceAll('.jpg', '');

            final novelLink = infoDiv.querySelector('h3.novel-title a');
            final novelTitle = novelLink?.attributes['title'] ??
                novelLink?.text.trim() ??
                "Title not found";

            final authorSpan = infoDiv.querySelector('span.author');
            final author =
                authorSpan?.nodes.last.text?.trim() ?? "Author not found";

            novels.add(
              NovelModel(
                id: id, // Set the id here
                author: author,
                status: '',
                genre: const [],
                publishers: '',
                yearOfPublishing: '',
                description: '',
                title: novelTitle,
                chapters: const [],
                image: img,
              ),
            );
          }
        } catch (e) {
          log("An error occurred while processing an entry: $e");
          continue;
        }
      }

      return novels;
    } else {
      throw Exception('Failed to load novels');
    }
  }

  @override
  Future<List<NovelModel>> getHotNovels(int page) async {
    final url = "${AppContanse.hotNovelUrl}?page=$page";
    final totalPages = await getTotalPages(url);
    final response = await http.get(Uri.parse(url));

    if (page > totalPages) {
      return [];
    }

    if (response.statusCode == 200) {
      final document = parse(response.body);
      final novelEntries = document.querySelectorAll('div.row');

      List<NovelModel> novels = [];

      for (var entry in novelEntries) {
        try {
          final imgDiv = entry.querySelector('div.col-xs-3');
          final infoDiv = entry.querySelector('div.col-xs-7');
          if (imgDiv != null && infoDiv != null) {
            final imgTag = imgDiv.querySelector('img.cover.lazy');
            final imgSrc =
                imgTag?.attributes['data-src'] ?? "Image URL not found";
            final parsedUri = Uri.parse(imgSrc);
            final path = parsedUri.path;
            final img = path.split('/').last;
            final id = img.replaceAll('.jpg', '');
            final novelLink = infoDiv.querySelector('h3.novel-title a');
            final novelTitle = novelLink?.attributes['title'] ??
                novelLink?.text.trim() ??
                "Title not found";

            final authorSpan = infoDiv.querySelector('span.author');
            final author =
                authorSpan?.nodes.last.text?.trim() ?? "Author not found";

            novels.add(
              NovelModel(
                author: author,
                status: '',
                genre: const [],
                publishers: '',
                yearOfPublishing: '',
                description: '',
                title: novelTitle,
                chapters: const [],
                image: img,
                id: id,
              ),
            );
          }
        } catch (e) {
          log("An error occurred while processing an entry: $e");
          continue;
        }
      }

      return novels;
    } else {
      throw Exception('Failed to load page');
    }
  }

  @override
  Future<List<NovelModel>> getLatestReleaseNovels(int page) async {
    final url = "${AppContanse.latestReleaseNovelUrl}?page=$page";
    final totalPages = await getTotalPages(url);
    final response = await http.get(Uri.parse(url));

    if (page > totalPages) {
      return [];
    }

    if (response.statusCode == 200) {
      final document = parse(response.body);
      final novelEntries = document.querySelectorAll('div.row');

      List<NovelModel> novels = [];

      for (var entry in novelEntries) {
        try {
          final imgDiv = entry.querySelector('div.col-xs-3');
          final infoDiv = entry.querySelector('div.col-xs-7');
          if (imgDiv != null && infoDiv != null) {
            final imgTag = imgDiv.querySelector('img.cover.lazy');
            final imgSrc =
                imgTag?.attributes['data-src'] ?? "Image URL not found";
            final parsedUri = Uri.parse(imgSrc);
            final path = parsedUri.path;
            final img = path.split('/').last;
            final id = img.replaceAll('.jpg', '');
            final novelLink = infoDiv.querySelector('h3.novel-title a');
            final novelTitle = novelLink?.attributes['title'] ??
                novelLink?.text.trim() ??
                "Title not found";

            final authorSpan = infoDiv.querySelector('span.author');
            final author =
                authorSpan?.nodes.last.text?.trim() ?? "Author not found";

            novels.add(
              NovelModel(
                author: author,
                status: '',
                genre: const [],
                publishers: '',
                yearOfPublishing: '',
                description: '',
                title: novelTitle,
                chapters: const [],
                image: img,
                id: id,
              ),
            );
          }
        } catch (e) {
          log("An error occurred while processing an entry: $e");
          continue;
        }
      }

      return novels;
    } else {
      throw Exception('Failed to load page');
    }
  }

  @override
  Future<List<NovelModel>> getMostPopularNovels(int page) async {
    final url = "${AppContanse.popularNovelUrl}?page=$page";
    final totalPages = await getTotalPages(url);
    final response = await http.get(Uri.parse(url));

    if (page > totalPages) {
      return [];
    }

    if (response.statusCode == 200) {
      final document = parse(response.body);
      final novelEntries = document.querySelectorAll('div.row');

      List<NovelModel> novels = [];

      for (var entry in novelEntries) {
        try {
          final imgDiv = entry.querySelector('div.col-xs-3');
          final infoDiv = entry.querySelector('div.col-xs-7');
          if (imgDiv != null && infoDiv != null) {
            final imgTag = imgDiv.querySelector('img.cover.lazy');
            final imgSrc =
                imgTag?.attributes['data-src'] ?? "Image URL not found";
            final parsedUri = Uri.parse(imgSrc);
            final path = parsedUri.path;
            final img = path.split('/').last;
            final id = img.replaceAll('.jpg', '');
            final novelLink = infoDiv.querySelector('h3.novel-title a');
            final novelTitle = novelLink?.attributes['title'] ??
                novelLink?.text.trim() ??
                "Title not found";

            final authorSpan = infoDiv.querySelector('span.author');
            final author =
                authorSpan?.nodes.last.text?.trim() ?? "Author not found";

            novels.add(
              NovelModel(
                author: author,
                status: '',
                genre: const [],
                publishers: '',
                yearOfPublishing: '',
                description: '',
                title: novelTitle,
                chapters: const [],
                image: img,
                id: id,
              ),
            );
          }
        } catch (e) {
          log("An error occurred while processing an entry: $e");
          continue;
        }
      }

      return novels;
    } else {
      throw Exception('Failed to load page');
    }
  }

  @override
  Future<NovelModel> getNovelsDetails(String id) async {
    final String url = "https://novelbin.me/novel-book/$id";
    try {
      final response = await http.get(Uri.parse(url));

      if (response.statusCode == 200) {
        final document = parse(response.body);

        String safeExtract(dom.Element? element, {String? attribute}) {
          if (element == null) return 'N/A';
          if (attribute != null) return element.attributes[attribute] ?? 'N/A';
          return element.text.trim();
        }

        final title =
            safeExtract(document.querySelector('h3.title[itemprop="name"]'));
        final authorMeta = document
            .querySelector('span[itemprop="author"] meta[itemprop="name"]');
        final author = safeExtract(authorMeta, attribute: 'content');

        final genres = document.querySelectorAll('li').where((li) {
          return li.querySelector('h3')?.text.trim() == 'Genre:';
        }).expand((li) {
          return li
              .querySelectorAll(
                  'a[href^="https://novelbin.me/novelbin-genres/"]')
              .map((a) => a.text.trim());
        }).toList();

        final statusElement = document
            .querySelector('a[href^="https://novelbin.me/sort/novelbin-"]');
        final status = safeExtract(statusElement);

        final imageMeta = document.querySelector('meta[itemprop="image"]');
        final imageUrl = safeExtract(imageMeta, attribute: 'content');
        final img = imageUrl.split('/').last;

        String description = 'N/A';
        final descriptionDiv = document.querySelector('div#tab-description');
        if (descriptionDiv != null) {
          final descTextDiv = descriptionDiv.querySelector('div.desc-text');
          if (descTextDiv != null) {
            description = descTextDiv.text.trim();
          }
        }
        final chapterList = await fetchChaptersList(id);
        // Now return the extracted data in a NovelModel instance
        return NovelModel(
          title: title,
          author: author,
          genre: genres,
          status: status,
          image: img,
          description: description,
          publishers: '',
          yearOfPublishing: '',
          chapters: chapterList,
          id: id,
        );
      } else {
        throw Exception("Failed to load novel information");
      }
    } catch (e) {
      // Optionally log or rethrow the error for debugging
      log('Error occurred: $e');
      throw Exception('Error occurred while fetching novel details');
    }
  }

  @override
  Future<List<String>> getGenres() async {
    const url = AppContanse.genresUrl;
    final response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      final document = parse(response.body);
      final genreItems = document.querySelectorAll('ul.dropdown-menu li a');

      List<String> genres = [];

      for (var genreItem in genreItems) {
        final genreName = genreItem.text.trim();
        if (genreName.isNotEmpty &&
            !['Yaoi', 'Yuri', 'Lgbt+', 'Adult'].contains(genreName)) {
          genres.add(genreName);
        }
      }

      return genres;
    } else {
      throw Exception('Failed to load genres');
    }
  }

  @override
  Future<List<NovelModel>> getSearchedNovels(String query, page) async {
    final url =
        Uri.parse('https://novelbin.me/search?keyword=$query&page=$page');
    final response = await http.get(url);

    if (response.statusCode == 200) {
      var document = parse(response.body);
      var novelEntries = document.querySelectorAll('div.row');
      List<NovelModel> novels = [];

      for (var entry in novelEntries) {
        try {
          var titleElement = entry.querySelector('h3.novel-title');
          var title = titleElement?.text.trim();

          var imgElement = entry.querySelector('img.cover');
          var image = imgElement?.attributes['src']?.split('/').last;

          var authorElement = entry.querySelector('span.author');
          var author = authorElement?.text.trim();

          if (title != null && image != null && author != null) {
            novels.add(NovelModel(
              id: '', // Add an appropriate id if available
              title: title,
              author: author,
              image: image,
              genre: const [], // Add genres if you can extract them
              status: '', // Add status if available
              publishers: '', // Add publishers if available
              yearOfPublishing: '', // Add year if available
              description: '', // Add description if needed
              chapters: const [], // Chapters can be added after scraping the details page
            ));
          }
        } catch (e) {
          log('Error occurred while processing entry: $e');
          continue;
        }
      }

      return novels;
    } else {
      throw Exception(
          'Failed to retrieve the webpage. Status code: ${response.statusCode}');
    }
  }

  @override
  Future<ChapterContentModel> getChapterContent(String href) async {
    final pageContent = await fetchPage(href);

    dom.Document document = parse(pageContent);

    // Extract Novel Title
    final novelTitle =
        document.querySelector('a.novel-title')?.text.trim() ?? 'Unknown Novel';

    // Initialize chapter variables
    String chapterNumber = 'Unknown Number';
    String chapterTitle = 'Unknown Title';
    String chapterContent = 'No Content Found.';

    // Extract Chapter Title and Number
    var chapterTitleElement = document.querySelector('a.chr-title span');
    if (chapterTitleElement != null) {
      var chapterTitleFull = chapterTitleElement.text.trim();
      if (chapterTitleFull.contains(':')) {
        var parts = chapterTitleFull.split(':');
        chapterNumber = parts[0].replaceAll('Chapter', '').trim();
        chapterTitle = parts[1].trim();
      } else {
        chapterTitle = chapterTitleFull; // Use full title if no ':' found
      }
    }

    // Extract Chapter Content
    var chapterContentElements = document.querySelector('#chr-content');
    if (chapterContentElements != null) {
      chapterContent = chapterContentElements
          .getElementsByTagName('p')
          .map((para) => para.text.trim())
          .where((text) => text.isNotEmpty)
          .join('\n\n');
    }

    return ChapterContentModel(
      chapterContent: chapterContent,
      chapterNumber: chapterNumber,
      chapterTitle: chapterTitle,
      novelTitle: novelTitle,
    ); // Use chapterTitle instead of novelTitle
  }
}