diff --git a/android/app/build.gradle b/android/app/build.gradle index bfe2276..a750bb5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,7 +44,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.anime_tv" - minSdkVersion 27 + minSdkVersion 25 targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/assets/cover_placeholder.jpg b/assets/cover_placeholder.jpg index 6d96037..f6b12c3 100644 Binary files a/assets/cover_placeholder.jpg and b/assets/cover_placeholder.jpg differ diff --git a/lib/api/api.dart b/lib/api/api.dart index ffa5e6b..a7496ec 100644 --- a/lib/api/api.dart +++ b/lib/api/api.dart @@ -190,9 +190,9 @@ class Api { ) .where((e) => e.url.isNotEmpty && e.cover.isNotEmpty) .toList(); - recentEpisodes.forEach((e) { - e.cover = 'https:${e.cover}'; - }); + for (var ep in recentEpisodes) { + ep.cover = 'https:${ep.cover}'; + } return recentEpisodes; } else { log('Error: Fetch request returned status code ${response.statusCode}'); diff --git a/lib/main.dart b/lib/main.dart index b61ba06..bb2093a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,7 +29,12 @@ class AnimeTV extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Anime TV', - theme: ThemeData.dark(), + theme: ThemeData.from( + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.blue, + brightness: Brightness.dark, + ), + ), initialRoute: '/', routes: { '/': (context) => const Home(), diff --git a/lib/models.dart b/lib/models.dart index c94a125..74737f6 100644 --- a/lib/models.dart +++ b/lib/models.dart @@ -1,4 +1,3 @@ -import 'dart:collection'; import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; diff --git a/lib/pages/home/favorite_shows.dart b/lib/pages/home/favorite_shows.dart index 90a5e98..aa27bb2 100644 --- a/lib/pages/home/favorite_shows.dart +++ b/lib/pages/home/favorite_shows.dart @@ -1,4 +1,3 @@ -import 'package:anime_tv/api/models.dart'; import 'package:anime_tv/models.dart'; import 'package:anime_tv/routes.dart'; import 'package:anime_tv/widgets/image_card.dart'; diff --git a/lib/widgets/app_bar.dart b/lib/widgets/app_bar.dart index cc6e4ed..516d8c3 100644 --- a/lib/widgets/app_bar.dart +++ b/lib/widgets/app_bar.dart @@ -24,7 +24,6 @@ class AnimeTVAppBar extends StatelessWidget implements PreferredSizeWidget { fit: BoxFit.fitHeight, height: 50, ), - // size: 35, ); titleWidgets.add(const SizedBox(width: 15)); } @@ -42,7 +41,7 @@ class AnimeTVAppBar extends StatelessWidget implements PreferredSizeWidget { color: borderColor ?? Theme.of(context).colorScheme.primary, ), ), - elevation: 0, + elevation: 10, backgroundColor: Theme.of(context).primaryColor, title: title, ); diff --git a/lib/widgets/better_player_custom_controls.dart b/lib/widgets/better_player_custom_controls.dart index 5d240e1..20e4d41 100644 --- a/lib/widgets/better_player_custom_controls.dart +++ b/lib/widgets/better_player_custom_controls.dart @@ -203,7 +203,6 @@ class _CustomPlayerMaterialControlsState } else { Navigator.pop(context); } - ; }), const Spacer(), if (_controlsConfiguration.enablePip) diff --git a/lib/widgets/catalogue.dart b/lib/widgets/catalogue.dart index 06ad275..27fcca6 100644 --- a/lib/widgets/catalogue.dart +++ b/lib/widgets/catalogue.dart @@ -81,6 +81,7 @@ class _CatalogueState extends State catalogue[_filteredItemsIndices[index]].title, style: const TextStyle( fontSize: 16, + color: Colors.white, ), ), ), diff --git a/lib/widgets/episode_list.dart b/lib/widgets/episode_list.dart index bda20de..83a0d75 100644 --- a/lib/widgets/episode_list.dart +++ b/lib/widgets/episode_list.dart @@ -21,8 +21,10 @@ class EpisodeList extends StatelessWidget { return PreferenceBuilder( preference: watchedUrls.preference, builder: (BuildContext context, _) { + final bool isWatched = watchedUrls.isPresent(ep.url); + final opacity = isWatched ? 0.6 : 1.0; return Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.all(5), child: SizedBox( width: double.infinity, child: ElevatedButton.icon( @@ -36,16 +38,26 @@ class EpisodeList extends StatelessWidget { arguments: ep.url, ); }, - icon: Icon(Icons.play_circle, - color: watchedUrls.isPresent(ep.url) - ? Colors.grey - : Colors.white), + icon: Opacity( + opacity: opacity, + child: const Icon( + Icons.play_circle, + color: Colors.white, + ), + ), label: Padding( padding: const EdgeInsets.all(18), - child: Text( - ep.title, - maxLines: 2, - overflow: TextOverflow.ellipsis, + child: Align( + alignment: Alignment.centerLeft, + child: Opacity( + opacity: opacity, + child: Text( + ep.title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.white), + ), + ), ), ), ), diff --git a/lib/widgets/show_description.dart b/lib/widgets/show_description.dart index b3faaa2..2581a5c 100644 --- a/lib/widgets/show_description.dart +++ b/lib/widgets/show_description.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:anime_tv/api/models.dart'; import 'package:provider/provider.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; -import 'package:anime_tv/utils.dart'; class ShowDescription extends StatefulWidget { const ShowDescription({Key? key, required this.details}) : super(key: key); @@ -33,7 +32,7 @@ class _ShowDescriptionState extends State { final episodeText = widget.details.episodeList.isEmpty ? '' - : '${widget.details.episodeList.length} Episodes'; + : 'Episodes: ${widget.details.episodeList.length}'; final controls = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -59,29 +58,9 @@ class _ShowDescriptionState extends State { ); }); }), - // IconButton( - // onPressed: () => {}, - // icon: Icon(Icons.star, color: true ? Colors.amber : null), - // ), ], ); - final genreTags = Wrap( - spacing: 8, - runSpacing: 8, - children: widget.details.genreList - .map((x) => Chip( - backgroundColor: Colors - .primaries[x.hashCode % Colors.primaries.length] - .darken(), - label: Text( - x, - style: const TextStyle(color: Colors.white), - ), - )) - .toList(), - ); - final plot = Text( widget.details.description, style: const TextStyle(fontSize: 16, height: 1.4), @@ -96,8 +75,6 @@ class _ShowDescriptionState extends State { controls, const SizedBox(height: 15), plot, - const SizedBox(height: 15), - genreTags, ], ), ); diff --git a/lib/widgets/show_detail.dart b/lib/widgets/show_detail.dart index cdf0db2..8371c1a 100644 --- a/lib/widgets/show_detail.dart +++ b/lib/widgets/show_detail.dart @@ -4,6 +4,7 @@ import 'package:anime_tv/api/api.dart'; import 'package:anime_tv/api/models.dart'; import 'package:anime_tv/widgets/episode_list.dart'; import 'package:anime_tv/widgets/show_description.dart'; +import 'package:anime_tv/utils.dart'; class ShowDetailView extends StatefulWidget { final String url; @@ -42,7 +43,7 @@ class _ShowDetailViewState extends State { builder: (context, AsyncSnapshot snapshot) { if (snapshot.hasData) { final cover = SizedBox( - height: MediaQuery.of(context).size.height / 2.0, + height: double.infinity, width: double.infinity, child: FadeInImage( image: (snapshot.data!.image.isEmpty @@ -53,6 +54,46 @@ class _ShowDetailViewState extends State { ), ); + final genreTags = Wrap( + spacing: 8, + runSpacing: 8, + children: snapshot.data!.genreList + .map( + (genre) => Chip( + visualDensity: VisualDensity.compact, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: Colors + .primaries[genre.hashCode % Colors.accents.length] + .darken(), + label: Text( + genre, + style: const TextStyle(color: Colors.white), + ), + ), + ) + .toList(), + ); + + final stack = SizedBox( + width: double.infinity, + height: MediaQuery.of(context).size.height / 2.5, + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + cover, + Container( + height: double.infinity, + width: double.infinity, + color: Colors.black12, + ), + Padding( + child: genreTags, + padding: const EdgeInsets.all(8), + ), + ], + ), + ); + return RefreshIndicator( onRefresh: onRefresh, child: ListView( @@ -60,7 +101,7 @@ class _ShowDetailViewState extends State { parent: AlwaysScrollableScrollPhysics(), ), children: [ - cover, + stack, ShowDescription(details: snapshot.data!), EpisodeList( details: snapshot.data!, diff --git a/lib/widgets/slant_gradient_container.dart b/lib/widgets/slant_gradient_container.dart index e62d685..19ac776 100644 --- a/lib/widgets/slant_gradient_container.dart +++ b/lib/widgets/slant_gradient_container.dart @@ -20,8 +20,8 @@ class SlantGradientBackgroundContainer extends StatelessWidget { end: Alignment.bottomRight, colors: colors ?? [ + Theme.of(context).scaffoldBackgroundColor.lighten(0.05), Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).scaffoldBackgroundColor.darken(), ]), ), child: child,