mangayomi-mirror/lib/modules/tracker_library/tracker_library_card.dart
NBA2K1 98b3121c04 Move tracker lookup to parent
Replace per-card Isar tracking streams with a single subscription in
TrackerSectionScreen.

- Build a mediaId -> Track index at the screen level
- Pass resolved Track? into TrackerLibraryImageCard
- Convert TrackerLibraryImageCard to a plain StatelessWidget
- Remove StreamBuilder, ConsumerStatefulWidget, and keep-alive boilerplate
- Keep the same UI while reducing widget-level DB work

This follows the same parent-index pattern used elsewhere and makes
the tracker library view lighter and easier to maintain.
2026-04-19 01:48:59 +02:00

120 lines
4.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/track.dart';
import 'package:mangayomi/models/track_search.dart';
import 'package:mangayomi/modules/tracker_library/tracker_item_card.dart';
import 'package:mangayomi/modules/widgets/bottom_text_widget.dart';
import 'package:mangayomi/utils/cached_network.dart';
import 'package:mangayomi/utils/constant.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
class TrackerLibraryImageCard extends StatelessWidget {
final TrackSearch track;
final ItemType itemType;
final Track? libraryTrack;
const TrackerLibraryImageCard({
super.key,
required this.track,
required this.itemType,
this.libraryTrack,
});
@override
Widget build(BuildContext context) {
final hasData = libraryTrack != null;
return GestureDetector(
onTap: () => _showCard(context, libraryTrack?.mangaId),
child: Padding(
padding: const EdgeInsets.only(left: 10),
child: Stack(
children: [
SizedBox(
width: 110,
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Stack(
children: [
cachedNetworkImage(
imageUrl: toImgUrl(track.coverUrl ?? ""),
width: 110,
height: 150,
fit: BoxFit.cover,
),
Positioned(
top: 0,
right: 0,
child: Text.rich(
TextSpan(
style: TextStyle(
background: Paint()
..color = Theme.of(context)
.scaffoldBackgroundColor
.withValues(alpha: 0.75)
..strokeWidth = 20.0
..strokeJoin = StrokeJoin.round
..style = PaintingStyle.stroke,
),
children: [
WidgetSpan(
child: Icon(
Icons.star,
color: context.primaryColor,
),
),
TextSpan(
text: " ${track.score ?? "?"}",
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
],
),
),
),
],
),
),
BottomTextWidget(
fontSize: 12.0,
text: track.title!,
isLoading: true,
textColor: Theme.of(context).textTheme.bodyLarge!.color,
isComfortableGrid: true,
),
],
),
),
Container(
width: 110,
height: 150,
color: hasData ? Colors.black.withValues(alpha: 0.7) : null,
),
if (hasData)
Positioned(
top: 0,
left: 0,
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(
Icons.collections_bookmark,
color: context.primaryColor,
),
),
),
],
),
),
);
}
void _showCard(BuildContext context, int? mangaId) {
showDialog(
context: context,
builder: (context) =>
TrackerItemCard(track: track, itemType: itemType, mangaId: mangaId),
);
}
}