refactor: replace ListView with SuperListView across multiple widgets

This commit is contained in:
Moustapha Kodjo Amadou 2025-03-09 12:02:38 +01:00
parent dd27a6b3b3
commit 2eb4545082
29 changed files with 270 additions and 56 deletions

View file

@ -9,6 +9,7 @@ import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.da
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/modules/browse/extension/widgets/extension_lang_list_tile_widget.dart';
import 'package:mangayomi/utils/global_style.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class ExtensionsLang extends ConsumerWidget {
final ItemType itemType;
@ -71,7 +72,7 @@ class ExtensionsLang extends ConsumerWidget {
final languages = entries!.map((e) => e.lang!).toSet().toList();
languages.sort((a, b) => a.compareTo(b));
return ListView.builder(
return SuperListView.builder(
itemCount: languages.length,
itemBuilder: (context, index) {
final lang = languages[index];

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/modules/widgets/custom_sliver_grouped_list_view.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/browse/extension/providers/extensions_provider.dart';
@ -152,7 +152,7 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
}
Widget _buildUpdateSection(List<Source> updateEntries, dynamic l10n) {
return SliverGroupedListView<Source, String>(
return CustomSliverGroupedListView<Source, String>(
elements: updateEntries,
groupBy: (_) => "",
groupSeparatorBuilder:
@ -211,7 +211,7 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
}
Widget _buildInstalledSection(List<Source> installedEntries, dynamic l10n) {
return SliverGroupedListView<Source, String>(
return CustomSliverGroupedListView<Source, String>(
elements: installedEntries,
groupBy: (_) => "",
groupSeparatorBuilder:
@ -233,7 +233,7 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
}
Widget _buildNotInstalledSection(List<Source> notInstalledEntries) {
return SliverGroupedListView<Source, String>(
return CustomSliverGroupedListView<Source, String>(
elements: notInstalledEntries,
groupBy:
(element) => completeLanguageName(element.lang?.toLowerCase() ?? ''),

View file

@ -5,6 +5,7 @@ import 'package:mangayomi/modules/browse/extension/providers/extension_preferenc
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class SourcePreferenceWidget extends StatefulWidget {
final List<SourcePreference> sourcePreference;
@ -128,7 +129,7 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: pref.entries!.length,
itemBuilder: (context, index) {
@ -198,7 +199,7 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
title: Text(pref.title!),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: pref.entries!.length,
itemBuilder: (context, index) {

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/modules/widgets/custom_sliver_grouped_list_view.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/changed.dart';
@ -36,7 +36,7 @@ class SourcesFilterScreen extends ConsumerWidget {
final entries = snapshot.data!;
return CustomScrollView(
slivers: [
SliverGroupedListView<Source, String>(
CustomSliverGroupedListView<Source, String>(
elements: entries,
groupBy: (element) => element.lang!,
groupSeparatorBuilder:

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/modules/widgets/custom_sliver_grouped_list_view.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga.dart';
@ -84,7 +84,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
child: CustomScrollView(
controller: controller,
slivers: [
SliverGroupedListView<Source, String>(
CustomSliverGroupedListView<Source, String>(
elements: lastUsedEntries,
groupBy: (element) => "",
groupSeparatorBuilder:
@ -113,7 +113,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
(item1, item2) => item1.name!.compareTo(item2.name!),
order: GroupedListOrder.ASC,
),
SliverGroupedListView<Source, String>(
CustomSliverGroupedListView<Source, String>(
elements: isPinnedEntries,
groupBy: (element) => "",
groupSeparatorBuilder:
@ -142,7 +142,7 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
(item1, item2) => item1.name!.compareTo(item2.name!),
order: GroupedListOrder.ASC,
),
SliverGroupedListView<Source, String>(
CustomSliverGroupedListView<Source, String>(
elements: allEntriesWithoutIspinned,
groupBy:
(element) =>

View file

@ -2,7 +2,7 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/modules/widgets/custom_sliver_grouped_list_view.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
@ -263,7 +263,7 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
if (entries.isNotEmpty) {
return CustomScrollView(
slivers: [
SliverGroupedListView<History, String>(
CustomSliverGroupedListView<History, String>(
elements: entries,
groupBy:
(element) => dateFormat(

View file

@ -39,6 +39,7 @@ import 'package:mangayomi/modules/manga/detail/widgets/chapter_sort_list_tile_wi
import 'package:mangayomi/modules/widgets/error_text.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/utils/global_style.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class LibraryScreen extends ConsumerStatefulWidget {
final ItemType itemType;
@ -1147,7 +1148,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
builder: (context) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
final entries = snapshot.data!;
return ListView.builder(
return SuperListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (context, index) {

View file

@ -37,7 +37,7 @@ class LibraryListViewWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListViewWidget(
return SuperListViewWidget(
itemCount: entriesManga.length,
itemBuilder: (context, index) {
final entry = entriesManga[index];

View file

@ -1166,7 +1166,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: scanlators.$1.length,
itemBuilder: (context, index) {
@ -2251,7 +2251,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.separated(
child: SuperListView.separated(
padding: const EdgeInsets.all(0),
itemCount: entries!.length,
primary: false,

View file

@ -18,6 +18,7 @@ import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
import 'package:mangayomi/modules/more/providers/incognito_mode_state_provider.dart';
import 'package:mangayomi/utils/extensions/chapter.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class MangaDetailsView extends ConsumerStatefulWidget {
final Manga manga;
@ -328,7 +329,7 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
final entries = snapshot.data!;
return ListView.builder(
return SuperListView.builder(
shrinkWrap: true,
itemCount: entries.length,
itemBuilder: (context, index) {

View file

@ -10,6 +10,7 @@ import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
import 'package:mangayomi/modules/widgets/error_text.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class TrackerWidgetSearch extends ConsumerStatefulWidget {
final ItemType itemType;
@ -94,7 +95,7 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
),
if (_errorMsg == null && !hide)
Flexible(
child: ListView.separated(
child: SuperListView.separated(
padding: const EdgeInsets.only(top: 20),
itemCount: tracks!.length,
itemBuilder: (context, index) {

View file

@ -11,6 +11,7 @@ import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:mangayomi/utils/constant.dart';
import 'package:mangayomi/utils/date.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class TrackerWidget extends ConsumerStatefulWidget {
final ItemType itemType;
@ -171,7 +172,7 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
title: Text(l10n!.status),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount:
ref

View file

@ -25,6 +25,7 @@ import 'package:mangayomi/modules/manga/home/widget/mangas_card_selector.dart';
import 'package:mangayomi/modules/widgets/gridview_widget.dart';
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
import 'package:mangayomi/utils/global_style.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class MangaHomeScreen extends ConsumerStatefulWidget {
final Source source;
@ -294,7 +295,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
SizedBox(
width: context.width(1),
height: 45,
child: ListView.builder(
child: SuperListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: 3,
@ -536,7 +537,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
Flexible(
child:
displayType == DisplayType.list
? ListViewWidget(
? SuperListViewWidget(
controller: _scrollController,
itemCount: _length + 1,
itemBuilder: (context, index) {

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:mangayomi/eval/model/filter.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class FilterWidget extends StatelessWidget {
final List<dynamic> filterList;
@ -13,7 +14,7 @@ class FilterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView.builder(
return SuperListView.builder(
padding: const EdgeInsets.all(0),
itemCount: filterList.length,
primary: false,

View file

@ -44,6 +44,7 @@ import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'package:share_plus/share_plus.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
import 'package:window_manager/window_manager.dart';
import 'package:path/path.dart' as p;
@ -296,7 +297,7 @@ class _MangaChapterPageGalleryState
context: context,
constraints: BoxConstraints(maxWidth: context.width(1)),
builder: (context) {
return ListView(
return SuperListView(
shrinkWrap: true,
children: [
Container(

View file

@ -10,6 +10,7 @@ import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_pr
import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class CategoriesScreen extends ConsumerStatefulWidget {
final (bool, int) data;
@ -116,7 +117,7 @@ class _CategoriesTabState extends ConsumerState<CategoriesTab> {
);
}
_entries = data;
return ListView.builder(
return SuperListView.builder(
itemCount: _entries.length,
itemBuilder: (context, index) {
return Padding(

View file

@ -9,6 +9,7 @@ import 'package:mangayomi/modules/more/data_and_storage/providers/backup.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class CreateBackup extends ConsumerStatefulWidget {
const CreateBackup({super.key});
@ -64,7 +65,7 @@ class _CreateBackupState extends ConsumerState<CreateBackup> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
child: ListView.builder(
child: SuperListView.builder(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15),
shrinkWrap: true,
primary: false,
@ -99,7 +100,7 @@ class _CreateBackupState extends ConsumerState<CreateBackup> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
child: ListView.builder(
child: SuperListView.builder(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15),
shrinkWrap: true,
primary: false,
@ -134,7 +135,7 @@ class _CreateBackupState extends ConsumerState<CreateBackup> {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
child: ListView.builder(
child: SuperListView.builder(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 15),
shrinkWrap: true,
primary: false,

View file

@ -10,6 +10,7 @@ import 'package:mangayomi/modules/more/data_and_storage/providers/storage_usage.
import 'package:mangayomi/modules/more/settings/downloads/providers/downloads_state_provider.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class DataAndStorage extends ConsumerWidget {
const DataAndStorage({super.key});
@ -38,7 +39,7 @@ class DataAndStorage extends ConsumerWidget {
title: Text(l10n.download_location),
content: SizedBox(
width: context.width(0.8),
child: ListView(
child: SuperListView(
shrinkWrap: true,
children: [
RadioListTile(
@ -184,7 +185,7 @@ class DataAndStorage extends ConsumerWidget {
title: Text(l10n.restore_backup),
content: SizedBox(
width: context.width(0.8),
child: ListView(
child: SuperListView(
shrinkWrap: true,
children: [
Row(
@ -277,7 +278,7 @@ class DataAndStorage extends ConsumerWidget {
title: Text(l10n.backup_frequency),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (context, index) {

View file

@ -117,7 +117,7 @@ class AppearanceScreen extends ConsumerWidget {
title: Text(l10n.app_language),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount:
AppLocalizations.supportedLocales.length,
@ -388,7 +388,7 @@ class AppearanceScreen extends ConsumerWidget {
title: Text(l10n.relative_timestamp),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount:
relativeTimestampsList(context).length,
@ -460,7 +460,7 @@ class AppearanceScreen extends ConsumerWidget {
title: Text(l10n.date_format),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: dateFormatsList.length,
itemBuilder: (context, index) {

View file

@ -6,6 +6,7 @@ import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:mangayomi/modules/more/settings/appearance/providers/flex_scheme_color_state_provider.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class ThemeSelector extends ConsumerStatefulWidget {
const ThemeSelector({super.key, this.contentPadding});
@ -29,7 +30,7 @@ class _ThemeSelectorState extends ConsumerState<ThemeSelector> {
child: Row(
children: [
Expanded(
child: ListView.builder(
child: SuperListView.builder(
padding: const EdgeInsetsDirectional.only(start: 8, end: 16),
physics: const ClampingScrollPhysics(),
scrollDirection: Axis.horizontal,

View file

@ -6,6 +6,7 @@ import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class SourceRepositories extends ConsumerStatefulWidget {
final ItemType itemType;
@ -49,7 +50,7 @@ class _SourceRepositoriesState extends ConsumerState<SourceRepositories> {
}
_entries = data;
return ListView.builder(
return SuperListView.builder(
itemCount: _entries.length,
itemBuilder: (context, index) {
final repo = _entries[index];

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:mangayomi/utils/language.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class GeneralScreen extends ConsumerWidget {
const GeneralScreen({super.key});
@ -26,7 +27,7 @@ class GeneralScreen extends ConsumerWidget {
title: Text(l10n.app_language),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: AppLocalizations.supportedLocales.length,
itemBuilder: (context, index) {

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/modules/more/settings/player/providers/player_state_pr
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class PlayerScreen extends ConsumerWidget {
const PlayerScreen({super.key});
@ -39,7 +40,7 @@ class PlayerScreen extends ConsumerWidget {
title: Text(context.l10n.markEpisodeAsSeenSetting),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: values.length,
itemBuilder: (context, index) {
@ -173,7 +174,7 @@ class PlayerScreen extends ConsumerWidget {
),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: values.length,
itemBuilder: (context, index) {
@ -232,7 +233,7 @@ class PlayerScreen extends ConsumerWidget {
title: Text(context.l10n.default_playback_speed_length),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: values.length,
itemBuilder: (context, index) {
@ -338,7 +339,7 @@ class PlayerScreen extends ConsumerWidget {
),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: values.length,
itemBuilder: (context, index) {

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class ReaderScreen extends ConsumerWidget {
const ReaderScreen({super.key});
@ -38,7 +39,7 @@ class ReaderScreen extends ConsumerWidget {
title: Text(context.l10n.default_reading_mode),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: ReaderMode.values.length,
itemBuilder: (context, index) {
@ -104,7 +105,7 @@ class ReaderScreen extends ConsumerWidget {
title: Text(context.l10n.double_tap_animation_speed),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
@ -166,7 +167,7 @@ class ReaderScreen extends ConsumerWidget {
title: Text(context.l10n.background_color),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: BackgroundColor.values.length,
itemBuilder: (context, index) {
@ -231,7 +232,7 @@ class ReaderScreen extends ConsumerWidget {
title: Text(context.l10n.page_preload_amount),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: numbers.length,
itemBuilder: (context, index) {
@ -290,7 +291,7 @@ class ReaderScreen extends ConsumerWidget {
title: Text(context.l10n.scale_type),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: getScaleTypeNames(context).length,
itemBuilder: (context, index) {

View file

@ -10,6 +10,7 @@ import 'package:mangayomi/modules/more/settings/sync/widgets/sync_listile.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/sync_server.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class SyncScreen extends ConsumerWidget {
const SyncScreen({super.key});
@ -69,7 +70,7 @@ class SyncScreen extends ConsumerWidget {
title: Text(l10n.sync_auto),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: autoSyncOptions.length,
itemBuilder: (context, index) {
@ -666,7 +667,7 @@ class SyncScreen extends ConsumerWidget {
title: Text(l10n.sync_snapshots),
content: SizedBox(
width: context.width(0.8),
child: ListView.builder(
child: SuperListView.builder(
shrinkWrap: true,
itemCount: snapshots.length,
itemBuilder: (context, index) {

View file

@ -7,6 +7,7 @@ import 'package:mangayomi/models/track_preference.dart';
import 'package:mangayomi/modules/manga/detail/widgets/tracker_widget.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/constant.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class TrackingDetail extends StatefulWidget {
final TrackPreference trackerPref;
@ -85,7 +86,7 @@ class TrackingTab extends StatelessWidget {
final mediaIds = trackRes!.map((e) => e.mediaId).toSet().toList();
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.separated(
child: SuperListView.separated(
padding: const EdgeInsets.all(0),
itemCount: mediaIds.length,
primary: false,
@ -149,7 +150,7 @@ class TrackingWidget extends StatelessWidget {
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.separated(
child: SuperListView.separated(
padding: const EdgeInsets.all(0),
itemCount: trackRes.length,
primary: false,

View file

@ -1,7 +1,7 @@
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:grouped_list/sliver_grouped_list.dart';
import 'package:mangayomi/modules/widgets/custom_sliver_grouped_list_view.dart';
import 'package:isar/isar.dart';
import 'package:mangayomi/eval/model/m_bridge.dart';
@ -389,7 +389,7 @@ class _UpdateTabState extends ConsumerState<UpdateTab> {
]),
),
),
SliverGroupedListView<Update, String>(
CustomSliverGroupedListView<Update, String>(
elements: entries,
groupBy:
(element) => dateFormat(

View file

@ -0,0 +1,195 @@
// ignore_for_file: implementation_imports
import 'dart:collection';
import 'package:flutter/widgets.dart';
import 'package:grouped_list/src/grouped_list_order.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
export 'package:grouped_list/src/grouped_list_order.dart';
@immutable
class CustomSliverGroupedListView<T, E> extends StatefulWidget {
/// Items of which [itemBuilder] or [indexedItemBuilder] produce the list.
final List<T> elements;
/// Defines which elements are grouped together.
///
/// Function is called for each element in the list, when equal for two
/// elements, those two belong to the same group.
final E Function(T element) groupBy;
/// Can be used to define a custom sorting for the groups.
///
/// If not set groups will be sorted with their natural sorting order or their
/// specific [Comparable] implementation.
final int Function(E value1, E value2)? groupComparator;
/// Can be used to define a custom sorting for the elements inside each group.
///
/// If not set elements will be sorted with their natural sorting order or
/// their specific [Comparable] implementation.
final int Function(T element1, T element2)? itemComparator;
/// Called to build group separators for each group.
/// Value is always the groupBy result from the first element of the group.
///
/// Will be ignored if [groupHeaderBuilder] is used.
final Widget Function(E value)? groupSeparatorBuilder;
/// Same as [groupSeparatorBuilder], will be called to build group separators
/// for each group.
/// The passed element is always the first element of the group.
///
/// If defined [groupSeparatorBuilder] wont be used.
final Widget Function(T element)? groupHeaderBuilder;
/// Called to build children for the list with
/// 0 <= element < elements.length.
final Widget Function(BuildContext context, T element)? itemBuilder;
/// Called to build children for the list with
/// 0 <= element, index < elements.length
final Widget Function(BuildContext context, T element, int index)?
indexedItemBuilder;
/// Whether the order of the list is ascending or descending.
///
/// Defaults to ASC.
final GroupedListOrder order;
/// Whether the elements will be sorted or not. If not it must be done
/// manually.
///
/// Defauts to true.
final bool sort;
/// Called to build separators for between each item in the list.
final Widget separator;
/// Widget at the end of the list
final Widget? footer;
/// Creates a [CustomSliverGroupedListView]
const CustomSliverGroupedListView({
super.key,
required this.elements,
required this.groupBy,
this.groupComparator,
this.groupSeparatorBuilder,
this.groupHeaderBuilder,
this.itemBuilder,
this.indexedItemBuilder,
this.itemComparator,
this.order = GroupedListOrder.ASC,
this.sort = true,
this.separator = const SizedBox.shrink(),
this.footer,
}) : assert(itemBuilder != null || indexedItemBuilder != null),
assert(groupSeparatorBuilder != null || groupHeaderBuilder != null);
@override
State<StatefulWidget> createState() =>
_CustomSliverGroupedListViewState<T, E>();
}
class _CustomSliverGroupedListViewState<T, E>
extends State<CustomSliverGroupedListView<T, E>> {
final LinkedHashMap<String, GlobalKey> _keys = LinkedHashMap();
List<T> _sortedElements = [];
@override
Widget build(BuildContext context) {
_sortedElements = _sortElements();
var hiddenIndex = 0;
isSeparator(int i) => i.isEven;
return SuperSliverList(
delegate: SliverChildBuilderDelegate(
childCount:
widget.footer == null
? _sortedElements.length * 2
: (_sortedElements.length * 2) + 1,
(context, index) {
var actualIndex = index ~/ 2;
if (widget.footer != null && index == _sortedElements.length * 2) {
return widget.footer!;
}
if (index == hiddenIndex) {
return Opacity(
opacity: 1,
child: _buildGroupSeparator(_sortedElements[actualIndex]),
);
}
if (isSeparator(index)) {
var curr = widget.groupBy(_sortedElements[actualIndex]);
var prev = widget.groupBy(_sortedElements[actualIndex - 1]);
if (prev != curr) {
return _buildGroupSeparator(_sortedElements[actualIndex]);
}
return widget.separator;
}
return _buildItem(context, actualIndex);
},
),
);
}
Container _buildItem(context, int actualIndex) {
var key = GlobalKey();
_keys['$actualIndex'] = key;
return Container(
key: key,
child:
widget.indexedItemBuilder == null
? widget.itemBuilder!(context, _sortedElements[actualIndex])
: widget.indexedItemBuilder!(
context,
_sortedElements[actualIndex],
actualIndex,
),
);
}
List<T> _sortElements() {
var elements = [...widget.elements];
if (widget.sort && elements.isNotEmpty) {
elements.sort((e1, e2) {
int? compareResult;
// compare groups
if (widget.groupComparator != null) {
compareResult = widget.groupComparator!(
widget.groupBy(e1),
widget.groupBy(e2),
);
} else if (widget.groupBy(e1) is Comparable) {
compareResult = (widget.groupBy(e1) as Comparable).compareTo(
widget.groupBy(e2) as Comparable,
);
}
// compare elements inside group
if (compareResult == null || compareResult == 0) {
if (widget.itemComparator != null) {
compareResult = widget.itemComparator!(e1, e2);
} else if (e1 is Comparable) {
compareResult = e1.compareTo(e2);
}
}
return compareResult!;
});
if (widget.order == GroupedListOrder.DESC) {
elements = elements.reversed.toList();
}
}
return elements;
}
Widget _buildGroupSeparator(T element) {
if (widget.groupHeaderBuilder == null) {
return widget.groupSeparatorBuilder!(widget.groupBy(element));
}
return widget.groupHeaderBuilder!(element);
}
}

View file

@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
class ListViewWidget extends StatelessWidget {
class SuperListViewWidget extends StatelessWidget {
final ScrollController? controller;
final int? itemCount;
final bool reverse;
final Widget? Function(BuildContext, int) itemBuilder;
const ListViewWidget({
const SuperListViewWidget({
super.key,
this.controller,
required this.itemCount,