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 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 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> getGenres();
Future<List> getCompletedNovels(int page);
Future<List> getHotNovels(int page);
Future<List> getLatestReleaseNovels(int page);
Future<List> getMostPopularNovels(int page);
Future getNovelsDetails(String id);
Future<List> getSearchedNovels(String query, page);
Future getChapterContent(String href);
}

class NovelRemoteDataSource extends BaseNovelRemoteDataSource {
@override
Future<List> 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> 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> 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> 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 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> 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> 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 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
}
}