From 4aa89011e3b9cb7b4e631082fa164cca7f355968 Mon Sep 17 00:00:00 2001 From: MiaoMint <44718819+MiaoMint@users.noreply.github.com> Date: Sat, 23 Sep 2023 23:26:39 +0800 Subject: [PATCH] feat: text cover (#75) * feat: text cover * fix(android): detail background error --- lib/models/extension.dart | 8 +- lib/models/extension.g.dart | 4 +- lib/models/favorite.dart | 2 +- lib/models/favorite.g.dart | 39 ++++-- lib/models/history.dart | 2 +- lib/models/history.g.dart | 39 ++++-- lib/pages/detail/controller.dart | 6 +- lib/pages/detail/view.dart | 43 +++---- .../widgets/detail_appbar_flexible_space.dart | 52 ++++---- lib/pages/home/widgets/home_resent_card.dart | 119 ++++++++++-------- lib/pages/watch/reader_controller.dart | 4 +- lib/pages/watch/view.dart | 4 +- .../widgets/reader/comic/comic_reader.dart | 4 +- .../widgets/reader/novel/novel_reader.dart | 4 +- lib/utils/color.dart | 22 ++++ lib/utils/database.dart | 2 +- lib/widgets/cover.dart | 43 +++++++ lib/widgets/extension_item_card.dart | 4 +- lib/widgets/grid_item_tile.dart | 19 ++- 19 files changed, 273 insertions(+), 147 deletions(-) create mode 100644 lib/utils/color.dart create mode 100644 lib/widgets/cover.dart diff --git a/lib/models/extension.dart b/lib/models/extension.dart index ad1382b6..5ed7d2cd 100644 --- a/lib/models/extension.dart +++ b/lib/models/extension.dart @@ -75,14 +75,14 @@ class ExtensionListItem { ExtensionListItem({ required this.title, required this.url, - required this.cover, + this.cover, this.update, this.headers, }); final String title; final String url; - final String cover; + final String? cover; final String? update; late Map? headers; @@ -98,14 +98,14 @@ class ExtensionListItem { class ExtensionDetail { ExtensionDetail({ required this.title, - required this.cover, + this.cover, this.desc, this.episodes, this.headers, }); final String title; - final String cover; + final String? cover; final String? desc; final List? episodes; late Map? headers; diff --git a/lib/models/extension.g.dart b/lib/models/extension.g.dart index 28a9b6a7..4f152d97 100644 --- a/lib/models/extension.g.dart +++ b/lib/models/extension.g.dart @@ -64,7 +64,7 @@ ExtensionListItem _$ExtensionListItemFromJson(Map json) => ExtensionListItem( title: json['title'] as String, url: json['url'] as String, - cover: json['cover'] as String, + cover: json['cover'] as String?, update: json['update'] as String?, headers: (json['headers'] as Map?)?.map( (k, e) => MapEntry(k, e as String), @@ -83,7 +83,7 @@ Map _$ExtensionListItemToJson(ExtensionListItem instance) => ExtensionDetail _$ExtensionDetailFromJson(Map json) => ExtensionDetail( title: json['title'] as String, - cover: json['cover'] as String, + cover: json['cover'] as String?, desc: json['desc'] as String?, episodes: (json['episodes'] as List?) ?.map( diff --git a/lib/models/favorite.dart b/lib/models/favorite.dart index a8e53628..a6cf6831 100644 --- a/lib/models/favorite.dart +++ b/lib/models/favorite.dart @@ -12,6 +12,6 @@ class Favorite { @Enumerated(EnumType.name) late ExtensionType type; late String title; - late String cover; + String? cover; DateTime date = DateTime.now(); } diff --git a/lib/models/favorite.g.dart b/lib/models/favorite.g.dart index f9de1c44..e5e87e54 100644 --- a/lib/models/favorite.g.dart +++ b/lib/models/favorite.g.dart @@ -88,7 +88,12 @@ int _favoriteEstimateSize( Map> allOffsets, ) { var bytesCount = offsets.last; - bytesCount += 3 + object.cover.length * 3; + { + final value = object.cover; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } bytesCount += 3 + object.package.length * 3; bytesCount += 3 + object.title.length * 3; bytesCount += 3 + object.type.name.length * 3; @@ -117,7 +122,7 @@ Favorite _favoriteDeserialize( Map> allOffsets, ) { final object = Favorite(); - object.cover = reader.readString(offsets[0]); + object.cover = reader.readStringOrNull(offsets[0]); object.date = reader.readDateTime(offsets[1]); object.id = id; object.package = reader.readString(offsets[2]); @@ -137,7 +142,7 @@ P _favoriteDeserializeProp

( ) { switch (propertyId) { case 0: - return (reader.readString(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 1: return (reader.readDateTime(offset)) as P; case 2: @@ -344,8 +349,24 @@ extension FavoriteQueryWhere on QueryBuilder { extension FavoriteQueryFilter on QueryBuilder { + QueryBuilder coverIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'cover', + )); + }); + } + + QueryBuilder coverIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'cover', + )); + }); + } + QueryBuilder coverEqualTo( - String value, { + String? value, { bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { @@ -358,7 +379,7 @@ extension FavoriteQueryFilter } QueryBuilder coverGreaterThan( - String value, { + String? value, { bool include = false, bool caseSensitive = true, }) { @@ -373,7 +394,7 @@ extension FavoriteQueryFilter } QueryBuilder coverLessThan( - String value, { + String? value, { bool include = false, bool caseSensitive = true, }) { @@ -388,8 +409,8 @@ extension FavoriteQueryFilter } QueryBuilder coverBetween( - String lower, - String upper, { + String? lower, + String? upper, { bool includeLower = true, bool includeUpper = true, bool caseSensitive = true, @@ -1319,7 +1340,7 @@ extension FavoriteQueryProperty }); } - QueryBuilder coverProperty() { + QueryBuilder coverProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'cover'); }); diff --git a/lib/models/history.dart b/lib/models/history.dart index 5a022a3a..20690f6a 100644 --- a/lib/models/history.dart +++ b/lib/models/history.dart @@ -10,7 +10,7 @@ class History { late String package; late String url; // 截图,保存封面地址 - late String cover; + String? cover; @Enumerated(EnumType.name) late ExtensionType type; // 不同线路 diff --git a/lib/models/history.g.dart b/lib/models/history.g.dart index 15477ca4..1bc506e1 100644 --- a/lib/models/history.g.dart +++ b/lib/models/history.g.dart @@ -113,7 +113,12 @@ int _historyEstimateSize( Map> allOffsets, ) { var bytesCount = offsets.last; - bytesCount += 3 + object.cover.length * 3; + { + final value = object.cover; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } bytesCount += 3 + object.episodeTitle.length * 3; bytesCount += 3 + object.package.length * 3; bytesCount += 3 + object.progress.length * 3; @@ -150,7 +155,7 @@ History _historyDeserialize( Map> allOffsets, ) { final object = History(); - object.cover = reader.readString(offsets[0]); + object.cover = reader.readStringOrNull(offsets[0]); object.date = reader.readDateTime(offsets[1]); object.episodeGroupId = reader.readLong(offsets[2]); object.episodeId = reader.readLong(offsets[3]); @@ -174,7 +179,7 @@ P _historyDeserializeProp

( ) { switch (propertyId) { case 0: - return (reader.readString(offset)) as P; + return (reader.readStringOrNull(offset)) as P; case 1: return (reader.readDateTime(offset)) as P; case 2: @@ -391,8 +396,24 @@ extension HistoryQueryWhere on QueryBuilder { extension HistoryQueryFilter on QueryBuilder { + QueryBuilder coverIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'cover', + )); + }); + } + + QueryBuilder coverIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'cover', + )); + }); + } + QueryBuilder coverEqualTo( - String value, { + String? value, { bool caseSensitive = true, }) { return QueryBuilder.apply(this, (query) { @@ -405,7 +426,7 @@ extension HistoryQueryFilter } QueryBuilder coverGreaterThan( - String value, { + String? value, { bool include = false, bool caseSensitive = true, }) { @@ -420,7 +441,7 @@ extension HistoryQueryFilter } QueryBuilder coverLessThan( - String value, { + String? value, { bool include = false, bool caseSensitive = true, }) { @@ -435,8 +456,8 @@ extension HistoryQueryFilter } QueryBuilder coverBetween( - String lower, - String upper, { + String? lower, + String? upper, { bool includeLower = true, bool includeUpper = true, bool caseSensitive = true, @@ -2020,7 +2041,7 @@ extension HistoryQueryProperty }); } - QueryBuilder coverProperty() { + QueryBuilder coverProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'cover'); }); diff --git a/lib/pages/detail/controller.dart b/lib/pages/detail/controller.dart index 59e92015..bd4fcb3b 100644 --- a/lib/pages/detail/controller.dart +++ b/lib/pages/detail/controller.dart @@ -55,12 +55,12 @@ class DetailPageController extends GetxController { TMDBDetail? get tmdbDetail => tmdb.value; set tmdbDetail(TMDBDetail? value) => tmdb.value = value; - String get backgorund { - String bg = ''; + String? get backgorund { + String? bg; if (tmdbDetail != null && tmdbDetail!.backdrop != null) { bg = TmdbApi.getImageUrl(tmdbDetail!.backdrop!) ?? ''; } else { - bg = detail?.cover ?? ''; + bg = detail?.cover; } return bg; } diff --git a/lib/pages/detail/view.dart b/lib/pages/detail/view.dart index b97e40a3..258901cf 100644 --- a/lib/pages/detail/view.dart +++ b/lib/pages/detail/view.dart @@ -17,6 +17,7 @@ import 'package:miru_app/utils/i18n.dart'; import 'package:miru_app/utils/layout.dart'; import 'package:miru_app/widgets/cache_network_image.dart'; import 'package:miru_app/widgets/card_tile.dart'; +import 'package:miru_app/widgets/cover.dart'; import 'package:miru_app/widgets/platform_widget.dart'; import 'package:miru_app/widgets/progress.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -232,11 +233,10 @@ class _DetailPageState extends State { return Stack( children: [ Animate( - child: CacheNetWorkImage( - c.backgorund, - width: double.infinity, - height: double.infinity, - headers: c.detail?.headers, + child: Cover( + alt: c.detail?.title ?? '', + url: c.backgorund, + noText: true, ), ).blur( begin: const Offset(10, 10), @@ -260,24 +260,25 @@ class _DetailPageState extends State { height: 330, child: Row( children: [ - if (constraints.maxWidth > 600) ...[ - Hero( - tag: c.heroTag ?? '', - child: Container( - width: 230, - height: double.infinity, - clipBehavior: Clip.antiAlias, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - ), - child: CacheNetWorkImage( - c.detail?.cover ?? '', - headers: c.detail?.headers, + if (c.detail!.cover != null) + if (constraints.maxWidth > 600) ...[ + Hero( + tag: c.heroTag ?? '', + child: Container( + width: 230, + height: double.infinity, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + ), + child: CacheNetWorkImage( + c.detail?.cover ?? '', + headers: c.detail?.headers, + ), ), ), - ), - const SizedBox(width: 30), - ], + const SizedBox(width: 30), + ], Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/detail/widgets/detail_appbar_flexible_space.dart b/lib/pages/detail/widgets/detail_appbar_flexible_space.dart index 7b17b33a..6ac6c2f0 100644 --- a/lib/pages/detail/widgets/detail_appbar_flexible_space.dart +++ b/lib/pages/detail/widgets/detail_appbar_flexible_space.dart @@ -5,6 +5,7 @@ import 'package:miru_app/pages/detail/widgets/detail_continue_play.dart'; import 'package:miru_app/pages/detail/widgets/detail_extension_tile.dart'; import 'package:miru_app/pages/detail/widgets/detail_favorite_button.dart'; import 'package:miru_app/widgets/cache_network_image.dart'; +import 'package:miru_app/widgets/cover.dart'; class DetailAppbarflexibleSpace extends StatefulWidget { const DetailAppbarflexibleSpace({ @@ -43,6 +44,16 @@ class _DetailAppbarflexibleSpaceState extends State { @override Widget build(BuildContext context) { + bool needShowCover() { + if (c.isLoading.value) { + return true; + } + if (c.data.value?.cover != null) { + return true; + } + return false; + } + return Obx( () => Opacity( opacity: _scrollListener(), @@ -53,12 +64,10 @@ class _DetailAppbarflexibleSpaceState extends State { width: double.infinity, child: c.isLoading.value ? const SizedBox.shrink() - : CacheNetWorkImage( - c.backgorund, - height: double.infinity, - fit: BoxFit.cover, - width: double.infinity, - headers: c.detail?.headers, + : Cover( + alt: c.data.value?.title ?? '', + url: c.backgorund, + noText: true, ), ), Positioned.fill( @@ -83,23 +92,24 @@ class _DetailAppbarflexibleSpaceState extends State { right: 20, child: Row( children: [ - Hero( - tag: c.heroTag ?? '', - child: Card( - clipBehavior: Clip.antiAlias, - child: SizedBox( - height: 150, - width: 100, - child: c.isLoading.value - ? const Center(child: CircularProgressIndicator()) - : CacheNetWorkImage( - c.data.value!.cover, - fit: BoxFit.cover, - headers: c.detail?.headers, - ), + if (needShowCover()) + Hero( + tag: c.heroTag ?? '', + child: Card( + clipBehavior: Clip.antiAlias, + child: SizedBox( + height: 150, + width: 100, + child: c.isLoading.value + ? const Center(child: CircularProgressIndicator()) + : CacheNetWorkImage( + c.data.value?.cover ?? '', + fit: BoxFit.cover, + headers: c.detail?.headers, + ), + ), ), ), - ), Expanded( child: Container( padding: const EdgeInsets.only(left: 20), diff --git a/lib/pages/home/widgets/home_resent_card.dart b/lib/pages/home/widgets/home_resent_card.dart index 68d5b16b..6f6d301d 100644 --- a/lib/pages/home/widgets/home_resent_card.dart +++ b/lib/pages/home/widgets/home_resent_card.dart @@ -10,6 +10,7 @@ import 'package:miru_app/models/history.dart'; import 'package:miru_app/pages/detail/view.dart'; import 'package:miru_app/pages/home/controller.dart'; import 'package:miru_app/router/router.dart'; +import 'package:miru_app/utils/color.dart'; import 'package:miru_app/utils/database.dart'; import 'package:miru_app/utils/extension.dart'; import 'package:miru_app/utils/extension_runtime.dart'; @@ -35,6 +36,7 @@ class _HomeRecentCardState extends State { final contextAttachKey = GlobalKey(); // 主要颜色 Color? primaryColor; + late bool noCover = widget.history.cover == null; @override void initState() { @@ -59,11 +61,11 @@ class _HomeRecentCardState extends State { } _genColor() async { - if (widget.history.type == ExtensionType.bangumi) { + if (widget.history.type == ExtensionType.bangumi || noCover) { return; } final paletteGenerator = await PaletteGenerator.fromImageProvider( - CachedNetworkImageProvider(widget.history.cover), + CachedNetworkImageProvider(widget.history.cover!), maximumColorCount: 2, ); @@ -97,7 +99,7 @@ class _HomeRecentCardState extends State { child: Stack( children: [ Image.file( - File(widget.history.cover), + File(widget.history.cover!), fit: BoxFit.cover, width: double.infinity, height: double.infinity, @@ -165,22 +167,25 @@ class _HomeRecentCardState extends State { } Widget _coverCard() { + if (widget.history.cover == null) {} + return Container( width: 350, decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(8)), - // color: - // _paletteGenerator != null ? _paletteGenerator!.colors.first : null, - image: DecorationImage( - image: CachedNetworkImageProvider(widget.history.cover), - fit: BoxFit.cover, - colorFilter: primaryColor != null - ? ColorFilter.mode( - primaryColor!.withOpacity(0.9), - BlendMode.srcOver, - ) - : null, - ), + color: noCover ? ColorUtils.getColor(widget.history.title) : null, + image: noCover + ? null + : DecorationImage( + image: CachedNetworkImageProvider(widget.history.cover!), + fit: BoxFit.cover, + colorFilter: primaryColor != null + ? ColorFilter.mode( + primaryColor!.withOpacity(0.9), + BlendMode.srcOver, + ) + : null, + ), ), clipBehavior: Clip.antiAlias, child: Container( @@ -197,52 +202,56 @@ class _HomeRecentCardState extends State { ), child: Row( children: [ - Container( - margin: const EdgeInsets.all(10), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5)), - ), - clipBehavior: Clip.antiAlias, - child: CachedNetworkImage( - imageUrl: widget.history.cover, - width: 130, - height: double.infinity, - fit: BoxFit.cover, + if (!noCover) + Container( + margin: const EdgeInsets.only(left: 10, bottom: 10, top: 10), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + clipBehavior: Clip.antiAlias, + child: CachedNetworkImage( + imageUrl: widget.history.cover!, + width: 130, + height: double.infinity, + fit: BoxFit.cover, + ), ), - ), Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - widget.history.title, - style: const TextStyle(color: Colors.white), - overflow: TextOverflow.ellipsis, - ), - Text( - FlutterI18n.translate( - context, - "home.watched", - translationParams: { - "ep": widget.history.episodeTitle, - }, - ), - style: const TextStyle( - color: Colors.white, - fontSize: 12, - ), - maxLines: 1, - ), - if (_update.isNotEmpty) ...[ - const SizedBox(height: 8), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ Text( - _update, + widget.history.title, style: const TextStyle(color: Colors.white), + overflow: TextOverflow.ellipsis, + ), + Text( + FlutterI18n.translate( + context, + "home.watched", + translationParams: { + "ep": widget.history.episodeTitle, + }, + ), + style: const TextStyle( + color: Colors.white, + fontSize: 12, + ), + maxLines: 1, ), + if (_update.isNotEmpty) ...[ + const SizedBox(height: 8), + Text( + _update, + style: const TextStyle(color: Colors.white), + ), + ], + const SizedBox(height: 16), ], - const SizedBox(height: 16), - ], + ), ), ), ], diff --git a/lib/pages/watch/reader_controller.dart b/lib/pages/watch/reader_controller.dart index db8a8dc5..aded5903 100644 --- a/lib/pages/watch/reader_controller.dart +++ b/lib/pages/watch/reader_controller.dart @@ -14,7 +14,7 @@ class ReaderController extends GetxController { final int playIndex; final int episodeGroupId; final ExtensionRuntime runtime; - final String cover; + final String? cover; ReaderController({ required this.title, @@ -23,7 +23,7 @@ class ReaderController extends GetxController { required this.playIndex, required this.episodeGroupId, required this.runtime, - required this.cover, + this.cover, }); late Rx watchData = Rx(null); diff --git a/lib/pages/watch/view.dart b/lib/pages/watch/view.dart index ce6e7895..2894ca00 100644 --- a/lib/pages/watch/view.dart +++ b/lib/pages/watch/view.dart @@ -14,7 +14,7 @@ class WatchPage extends StatelessWidget { required this.playerIndex, required this.episodeGroupId, required this.detailUrl, - required this.cover, + this.cover, }) : super(key: key); final List playList; final int playerIndex; @@ -22,7 +22,7 @@ class WatchPage extends StatelessWidget { final String package; final String detailUrl; final int episodeGroupId; - final String cover; + final String? cover; @override Widget build(BuildContext context) { diff --git a/lib/pages/watch/widgets/reader/comic/comic_reader.dart b/lib/pages/watch/widgets/reader/comic/comic_reader.dart index cfed2241..9a727847 100644 --- a/lib/pages/watch/widgets/reader/comic/comic_reader.dart +++ b/lib/pages/watch/widgets/reader/comic/comic_reader.dart @@ -17,7 +17,7 @@ class ComicReader extends StatefulWidget { required this.playerIndex, required this.episodeGroupId, required this.runtime, - required this.cover, + this.cover, }) : super(key: key); final String title; @@ -26,7 +26,7 @@ class ComicReader extends StatefulWidget { final int playerIndex; final int episodeGroupId; final ExtensionRuntime runtime; - final String cover; + final String? cover; @override State createState() => _ComicReaderState(); diff --git a/lib/pages/watch/widgets/reader/novel/novel_reader.dart b/lib/pages/watch/widgets/reader/novel/novel_reader.dart index a388b7b9..b6e6acd2 100644 --- a/lib/pages/watch/widgets/reader/novel/novel_reader.dart +++ b/lib/pages/watch/widgets/reader/novel/novel_reader.dart @@ -16,7 +16,7 @@ class NovelReader extends StatefulWidget { required this.playerIndex, required this.title, required this.detailUrl, - required this.cover, + this.cover, }) : super(key: key); final String title; @@ -25,7 +25,7 @@ class NovelReader extends StatefulWidget { final int playerIndex; final int episodeGroupId; final ExtensionRuntime runtime; - final String cover; + final String? cover; @override State createState() => _NovelReaderState(); diff --git a/lib/utils/color.dart b/lib/utils/color.dart new file mode 100644 index 00000000..a1a9afc2 --- /dev/null +++ b/lib/utils/color.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class ColorUtils { + static Color getColor(String text) { + final int colorIndex = text.length % 10; + final color = [ + Colors.blueGrey[500], + Colors.brown[500], + Colors.deepPurple[500], + Colors.green[500], + Colors.indigo[500], + Colors.lightBlue[500], + Colors.lightGreen[500], + Colors.orange[500], + Colors.pink[500], + Colors.purple[500], + Colors.red[500], + Colors.teal[500], + ][colorIndex]; + return color!; + } +} diff --git a/lib/utils/database.dart b/lib/utils/database.dart index 8cabe380..5e6b1f43 100644 --- a/lib/utils/database.dart +++ b/lib/utils/database.dart @@ -12,8 +12,8 @@ class DatabaseUtils { static toggleFavorite({ required String package, required String url, - required String cover, required String name, + String? cover, }) async { return db.writeTxn(() async { if (await isFavorite( diff --git a/lib/widgets/cover.dart b/lib/widgets/cover.dart new file mode 100644 index 00000000..e01545db --- /dev/null +++ b/lib/widgets/cover.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:miru_app/utils/color.dart'; +import 'package:miru_app/widgets/cache_network_image.dart'; + +class Cover extends StatelessWidget { + const Cover({ + Key? key, + required this.alt, + this.url, + this.noText = false, + }) : super(key: key); + final String? url; + final String alt; + final bool noText; + + @override + Widget build(BuildContext context) { + if (url != null) { + return CacheNetWorkImage( + url!, + width: double.infinity, + height: double.infinity, + ); + } + + return Container( + padding: const EdgeInsets.all(8), + color: ColorUtils.getColor(alt), + child: noText + ? const SizedBox.expand() + : Center( + child: Text( + alt, + style: const TextStyle( + color: Colors.white, + ), + overflow: TextOverflow.ellipsis, + maxLines: 6, + ), + ), + ); + } +} diff --git a/lib/widgets/extension_item_card.dart b/lib/widgets/extension_item_card.dart index aba48f19..908e605c 100644 --- a/lib/widgets/extension_item_card.dart +++ b/lib/widgets/extension_item_card.dart @@ -11,11 +11,11 @@ class ExtensionItemCard extends StatefulWidget { required this.title, required this.url, required this.package, - required this.cover, + this.cover, this.update, }) : super(key: key); final String title; - final String cover; + final String? cover; final String? update; final String url; final String package; diff --git a/lib/widgets/grid_item_tile.dart b/lib/widgets/grid_item_tile.dart index 48a0c8b7..e978ff34 100644 --- a/lib/widgets/grid_item_tile.dart +++ b/lib/widgets/grid_item_tile.dart @@ -1,17 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:miru_app/widgets/cache_network_image.dart'; +import 'package:miru_app/widgets/cover.dart'; import 'package:miru_app/widgets/platform_widget.dart'; class GridItemTile extends StatefulWidget { const GridItemTile({ Key? key, required this.title, - required this.cover, + this.cover, this.subtitle, this.onTap, }) : super(key: key); final String title; - final String cover; + final String? cover; final String? subtitle; final Function()? onTap; @@ -30,10 +30,9 @@ class _GridItemTileState extends State { borderRadius: BorderRadius.all(Radius.circular(8)), ), clipBehavior: Clip.antiAlias, - child: CacheNetWorkImage( - widget.cover, - width: double.infinity, - height: double.infinity, + child: Cover( + alt: widget.title, + url: widget.cover, ), ), Positioned( @@ -132,9 +131,9 @@ class _GridItemTileState extends State { child: AnimatedScale( scale: _isHover ? 1.05 : 1, duration: const Duration(milliseconds: 80), - child: CacheNetWorkImage( - widget.cover, - width: double.infinity, + child: Cover( + alt: widget.title, + url: widget.cover, ), )), ),