mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-05-23 20:02:15 +00:00
154 lines
4.6 KiB
Dart
154 lines
4.6 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:hive_flutter/adapters.dart';
|
|
import 'package:isar_community/isar.dart';
|
|
import 'package:mangayomi/main.dart';
|
|
import 'package:mangayomi/models/track.dart';
|
|
import 'package:mangayomi/models/track_search.dart';
|
|
import 'package:mangayomi/modules/tracker_library/tracker_library_card.dart';
|
|
import 'package:mangayomi/modules/tracker_library/tracker_library_section.dart';
|
|
import 'package:mangayomi/providers/l10n_providers.dart';
|
|
import 'package:super_sliver_list/super_sliver_list.dart';
|
|
|
|
class TrackerSectionScreen extends StatefulWidget {
|
|
final TrackLibrarySection section;
|
|
|
|
const TrackerSectionScreen({super.key, required this.section});
|
|
|
|
@override
|
|
State<TrackerSectionScreen> createState() => _TrackerSectionScreenState();
|
|
}
|
|
|
|
class _TrackerSectionScreenState extends State<TrackerSectionScreen> {
|
|
String _errorMessage = "";
|
|
bool _isLoading = true;
|
|
List<TrackSearch> _tracks = [];
|
|
late StreamSubscription<List<Track>> _trackStreamSub;
|
|
Map<int, Track> _trackIndex = {};
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fetchData();
|
|
_subscribeToTracks();
|
|
}
|
|
|
|
void _subscribeToTracks() {
|
|
_trackStreamSub = isar.tracks
|
|
.filter()
|
|
.itemTypeEqualTo(widget.section.itemType)
|
|
.mangaIdIsNotNull()
|
|
.watch(fireImmediately: true)
|
|
.listen((tracks) {
|
|
if (mounted) {
|
|
setState(() {
|
|
_trackIndex = {
|
|
for (final t in tracks)
|
|
if (t.mediaId != null) t.mediaId!: t,
|
|
};
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant TrackerSectionScreen oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.section.itemType != widget.section.itemType) {
|
|
_trackStreamSub.cancel();
|
|
_subscribeToTracks();
|
|
}
|
|
_fetchData();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_trackStreamSub.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = l10nLocalizations(context)!;
|
|
return Scaffold(
|
|
body: SizedBox(
|
|
height: 260,
|
|
child: Column(
|
|
children: [
|
|
ListTile(dense: true, title: Text(widget.section.name)),
|
|
Flexible(
|
|
child: _isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: Builder(
|
|
builder: (context) {
|
|
if (_errorMessage.isNotEmpty) {
|
|
return Center(child: Text(_errorMessage));
|
|
}
|
|
if (_tracks.isNotEmpty) {
|
|
return SuperListView.builder(
|
|
extentPrecalculationPolicy:
|
|
SuperPrecalculationPolicy(),
|
|
scrollDirection: Axis.horizontal,
|
|
itemCount: _tracks.length,
|
|
itemBuilder: (context, index) {
|
|
final track = _tracks[index];
|
|
return TrackerLibraryImageCard(
|
|
track: track,
|
|
itemType: widget.section.itemType,
|
|
libraryTrack: _trackIndex[track.mediaId],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
return Center(child: Text(l10n.no_result));
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _fetchData() async {
|
|
final box = await Hive.openBox("tracker_library");
|
|
final key =
|
|
"${widget.section.syncId}-${widget.section.itemType.name}-${widget.section.name}";
|
|
if (_checkCache(box, key)) return;
|
|
try {
|
|
_errorMessage = "";
|
|
_tracks = await widget.section.func() ?? [];
|
|
box.put(key, _tracks);
|
|
if (mounted) {
|
|
setState(() => _isLoading = false);
|
|
}
|
|
} catch (e) {
|
|
if (mounted) {
|
|
setState(() {
|
|
_errorMessage = e.toString();
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
bool _checkCache(Box<dynamic> box, String key) {
|
|
if (!widget.section.isSearch && box.containsKey(key)) {
|
|
final temp = box.get(key);
|
|
if (temp is List<TrackSearch>) {
|
|
_errorMessage = "";
|
|
_tracks = temp;
|
|
if (mounted) setState(() => _isLoading = false);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
class SuperPrecalculationPolicy extends ExtentPrecalculationPolicy {
|
|
@override
|
|
bool shouldPrecalculateExtents(ExtentPrecalculationContext context) {
|
|
return context.numberOfItems < 100;
|
|
}
|
|
}
|