From cd1291a1922d2aeeffa3468c804411f8226e6cf7 Mon Sep 17 00:00:00 2001 From: "Alexander \"PapaTutuWawa" Date: Sat, 4 Feb 2023 11:58:15 +0100 Subject: [PATCH] feat(ui): Implement a generic list item --- lib/src/ui/pages/anime_list.dart | 13 +++- lib/src/ui/pages/anime_search.dart | 60 +++++-------------- .../ui/widgets/{anime.dart => list_item.dart} | 45 ++++++++------ 3 files changed, 52 insertions(+), 66 deletions(-) rename lib/src/ui/widgets/{anime.dart => list_item.dart} (75%) diff --git a/lib/src/ui/pages/anime_list.dart b/lib/src/ui/pages/anime_list.dart index fc2b218..27a6c93 100644 --- a/lib/src/ui/pages/anime_list.dart +++ b/lib/src/ui/pages/anime_list.dart @@ -3,7 +3,7 @@ import 'package:anitrack/src/data/type.dart'; import 'package:anitrack/src/ui/bloc/anime_list_bloc.dart'; import 'package:anitrack/src/ui/bloc/anime_search_bloc.dart'; import 'package:anitrack/src/ui/constants.dart'; -import 'package:anitrack/src/ui/widgets/anime.dart'; +import 'package:anitrack/src/ui/widgets/list_item.dart'; import 'package:bottom_bar/bottom_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -81,8 +81,15 @@ class AnimeListPage extends StatelessWidget { if (anime.state != state.filterState) return Container(); } - return AnimeListWidget( - data: anime, + return ListItem( + title: anime.title, + thumbnailUrl: anime.thumbnailUrl, + extra: [ + Text( + '${anime.episodesWatched}/${anime.episodesTotal ?? "???"}', + style: Theme.of(context).textTheme.titleMedium, + ), + ], onLeftSwipe: () { context.read().add( AnimeEpisodeDecrementedEvent(state.animes[index].id), diff --git a/lib/src/ui/pages/anime_search.dart b/lib/src/ui/pages/anime_search.dart index 618d58f..f8ae66e 100644 --- a/lib/src/ui/pages/anime_search.dart +++ b/lib/src/ui/pages/anime_search.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:anitrack/src/data/anime.dart'; import 'package:anitrack/src/ui/bloc/anime_search_bloc.dart'; import 'package:anitrack/src/ui/constants.dart'; -import 'package:anitrack/src/ui/widgets/anime.dart'; +import 'package:anitrack/src/ui/widgets/list_item.dart'; import 'package:anitrack/src/ui/widgets/image.dart'; class AnimeSearchPage extends StatelessWidget { @@ -54,7 +54,6 @@ class AnimeSearchPage extends StatelessWidget { else Expanded( child: ListView.builder( - //shrinkWrap: true, itemCount: state.searchResults.length, itemBuilder: (context, index) { final item = state.searchResults[index]; @@ -64,49 +63,22 @@ class AnimeSearchPage extends StatelessWidget { AnimeAddedEvent(item), ); }, - child: Padding( - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AnimeCoverImage( - url: item.thumbnailUrl, + child: ListItem( + title: item.title, + thumbnailUrl: item.thumbnailUrl, + extra: [ + Align( + alignment: Alignment.centerLeft, + child: Text( + item.description, + textAlign: TextAlign.justify, + style: Theme.of(context).textTheme.bodyMedium, + maxLines: 4, + softWrap: true, + overflow: TextOverflow.ellipsis, ), - - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Align( - alignment: Alignment.centerLeft, - child: Text( - item.title, - style: Theme.of(context).textTheme.titleLarge, - maxLines: 2, - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - ), - - Align( - alignment: Alignment.centerLeft, - child: Text( - item.description, - textAlign: TextAlign.justify, - style: Theme.of(context).textTheme.bodyMedium, - maxLines: 4, - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - ), - ], - ), + ), + ], ), ); } diff --git a/lib/src/ui/widgets/anime.dart b/lib/src/ui/widgets/list_item.dart similarity index 75% rename from lib/src/ui/widgets/anime.dart rename to lib/src/ui/widgets/list_item.dart index a94999d..9830ae6 100644 --- a/lib/src/ui/widgets/anime.dart +++ b/lib/src/ui/widgets/list_item.dart @@ -4,29 +4,37 @@ import 'package:flutter/material.dart'; import 'package:swipeable_tile/swipeable_tile.dart'; /// A widget for displaying simple data about an anime in the listview -class AnimeListWidget extends StatelessWidget { - const AnimeListWidget({ - required this.data, - required this.onLeftSwipe, - required this.onRightSwipe, +class ListItem extends StatelessWidget { + ListItem({ + required this.thumbnailUrl, + required this.title, + this.onLeftSwipe, + this.onRightSwipe, + this.extra = const [], super.key, }); - /// The anime to display - final AnimeTrackingData data; + /// URL for the cover image. + final String thumbnailUrl; - /// Callbacks for the swipe functionality - final void Function() onLeftSwipe; - final void Function() onRightSwipe; + /// The title of the item + final String title; + + /// Extra widgets. + final List extra; + + /// Callbacks for the swipe functionality. + final void Function()? onLeftSwipe; + final void Function()? onRightSwipe; @override Widget build(BuildContext context) { return SwipeableTile.swipeToTrigger( onSwiped: (direction) { if (direction == SwipeDirection.endToStart) { - onRightSwipe(); + onRightSwipe!(); } else if (direction == SwipeDirection.startToEnd) { - onLeftSwipe(); + onLeftSwipe!(); } }, // TODO(PapaTutuWawa): Fix @@ -51,7 +59,9 @@ class AnimeListWidget extends StatelessWidget { return Container(); }, color: Theme.of(context).scaffoldBackgroundColor, - direction: SwipeDirection.horizontal, + direction: onRightSwipe != null && onLeftSwipe != null ? + SwipeDirection.horizontal : + SwipeDirection.none, child: Padding( padding: const EdgeInsets.all(8), child: Row( @@ -62,7 +72,7 @@ class AnimeListWidget extends StatelessWidget { child: SizedBox( width: 100, child: Image.network( - data.thumbnailUrl, + thumbnailUrl, ), ), ), @@ -75,7 +85,7 @@ class AnimeListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - data.title, + title, textAlign: TextAlign.left, style: Theme.of(context).textTheme.titleLarge, maxLines: 2, @@ -83,10 +93,7 @@ class AnimeListWidget extends StatelessWidget { overflow: TextOverflow.ellipsis, ), - Text( - '${data.episodesWatched}/${data.episodesTotal ?? "???"}', - style: Theme.of(context).textTheme.titleMedium, - ), + ...extra, ], ), ),