Merge pull request #618 from Whiskas101/fix/statistics-synchronous-load

fix: updated statistics to use async fetch from db
This commit is contained in:
Moustapha Kodjo Amadou 2025-12-05 10:19:01 +01:00 committed by GitHub
commit 0789f4c85a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 106 additions and 69 deletions

View file

@ -6,37 +6,68 @@ import 'package:mangayomi/models/manga.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'statistics_provider.g.dart'; part 'statistics_provider.g.dart';
class StatisticsData {
final int totalItems;
final int totalChapters;
final int readChapters;
final int completedItems;
final int downloadedItems;
const StatisticsData({
required this.totalItems,
required this.totalChapters,
required this.readChapters,
required this.completedItems,
required this.downloadedItems,
});
}
@riverpod @riverpod
class StatisticsState extends _$StatisticsState { class StatisticsState extends _$StatisticsState {
@override @override
void build(ItemType itemType) {} Future<StatisticsData> build(ItemType itemType) async {
final items = isar.mangas final items = await isar.mangas
.filter() .filter()
.idIsNotNull() .idIsNotNull()
.favoriteEqualTo(true) .favoriteEqualTo(true)
.findAllSync(); .itemTypeEqualTo(itemType)
final chapters = isar.chapters .findAll();
.filter()
.idIsNotNull()
.manga((q) => q.favoriteEqualTo(true))
.findAllSync();
int get totalItems => items.where((i) => i.itemType == itemType).length;
int get totalChapters =>
chapters.where((i) => i.manga.value!.itemType == itemType).length;
int get readChapters => chapters
.where((i) => i.manga.value!.itemType == itemType && (i.isRead ?? false))
.length;
int get completedItems => items
.where((i) => i.itemType == itemType && (i.status == Status.completed))
.where((e) => e.chapters.every((element) => element.isRead ?? false))
.length;
int get downloadedItems => isar.downloads final chapters = await isar.chapters
.filter() .filter()
.idIsNotNull() .idIsNotNull()
.chapter((q) => q.manga((m) => m.itemTypeEqualTo(itemType))) .manga((q) => q.favoriteEqualTo(true).itemTypeEqualTo(itemType))
.chapter((q) => q.manga((m) => m.favoriteEqualTo(true))) .findAll();
.isDownloadEqualTo(true)
.findAllSync() final downloadedCount = await isar.downloads
.length; .filter()
.idIsNotNull()
.chapter((q) => q.manga((m) => m.itemTypeEqualTo(itemType)))
.chapter((q) => q.manga((m) => m.favoriteEqualTo(true)))
.isDownloadEqualTo(true)
.count();
final totalItems = items.length;
final totalChapters = chapters.length;
final readChapters = chapters.where((c) => c.isRead ?? false).length;
int completedItems = 0;
for (var item in items) {
if (item.status == Status.completed) {
final itemChapters = item.chapters.toList();
if (itemChapters.isNotEmpty &&
itemChapters.every((element) => element.isRead ?? false)) {
completedItems++;
}
}
}
return StatisticsData(
totalItems: totalItems,
totalChapters: totalChapters,
readChapters: readChapters,
completedItems: completedItems,
downloadedItems: downloadedCount,
);
}
} }

View file

@ -75,7 +75,8 @@ class _StatisticsScreenState extends ConsumerState<StatisticsScreen>
Widget _buildStatisticsTab({required ItemType itemType}) { Widget _buildStatisticsTab({required ItemType itemType}) {
final l10n = context.l10n; final l10n = context.l10n;
final stats = ref.watch(statisticsStateProvider(itemType).notifier); // final stats = ref.watch(statisticsStateProvider(itemType).notifier);
final stats = ref.watch(statisticsStateProvider(itemType));
final title = switch (itemType) { final title = switch (itemType) {
ItemType.manga => l10n.manga, ItemType.manga => l10n.manga,
@ -94,47 +95,52 @@ class _StatisticsScreenState extends ConsumerState<StatisticsScreen>
_ => l10n.unread, _ => l10n.unread,
}; };
final totalItems = stats.totalItems; return stats.when(
final totalChapters = stats.totalChapters; loading: () => const Center(child: CircularProgressIndicator()),
final readChapters = stats.readChapters; error: (err, stack) => Center(child: Text("Err: $err")),
final unreadChapters = totalChapters - readChapters; data: (stats) {
final completedItems = stats.completedItems; final totalItems = stats.totalItems;
final downloadedItems = stats.downloadedItems; final totalChapters = stats.totalChapters;
final readChapters = stats.readChapters;
final unreadChapters = totalChapters - readChapters;
final completedItems = stats.completedItems;
final downloadedItems = stats.downloadedItems;
final averageChapters = totalItems > 0 ? totalChapters / totalItems : 0; final averageChapters = totalItems > 0 ? totalChapters / totalItems : 0;
final readPercentage = totalChapters > 0 final readPercentage = totalChapters > 0
? (readChapters / totalChapters) * 100 ? (readChapters / totalChapters) * 100
: 0; : 0;
final completedPercentage = totalItems > 0 final completedPercentage = totalItems > 0
? (completedItems / totalItems) * 100 ? (completedItems / totalItems) * 100
: 0; : 0;
return SingleChildScrollView(
return SingleChildScrollView( padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16.0), child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.stretch,
crossAxisAlignment: CrossAxisAlignment.stretch, children: [
children: [ _buildSectionHeader('Entries'),
_buildSectionHeader('Entries'), _buildEntriesCard(
_buildEntriesCard( totalItems: totalItems,
totalItems: totalItems, completedItems: completedItems,
completedItems: completedItems, completedPercentage: completedPercentage.toDouble(),
completedPercentage: completedPercentage.toDouble(), ),
const SizedBox(height: 10),
_buildSectionHeader(chapterLabel),
_buildChaptersCard(
totalChapters: totalChapters,
readChapters: readChapters,
unreadChapters: unreadChapters,
downloadedItems: downloadedItems,
averageChapters: averageChapters.toDouble(),
readPercentage: readPercentage.toDouble(),
title: title,
context: context,
unreadLabel: unreadLabel,
),
],
), ),
const SizedBox(height: 10), );
_buildSectionHeader(chapterLabel), },
_buildChaptersCard(
totalChapters: totalChapters,
readChapters: readChapters,
unreadChapters: unreadChapters,
downloadedItems: downloadedItems,
averageChapters: averageChapters.toDouble(),
readPercentage: readPercentage.toDouble(),
title: title,
context: context,
unreadLabel: unreadLabel,
),
],
),
); );
} }