From 8563f24140151e54ac9b91884d0535c5d29ace7d Mon Sep 17 00:00:00 2001 From: stonegate Date: Sun, 16 Aug 2020 01:43:45 +0800 Subject: [PATCH] Minor change. --- assets/avatar_backup.png | Bin 0 -> 13280 bytes lib/episodes/episode_detail.dart | 62 +---- lib/home/audioplayer.dart | 119 +++------ lib/home/download_list.dart | 4 +- lib/home/home.dart | 41 ++- lib/home/home_groups.dart | 33 +-- lib/home/playlist.dart | 63 ++--- lib/local_storage/sqflite_localpodcast.dart | 13 + lib/podcasts/podcast_group.dart | 4 +- lib/settings/downloads_manage.dart | 6 +- lib/settings/layouts.dart | 6 +- lib/settings/play_setting.dart | 4 +- lib/settings/storage.dart | 10 +- lib/settings/syncing.dart | 2 +- lib/settings/theme.dart | 18 +- lib/type/episodebrief.dart | 27 ++ lib/type/podcastlocal.dart | 17 ++ lib/util/audiopanel.dart | 4 + lib/util/custom_dropdown.dart | 1 + lib/util/custom_time_picker.dart | 280 +++++++++----------- lib/util/custom_widget.dart | 25 +- lib/util/episodegrid.dart | 22 +- lib/util/extension_helper.dart | 18 +- 23 files changed, 347 insertions(+), 432 deletions(-) create mode 100644 assets/avatar_backup.png diff --git a/assets/avatar_backup.png b/assets/avatar_backup.png new file mode 100644 index 0000000000000000000000000000000000000000..a18c36082a75cb533d09188d070084093d293245 GIT binary patch literal 13280 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 Bs*(Tz literal 0 HcmV?d00001 diff --git a/lib/episodes/episode_detail.dart b/lib/episodes/episode_detail.dart index 128b09c..aa1f94a 100644 --- a/lib/episodes/episode_detail.dart +++ b/lib/episodes/episode_detail.dart @@ -41,42 +41,8 @@ class _EpisodeDetailState extends State { /// Show page title. bool _showTitle; - - /// Load shownote. - bool _loaddes; bool _showMenu; String path; - String _description; - - Future _getSDescription(String url) async { - var dbHelper = DBHelper(); - _description = (await dbHelper.getDescription(url)) - .replaceAll(RegExp(r'\s?

(
)?

\s?'), '') - .replaceAll('\r', '') - .trim(); - if (!_description.contains('<')) { - final linkList = linkify(_description, - options: LinkifyOptions(humanize: false), - linkifiers: [UrlLinkifier(), EmailLinkifier()]); - for (var element in linkList) { - if (element is UrlElement) { - _description = _description.replaceAll(element.url, - '${element.text}'); - } - if (element is EmailElement) { - final address = element.emailAddress; - _description = _description.replaceAll(address, - '$address'); - } - } - } - - if (mounted) { - setState(() { - _loaddes = true; - }); - } - } Future _getPosition(EpisodeBrief episode) async { var dbHelper = DBHelper(); @@ -104,33 +70,9 @@ class _EpisodeDetailState extends State { } else if (_showTitle) setState(() => _showTitle = false); } - _markListened(EpisodeBrief episode) async { - var dbHelper = DBHelper(); - var marked = await dbHelper.checkMarked(episode); - if (!marked) { - final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1); - await dbHelper.saveHistory(history); - } - } - - int _getTimeStamp(String url) { - final time = url.substring(7); - final data = time.split(':'); - var seconds; - if (data.length == 3) { - seconds = int.tryParse(data[0]) * 3600 + - int.tryParse(data[1]) * 60 + - int.tryParse(data[2]); - } else if (data.length == 2) { - seconds = int.tryParse(data[0]) * 60 + int.tryParse(data[1]); - } - return seconds; - } - @override void initState() { super.initState(); - _loaddes = false; _showMenu = true; _showTitle = false; //_getSDescription(widget.episodeItem.enclosureUrl); @@ -569,8 +511,8 @@ class __MenuBarState extends State<_MenuBar> { ? Center() : CircleAvatar( radius: 15, - backgroundImage: FileImage( - File("${widget.episodeItem.imagePath}"))), + backgroundImage: + widget.episodeItem.avatarImage), ), ), ), diff --git a/lib/home/audioplayer.dart b/lib/home/audioplayer.dart index fe66abd..100cc85 100644 --- a/lib/home/audioplayer.dart +++ b/lib/home/audioplayer.dart @@ -59,7 +59,7 @@ class PlayerWidget extends StatelessWidget { selector: (_, audio) => Tuple2(audio.episode?.primaryColor, audio.seekSliderValue), builder: (_, data, __) { - var c = context.brightness == Brightness.light + final c = context.brightness == Brightness.light ? data.item1.colorizedark() : data.item1.colorizeLight(); return SizedBox( @@ -127,9 +127,10 @@ class PlayerWidget extends StatelessWidget { ), Expanded( flex: 2, - child: Selector>( + child: Selector>( selector: (_, audio) => - Tuple2(audio.buffering, audio.playing), + Tuple3(audio.buffering, audio.playing, audio.episode), builder: (_, data, __) { return Row( mainAxisAlignment: MainAxisAlignment.center, @@ -142,12 +143,15 @@ class PlayerWidget extends StatelessWidget { padding: const EdgeInsets.symmetric( vertical: 10.0), child: SizedBox( - height: 30.0, - width: 30.0, - child: CircleAvatar( - backgroundImage: FileImage(File( - "${audio.episode.imagePath}")), - )), + height: 30.0, + width: 30.0, + child: CircleAvatar( + backgroundColor: data.item3 + .backgroudColor(context), + backgroundImage: + data.item3.avatarImage, + ), + ), ), Container( height: 40.0, @@ -161,9 +165,8 @@ class PlayerWidget extends StatelessWidget { onTap: data.item2 ? () => audio.pauseAduio() : null, - child: ImageRotate( - title: audio.episode?.title, - path: audio.episode?.imagePath), + child: + ImageRotate(episodeItem: data.item3), ) : InkWell( onTap: data.item2 @@ -176,12 +179,15 @@ class PlayerWidget extends StatelessWidget { padding: EdgeInsets.symmetric( vertical: 10.0), child: SizedBox( - height: 30.0, - width: 30.0, - child: CircleAvatar( - backgroundImage: FileImage(File( - "${audio.episode.imagePath}")), - )), + height: 30.0, + width: 30.0, + child: CircleAvatar( + backgroundColor: data.item3 + .backgroudColor(context), + backgroundImage: + data.item3.avatarImage, + ), + ), ), Container( height: 40.0, @@ -384,71 +390,6 @@ class LastPosition extends StatelessWidget { } } -class ImageRotate extends StatefulWidget { - final String title; - final String path; - ImageRotate({this.title, this.path, Key key}) : super(key: key); - @override - _ImageRotateState createState() => _ImageRotateState(); -} - -class _ImageRotateState extends State - with SingleTickerProviderStateMixin { - Animation _animation; - AnimationController _controller; - double _value; - @override - void initState() { - super.initState(); - _value = 0; - _controller = AnimationController( - vsync: this, - duration: Duration(milliseconds: 2000), - ); - _animation = Tween(begin: 0.0, end: 1.0).animate(_controller) - ..addListener(() { - if (mounted) { - setState(() { - _value = _animation.value; - }); - } - }); - _controller.forward(); - _controller.addStatusListener((status) { - if (status == AnimationStatus.completed) { - _controller.reset(); - } else if (status == AnimationStatus.dismissed) { - _controller.forward(); - } - }); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Transform.rotate( - angle: 2 * math.pi * _value, - child: Container( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(15.0)), - child: Container( - height: 30.0, - width: 30.0, - color: Colors.white, - child: Image.file(File("${widget.path}")), - ), - ), - ), - ); - } -} - class PlaylistWidget extends StatefulWidget { const PlaylistWidget({Key key}) : super(key: key); @@ -500,7 +441,6 @@ class _PlaylistWidgetState extends State { miniPlaylistKey.currentState.removeItem( index, (context, animation) => Center()); - miniPlaylistKey.currentState.insertItem(0); }, child: Container( height: 60, @@ -586,7 +526,7 @@ class _PlaylistWidgetState extends State { ), ], ), - Divider(height: 2), + Divider(height: 1), ], ), ), @@ -638,7 +578,10 @@ class _PlaylistWidgetState extends State { onTap: () { Navigator.push( context, - SlideLeftRoute(page: PlaylistPage()), + SlideLeftRoute( + page: PlaylistPage( + initPage: InitPage.playlist, + )), ); }, child: SizedBox( @@ -1382,8 +1325,8 @@ class _ControlPanelState extends State height: 30.0, width: 30.0, child: CircleAvatar( - backgroundImage: FileImage(File( - "${data.item1.imagePath}")), + backgroundImage: + data.item1.avatarImage, ), ), SizedBox(width: 5), diff --git a/lib/home/download_list.dart b/lib/home/download_list.dart index 760ea1e..3217fd7 100644 --- a/lib/home/download_list.dart +++ b/lib/home/download_list.dart @@ -118,9 +118,7 @@ class _DownloadListState extends State { ), ), leading: CircleAvatar( - backgroundImage: FileImage( - File("${tasks[index].episode.imagePath}")), - ), + backgroundImage: tasks[index].episode.avatarImage), trailing: _downloadButton(tasks[index], context), ); }, diff --git a/lib/home/home.dart b/lib/home/home.dart index 3186779..d4bc94e 100644 --- a/lib/home/home.dart +++ b/lib/home/home.dart @@ -614,10 +614,9 @@ class PlaylistButtonState extends State { alignment: Alignment.center, children: [ CircleAvatar( - radius: 20, - backgroundImage: FileImage(File( - "${data.item2.playlist.first.imagePath}")), - ), + radius: 20, + backgroundImage: data + .item2.playlist.first.avatarImage), Container( height: 40.0, width: 40.0, @@ -678,12 +677,42 @@ class PlaylistButtonState extends State { ), ), ), + PopupMenuItem( + value: 2, + child: Container( + padding: EdgeInsets.only(left: 10), + child: Row( + children: [ + Icon(Icons.history), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 5.0), + ), + Text(s.settingsHistory), + ], + ), + ), + ), ], onSelected: (value) { if (value == 0) { Navigator.push( - context, MaterialPageRoute(builder: (context) => PlaylistPage())); - } else if (value == 1) {} + context, + MaterialPageRoute( + builder: (context) => PlaylistPage( + initPage: InitPage.playlist, + ), + ), + ); + } else if (value == 2) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PlaylistPage( + initPage: InitPage.history, + ), + ), + ); + } }, ); } diff --git a/lib/home/home_groups.dart b/lib/home/home_groups.dart index 7adad2d..a8f8eac 100644 --- a/lib/home/home_groups.dart +++ b/lib/home/home_groups.dart @@ -314,12 +314,8 @@ class _ScrollPodcastsState extends State { tabs: groups[_groupIndex] .podcasts .map((podcastLocal) { - var color = (Theme.of(context).brightness == - Brightness.light) - ? podcastLocal.primaryColor - .colorizedark() - : podcastLocal.primaryColor - .colorizeLight(); + final color = + podcastLocal.backgroudColor(context); return Tab( child: ClipRRect( borderRadius: BorderRadius.all( @@ -331,11 +327,10 @@ class _ScrollPodcastsState extends State { maxHeight: 50, maxWidth: 50, child: CircleAvatar( - backgroundColor: - color.withOpacity(0.5), - backgroundImage: FileImage(File( - "${podcastLocal.imagePath}")), - ), + backgroundColor: + color.withOpacity(0.5), + backgroundImage: + podcastLocal.avatarImage), ), FutureBuilder( future: getPodcastUpdateCounts( @@ -418,9 +413,7 @@ class PodcastPreview extends StatelessWidget { @override Widget build(BuildContext context) { - var _c = (Theme.of(context).brightness == Brightness.light) - ? podcastLocal.primaryColor.colorizedark() - : podcastLocal.primaryColor.colorizeLight(); + final c = podcastLocal.backgroudColor(context); return Column( children: [ Expanded( @@ -454,7 +447,7 @@ class PodcastPreview extends StatelessWidget { child: Text(podcastLocal.title, maxLines: 1, overflow: TextOverflow.visible, - style: TextStyle(fontWeight: FontWeight.bold, color: _c)), + style: TextStyle(fontWeight: FontWeight.bold, color: c)), ), Expanded( flex: 1, @@ -595,9 +588,7 @@ class ShowEpisode extends StatelessWidget { ), delegate: SliverChildBuilderDelegate( (context, index) { - var _c = (Theme.of(context).brightness == Brightness.light) - ? podcastLocal.primaryColor.colorizedark() - : podcastLocal.primaryColor.colorizeLight(); + final c = podcastLocal.backgroudColor(context); return Selector>>( selector: (_, audio) => Tuple2( @@ -809,8 +800,8 @@ class ShowEpisode extends StatelessWidget { height: _width / 18, width: _width / 18, child: CircleAvatar( - backgroundImage: FileImage(File( - "${podcastLocal.imagePath}")), + backgroundImage: + podcastLocal.avatarImage, ), ), ), @@ -882,7 +873,7 @@ class ShowEpisode extends StatelessWidget { overflow: TextOverflow.visible, style: TextStyle( fontSize: _width / 35, - color: _c, + color: c, fontStyle: FontStyle.italic, ), ), diff --git a/lib/home/playlist.dart b/lib/home/playlist.dart index a7b7d1c..ed6f597 100644 --- a/lib/home/playlist.dart +++ b/lib/home/playlist.dart @@ -16,7 +16,11 @@ import '../type/playlist.dart'; import '../util/custom_widget.dart'; import '../util/extension_helper.dart'; +enum InitPage { playlist, history } + class PlaylistPage extends StatefulWidget { + final InitPage initPage; + PlaylistPage({this.initPage, Key key}) : super(key: key); @override _PlaylistPageState createState() => _PlaylistPageState(); } @@ -47,7 +51,12 @@ class _PlaylistPageState extends State { @override void initState() { super.initState(); - _loadList = _ReorderablePlaylist(); + if (widget.initPage == InitPage.playlist) { + _loadList = _ReorderablePlaylist(); + } else { + _loadHistory = true; + _loadList = _HistoryList(); + } } @override @@ -213,41 +222,15 @@ class _PlaylistPageState extends State { ) : BoxDecoration(color: Colors.transparent), child: data.item2 - // ? _topHeight < 90 - // ? Row( - // mainAxisAlignment: - // MainAxisAlignment.center, - // crossAxisAlignment: - // CrossAxisAlignment.center, - // children: [ - // CircleAvatar( - // radius: 12, - // backgroundImage: FileImage(File( - // "${episodes.first.imagePath}")), - // ), - // Padding( - // padding: EdgeInsets.symmetric( - // horizontal: 15), - // child: SizedBox( - // width: 20, - // height: 15, - // child: WaveLoader( - // color: context.accentColor, - // )), - // ), - // ], - // ) ? Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ CircleAvatar( - radius: 15, - //backgroundColor: _c.withOpacity(0.5), - backgroundImage: FileImage( - File("${data.item4.imagePath}")), - ), + radius: 15, + backgroundImage: + data.item4.avatarImage), Container( width: 150, alignment: Alignment.center, @@ -380,11 +363,9 @@ class __DismissibleContainerState extends State<_DismissibleContainer> { @override Widget build(BuildContext context) { - var audio = Provider.of(context, listen: false); + final audio = Provider.of(context, listen: false); final s = context.s; - var c = (Theme.of(context).brightness == Brightness.light) - ? widget.episode.primaryColor.colorizedark() - : widget.episode.primaryColor.colorizeLight(); + final c = widget.episode.backgroudColor(context); return AnimatedContainer( duration: Duration(milliseconds: 300), alignment: Alignment.center, @@ -475,10 +456,8 @@ class __DismissibleContainerState extends State<_DismissibleContainer> { children: [ Icon(Icons.unfold_more, color: c), CircleAvatar( - backgroundColor: c.withOpacity(0.5), - backgroundImage: - FileImage(File(widget.episode.imagePath)), - ), + backgroundColor: c.withOpacity(0.5), + backgroundImage: widget.episode.avatarImage), ], ), subtitle: Container( @@ -595,10 +574,8 @@ class __HistoryListState extends State<_HistoryList> { EdgeInsets.fromLTRB(24, 8, 20, 8), onTap: () => audio.episodeLoad(episode), leading: CircleAvatar( - backgroundColor: c.withOpacity(0.5), - backgroundImage: - FileImage(File(episode.imagePath)), - ), + backgroundColor: c.withOpacity(0.5), + backgroundImage: episode.avatarImage), title: Padding( padding: EdgeInsets.symmetric(vertical: 5.0), @@ -741,7 +718,7 @@ class __HistoryListState extends State<_HistoryList> { ), ), ), - Divider(height: 2) + Divider(height: 1) ], ), ); diff --git a/lib/local_storage/sqflite_localpodcast.dart b/lib/local_storage/sqflite_localpodcast.dart index f41358f..d147dfb 100644 --- a/lib/local_storage/sqflite_localpodcast.dart +++ b/lib/local_storage/sqflite_localpodcast.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:developer' as developer; +import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; @@ -1170,6 +1171,12 @@ class DBHelper { list.first['is_new'], mediaId: list.first['media_id'], skipSeconds: list.first['skip_seconds']); + if (episode.enclosureUrl != episode.mediaId && + !File(episode.mediaId.substring(7)).existsSync()) { + final url = episode.enclosureUrl; + await delDownloaded(url); + episode = episode.copyWith(mediaId: url); + } return episode; } } @@ -1198,6 +1205,12 @@ class DBHelper { list.first['is_new'], mediaId: list.first['media_id'], skipSeconds: list.first['skip_seconds']); + if (episode.enclosureUrl != episode.mediaId && + !File(episode.mediaId.substring(7)).existsSync()) { + final url = episode.enclosureUrl; + await delDownloaded(url); + episode = episode.copyWith(mediaId: url); + } return episode; } } diff --git a/lib/podcasts/podcast_group.dart b/lib/podcasts/podcast_group.dart index 9110ede..d26af7b 100644 --- a/lib/podcasts/podcast_group.dart +++ b/lib/podcasts/podcast_group.dart @@ -161,9 +161,7 @@ class __PodcastCardState extends State<_PodcastCard> @override Widget build(BuildContext context) { - final c = (Theme.of(context).brightness == Brightness.light) - ? widget.podcastLocal.primaryColor.colorizedark() - : widget.podcastLocal.primaryColor.colorizeLight(); + final c = widget.podcastLocal.backgroudColor(context); final s = context.s; var width = context.width; var groupList = context.watch(); diff --git a/lib/settings/downloads_manage.dart b/lib/settings/downloads_manage.dart index e844898..e3a58ad 100644 --- a/lib/settings/downloads_manage.dart +++ b/lib/settings/downloads_manage.dart @@ -320,9 +320,9 @@ class _DownloadsManageState extends State { } }, leading: CircleAvatar( - backgroundImage: FileImage(File( - "${_episodes[index].imagePath}")), - ), + backgroundImage: + _episodes[index] + .avatarImage), title: Text( _episodes[index].title, maxLines: 1, diff --git a/lib/settings/layouts.dart b/lib/settings/layouts.dart index 24b4bc5..2ea76e4 100644 --- a/lib/settings/layouts.dart +++ b/lib/settings/layouts.dart @@ -190,7 +190,7 @@ class _LayoutSettingState extends State { title: Text(s.settingsPopupMenu), subtitle: Text(s.settingsPopupMenuDes), ), - Divider(height: 2), + Divider(height: 1), Padding( padding: EdgeInsets.all(10.0), ), @@ -226,7 +226,7 @@ class _LayoutSettingState extends State { audio.setPlayerHeight = PlayerHeight.values[index]), ), ), - Divider(height: 2), + Divider(height: 1), Padding( padding: EdgeInsets.all(10.0), ), @@ -258,7 +258,7 @@ class _LayoutSettingState extends State { text: s.settingsDefaultGridDownload, key: downloadLayoutKey), ]), - Divider(height: 2), + Divider(height: 1), ], ), )), diff --git a/lib/settings/play_setting.dart b/lib/settings/play_setting.dart index f43d0ef..f9fcd54 100644 --- a/lib/settings/play_setting.dart +++ b/lib/settings/play_setting.dart @@ -247,7 +247,7 @@ class PlaySetting extends StatelessWidget { ), ), ), - Divider(height: 2), + Divider(height: 1), ], ), Padding( @@ -415,7 +415,7 @@ class PlaySetting extends StatelessWidget { trailing: context.width > 360 ? _scheduleWidget(context) : null), - Divider(height: 2) + Divider(height: 1) ], ), SizedBox(height: 20) diff --git a/lib/settings/storage.dart b/lib/settings/storage.dart index 6c9bacd..2b2a4e7 100644 --- a/lib/settings/storage.dart +++ b/lib/settings/storage.dart @@ -145,7 +145,7 @@ class _StorageSettingState extends State ); }, ), - Divider(height: 2), + Divider(height: 1), FutureBuilder( future: _getAutoDownloadNetwork(), initialData: false, @@ -172,7 +172,7 @@ class _StorageSettingState extends State ), ); }), - Divider(height: 2), + Divider(height: 1), ], ), ]), @@ -207,7 +207,7 @@ class _StorageSettingState extends State title: Text(s.download), subtitle: Text(s.settingsManageDownloadDes), ), - Divider(height: 2), + Divider(height: 1), FutureBuilder( future: _getAutoDeleteDays(), initialData: 30, @@ -238,7 +238,7 @@ class _StorageSettingState extends State ); }, ), - Divider(height: 2), + Divider(height: 1), ListTile( contentPadding: EdgeInsets.only(left: 70.0, right: 25), // leading: Icon(Icons.colorize), @@ -281,7 +281,7 @@ class _StorageSettingState extends State }), ), ), - Divider(height: 2), + Divider(height: 1), ], ), ], diff --git a/lib/settings/syncing.dart b/lib/settings/syncing.dart index 82b99ce..5a3ccdf 100644 --- a/lib/settings/syncing.dart +++ b/lib/settings/syncing.dart @@ -110,7 +110,7 @@ class SyncingSetting extends StatelessWidget { value: e, child: Text(s.hoursCount(e))); }).toList()), ), - Divider(height: 2), + Divider(height: 1), ], ), ], diff --git a/lib/settings/theme.dart b/lib/settings/theme.dart index e725939..7f51d92 100644 --- a/lib/settings/theme.dart +++ b/lib/settings/theme.dart @@ -168,7 +168,7 @@ class ThemeSetting extends StatelessWidget { fontWeight: FontWeight.bold, color: context.accentColor)) ])), - content: ColorPicker( + content: _ColorPicker( onColorChanged: (value) => settings.setAccentColor = value, ), @@ -183,7 +183,7 @@ class ThemeSetting extends StatelessWidget { shape: BoxShape.circle, color: context.accentColor), ), ), - Divider(height: 2), + Divider(height: 1), ], ), ], @@ -193,14 +193,14 @@ class ThemeSetting extends StatelessWidget { } } -class ColorPicker extends StatefulWidget { +class _ColorPicker extends StatefulWidget { final ValueChanged onColorChanged; - ColorPicker({Key key, this.onColorChanged}) : super(key: key); + _ColorPicker({Key key, this.onColorChanged}) : super(key: key); @override - _ColorPickerState createState() => _ColorPickerState(); + __ColorPickerState createState() => __ColorPickerState(); } -class _ColorPickerState extends State +class __ColorPickerState extends State<_ColorPicker> with SingleTickerProviderStateMixin { TabController _controller; int _index; @@ -284,9 +284,9 @@ class _ColorPickerState extends State behavior: NoGrowBehavior(), child: GridView.count( primary: false, - padding: const EdgeInsets.all(10), - crossAxisSpacing: 10, - mainAxisSpacing: 10, + padding: const EdgeInsets.fromLTRB(2, 10, 2, 10), + crossAxisSpacing: 4, + mainAxisSpacing: 4, crossAxisCount: 3, children: [ _colorCircle(color.shade100), diff --git a/lib/type/episodebrief.dart b/lib/type/episodebrief.dart index 31a7a61..f72f6bd 100644 --- a/lib/type/episodebrief.dart +++ b/lib/type/episodebrief.dart @@ -1,6 +1,10 @@ +import 'dart:io'; + import 'package:equatable/equatable.dart'; import 'package:audio_service/audio_service.dart'; +import 'package:flutter/material.dart'; +import '../util/extension_helper.dart'; class EpisodeBrief extends Equatable { final String title; @@ -49,6 +53,29 @@ class EpisodeBrief extends Equatable { extras: {'skip': skipSeconds}); } + ImageProvider get avatarImage { + return File(imagePath).existsSync() + ? FileImage(File(imagePath)) + : const AssetImage('assets/avatar_backup.png'); + } + + Color backgroudColor(BuildContext context) { + return context.brightness == Brightness.light + ? primaryColor.colorizedark() + : primaryColor.colorizeLight(); + } + + EpisodeBrief copyWith({ + String mediaId, + }) => + EpisodeBrief(title, enclosureUrl, enclosureLength, pubDate, feedTitle, + primaryColor, duration, explicit, imagePath, isNew, + mediaId: mediaId ?? this.mediaId, + downloaded: downloaded, + skipSeconds: skipSeconds, + description: description, + downloadDate: downloadDate); + @override List get props => [enclosureUrl, title]; } diff --git a/lib/type/podcastlocal.dart b/lib/type/podcastlocal.dart index b2b56c4..d07ed31 100644 --- a/lib/type/podcastlocal.dart +++ b/lib/type/podcastlocal.dart @@ -1,4 +1,9 @@ +import 'dart:io'; + import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; + +import '../util/extension_helper.dart'; class PodcastLocal extends Equatable { final String title; @@ -29,6 +34,18 @@ class PodcastLocal extends Equatable { _episodeCount = episodeCount ?? 0, _upateCount = upateCount ?? 0; + ImageProvider get avatarImage { + return File(imagePath).existsSync() + ? FileImage(File(imagePath)) + : const AssetImage('assets/avatar_backup.png'); + } + + Color backgroudColor(BuildContext context) { + return context.brightness == Brightness.light + ? primaryColor.colorizedark() + : primaryColor.colorizeLight(); + } + @override List get props => [id, rssUrl]; } diff --git a/lib/util/audiopanel.dart b/lib/util/audiopanel.dart index fbd3bc6..a00ae1c 100644 --- a/lib/util/audiopanel.dart +++ b/lib/util/audiopanel.dart @@ -122,6 +122,10 @@ class AudioPanelState extends State with TickerProviderStateMixin { : Container( decoration: BoxDecoration( color: context.primaryColor, + // borderRadius: BorderRadius.only( + // topLeft: Radius.circular(20.0), + // topRight: Radius.circular(20.0)), + boxShadow: [ BoxShadow( offset: Offset(0, -1), diff --git a/lib/util/custom_dropdown.dart b/lib/util/custom_dropdown.dart index 553746f..bd28ac0 100644 --- a/lib/util/custom_dropdown.dart +++ b/lib/util/custom_dropdown.dart @@ -1113,6 +1113,7 @@ class MyDropdownButton extends StatefulWidget { class _MyDropdownButtonState extends State> // ignore: prefer_mixin with + // ignore: prefer_mixin WidgetsBindingObserver { int _selectedIndex; _DropdownRoute _dropdownRoute; diff --git a/lib/util/custom_time_picker.dart b/lib/util/custom_time_picker.dart index eb8aec3..cfe84ba 100644 --- a/lib/util/custom_time_picker.dart +++ b/lib/util/custom_time_picker.dart @@ -105,14 +105,12 @@ class _TimePickerHeader extends StatelessWidget { @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - final ThemeData themeData = Theme.of(context); - final TimeOfDayFormat timeOfDayFormat = - MaterialLocalizations.of(context).timeOfDayFormat( + final themeData = Theme.of(context); + final timeOfDayFormat = MaterialLocalizations.of(context).timeOfDayFormat( alwaysUse24HourFormat: MediaQuery.of(context).alwaysUse24HourFormat, ); - final _TimePickerFragmentContext fragmentContext = - _TimePickerFragmentContext( + final fragmentContext = _TimePickerFragmentContext( selectedTime: selectedTime, mode: mode, onTimeChange: onChanged, @@ -241,26 +239,26 @@ class _HourMinuteControl extends StatelessWidget { @override Widget build(BuildContext context) { - final ThemeData themeData = Theme.of(context); - final TimePickerThemeData timePickerTheme = TimePickerTheme.of(context); - final bool isDark = themeData.colorScheme.brightness == Brightness.dark; - final Color textColor = timePickerTheme.hourMinuteTextColor ?? - MaterialStateColor.resolveWith((Set states) { + final themeData = Theme.of(context); + final timePickerTheme = TimePickerTheme.of(context); + final isDark = themeData.colorScheme.brightness == Brightness.dark; + final textColor = timePickerTheme.hourMinuteTextColor ?? + MaterialStateColor.resolveWith((states) { return states.contains(MaterialState.selected) ? themeData.accentColor : themeData.colorScheme.onSurface; }); - final Color backgroundColor = timePickerTheme.hourMinuteColor ?? - MaterialStateColor.resolveWith((Set states) { + final backgroundColor = timePickerTheme.hourMinuteColor ?? + MaterialStateColor.resolveWith((states) { return states.contains(MaterialState.selected) ? themeData.accentColor.withOpacity(isDark ? 0.24 : 0.12) : themeData.colorScheme.onSurface.withOpacity(0.12); }); - final TextStyle style = + final style = timePickerTheme.hourMinuteTextStyle ?? themeData.textTheme.headline2; - final ShapeBorder shape = timePickerTheme.hourMinuteShape ?? _kDefaultShape; + final shape = timePickerTheme.hourMinuteShape ?? _kDefaultShape; - final Set states = isSelected + final states = isSelected ? {MaterialState.selected} : {}; return Container( @@ -298,38 +296,36 @@ class _HourControl extends StatelessWidget { @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - final bool alwaysUse24HourFormat = - MediaQuery.of(context).alwaysUse24HourFormat; - final MaterialLocalizations localizations = - MaterialLocalizations.of(context); - final String formattedHour = localizations.formatHour( + final alwaysUse24HourFormat = MediaQuery.of(context).alwaysUse24HourFormat; + final localizations = MaterialLocalizations.of(context); + final formattedHour = localizations.formatHour( fragmentContext.selectedTime, alwaysUse24HourFormat: alwaysUse24HourFormat, ); TimeOfDay hoursFromSelected(int hoursToAdd) { if (fragmentContext.use24HourDials) { - final int selectedHour = fragmentContext.selectedTime.hour; + final selectedHour = fragmentContext.selectedTime.hour; return fragmentContext.selectedTime.replacing( hour: (selectedHour + hoursToAdd) % TimeOfDay.hoursPerDay, ); } else { // Cycle 1 through 12 without changing day period. - final int periodOffset = fragmentContext.selectedTime.periodOffset; - final int hours = fragmentContext.selectedTime.hourOfPeriod; + final periodOffset = fragmentContext.selectedTime.periodOffset; + final hours = fragmentContext.selectedTime.hourOfPeriod; return fragmentContext.selectedTime.replacing( hour: periodOffset + (hours + hoursToAdd) % TimeOfDay.hoursPerPeriod, ); } } - final TimeOfDay nextHour = hoursFromSelected(1); - final String formattedNextHour = localizations.formatHour( + final nextHour = hoursFromSelected(1); + final formattedNextHour = localizations.formatHour( nextHour, alwaysUse24HourFormat: alwaysUse24HourFormat, ); - final TimeOfDay previousHour = hoursFromSelected(-1); - final String formattedPreviousHour = localizations.formatHour( + final previousHour = hoursFromSelected(-1); + final formattedPreviousHour = localizations.formatHour( previousHour, alwaysUse24HourFormat: alwaysUse24HourFormat, ); @@ -381,11 +377,11 @@ class _StringFragment extends StatelessWidget { @override Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); - final TimePickerThemeData timePickerTheme = TimePickerTheme.of(context); - final TextStyle hourMinuteStyle = + final theme = Theme.of(context); + final timePickerTheme = TimePickerTheme.of(context); + final hourMinuteStyle = timePickerTheme.hourMinuteTextStyle ?? theme.textTheme.headline2; - final Color textColor = + final textColor = timePickerTheme.hourMinuteTextColor ?? theme.colorScheme.onSurface; return ExcludeSemantics( @@ -417,21 +413,19 @@ class _MinuteControl extends StatelessWidget { @override Widget build(BuildContext context) { - final MaterialLocalizations localizations = - MaterialLocalizations.of(context); - final String formattedMinute = + final localizations = MaterialLocalizations.of(context); + final formattedMinute = localizations.formatMinute(fragmentContext.selectedTime); - final TimeOfDay nextMinute = fragmentContext.selectedTime.replacing( + final nextMinute = fragmentContext.selectedTime.replacing( minute: (fragmentContext.selectedTime.minute + 1) % TimeOfDay.minutesPerHour, ); - final String formattedNextMinute = localizations.formatMinute(nextMinute); - final TimeOfDay previousMinute = fragmentContext.selectedTime.replacing( + final formattedNextMinute = localizations.formatMinute(nextMinute); + final previousMinute = fragmentContext.selectedTime.replacing( minute: (fragmentContext.selectedTime.minute - 1) % TimeOfDay.minutesPerHour, ); - final String formattedPreviousMinute = - localizations.formatMinute(previousMinute); + final formattedPreviousMinute = localizations.formatMinute(previousMinute); return Semantics( excludeSemantics: true, @@ -470,9 +464,9 @@ class _DayPeriodControl extends StatelessWidget { final ValueChanged onChanged; void _togglePeriod() { - final int newHour = + final newHour = (selectedTime.hour + TimeOfDay.hoursPerPeriod) % TimeOfDay.hoursPerDay; - final TimeOfDay newTime = selectedTime.replacing(hour: newHour); + final newTime = selectedTime.replacing(hour: newHour); onChanged(newTime); } @@ -516,19 +510,18 @@ class _DayPeriodControl extends StatelessWidget { @override Widget build(BuildContext context) { - final MaterialLocalizations materialLocalizations = - MaterialLocalizations.of(context); - final ColorScheme colorScheme = Theme.of(context).colorScheme; - final TimePickerThemeData timePickerTheme = TimePickerTheme.of(context); - final bool isDark = colorScheme.brightness == Brightness.dark; - final Color textColor = timePickerTheme.dayPeriodTextColor ?? - MaterialStateColor.resolveWith((Set states) { + final materialLocalizations = MaterialLocalizations.of(context); + final colorScheme = Theme.of(context).colorScheme; + final timePickerTheme = TimePickerTheme.of(context); + final isDark = colorScheme.brightness == Brightness.dark; + final textColor = timePickerTheme.dayPeriodTextColor ?? + MaterialStateColor.resolveWith((states) { return states.contains(MaterialState.selected) ? colorScheme.primary : colorScheme.onSurface.withOpacity(0.60); }); - final Color backgroundColor = timePickerTheme.dayPeriodColor ?? - MaterialStateColor.resolveWith((Set states) { + final backgroundColor = timePickerTheme.dayPeriodColor ?? + MaterialStateColor.resolveWith((states) { // The unselected day period should match the overall picker dialog // color. Making it transparent enables that without being redundant // and allows the optional elevation overlay for dark mode to be @@ -537,25 +530,25 @@ class _DayPeriodControl extends StatelessWidget { ? colorScheme.primary.withOpacity(isDark ? 0.24 : 0.12) : Colors.transparent; }); - final bool amSelected = selectedTime.period == DayPeriod.am; - final Set amStates = amSelected + final amSelected = selectedTime.period == DayPeriod.am; + final amStates = amSelected ? {MaterialState.selected} : {}; - final bool pmSelected = !amSelected; - final Set pmStates = pmSelected + final pmSelected = !amSelected; + final pmStates = pmSelected ? {MaterialState.selected} : {}; - final TextStyle textStyle = timePickerTheme.dayPeriodTextStyle ?? + final textStyle = timePickerTheme.dayPeriodTextStyle ?? Theme.of(context).textTheme.subtitle1; - final TextStyle amStyle = textStyle.copyWith( + final amStyle = textStyle.copyWith( color: MaterialStateProperty.resolveAs(textColor, amStates), ); - final TextStyle pmStyle = textStyle.copyWith( + final pmStyle = textStyle.copyWith( color: MaterialStateProperty.resolveAs(textColor, pmStates), ); - OutlinedBorder shape = timePickerTheme.dayPeriodShape ?? + var shape = timePickerTheme.dayPeriodShape ?? const RoundedRectangleBorder(borderRadius: _kDefaultBorderRadius); - final BorderSide borderSide = timePickerTheme.dayPeriodBorderSide ?? + final borderSide = timePickerTheme.dayPeriodBorderSide ?? BorderSide( color: Color.alphaBlend( colorScheme.onBackground.withOpacity(0.38), colorScheme.surface), @@ -565,7 +558,7 @@ class _DayPeriodControl extends StatelessWidget { side: borderSide, ); - final double buttonTextScaleFactor = + final buttonTextScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 2.0); final Widget amButton = Material( @@ -605,7 +598,7 @@ class _DayPeriodControl extends StatelessWidget { Widget result; switch (orientation) { case Orientation.portrait: - const double width = 52.0; + const width = 52.0; result = _DayPeriodInputPadding( minSize: const Size(width, kMinInteractiveDimension * 2), orientation: orientation, @@ -737,10 +730,10 @@ class _RenderInputPadding extends RenderShiftedBox { void performLayout() { if (child != null) { child.layout(constraints, parentUsesSize: true); - final double width = math.max(child.size.width, minSize.width); - final double height = math.max(child.size.height, minSize.height); + final width = math.max(child.size.width, minSize.width); + final height = math.max(child.size.height, minSize.height); size = constraints.constrain(Size(width, height)); - final BoxParentData childParentData = child.parentData as BoxParentData; + final childParentData = child.parentData as BoxParentData; childParentData.offset = Alignment.center.alongOffset(size - child.size as Offset); } else { @@ -761,7 +754,7 @@ class _RenderInputPadding extends RenderShiftedBox { return false; } - Offset newPosition = child.size.center(Offset.zero); + var newPosition = child.size.center(Offset.zero); switch (orientation) { case Orientation.portrait: if (position.dy > newPosition.dy) { @@ -782,7 +775,7 @@ class _RenderInputPadding extends RenderShiftedBox { return result.addWithRawTransform( transform: MatrixUtils.forceToPoint(newPosition), position: newPosition, - hitTest: (BoxHitTestResult result, Offset position) { + hitTest: (result, position) { assert(position == newPosition); return child.hitTest(result, position: newPosition); }, @@ -832,12 +825,12 @@ class _DialPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final double radius = size.shortestSide / 2.0; - final Offset center = Offset(size.width / 2.0, size.height / 2.0); - final Offset centerPoint = center; + final radius = size.shortestSide / 2.0; + final center = Offset(size.width / 2.0, size.height / 2.0); + final centerPoint = center; canvas.drawCircle(centerPoint, radius, Paint()..color = backgroundColor); - final double labelRadius = radius - _labelPadding; + final labelRadius = radius - _labelPadding; Offset getOffsetForTheta(double theta) { return center + Offset(labelRadius * math.cos(theta), -labelRadius * math.sin(theta)); @@ -845,12 +838,12 @@ class _DialPainter extends CustomPainter { void paintLabels(List<_TappableLabel> labels) { if (labels == null) return; - final double labelThetaIncrement = -_kTwoPi / labels.length; - double labelTheta = math.pi / 2.0; + final labelThetaIncrement = -_kTwoPi / labels.length; + var labelTheta = math.pi / 2.0; - for (final _TappableLabel label in labels) { - final TextPainter labelPainter = label.painter; - final Offset labelOffset = + for (final label in labels) { + final labelPainter = label.painter; + final labelOffset = Offset(-labelPainter.width / 2.0, -labelPainter.height / 2.0); labelPainter.paint(canvas, getOffsetForTheta(labelTheta) + labelOffset); labelTheta += labelThetaIncrement; @@ -859,9 +852,9 @@ class _DialPainter extends CustomPainter { paintLabels(primaryLabels); - final Paint selectorPaint = Paint()..color = accentColor; - final Offset focusedPoint = getOffsetForTheta(theta); - const double focusedRadius = _labelPadding - 4.0; + final selectorPaint = Paint()..color = accentColor; + final focusedPoint = getOffsetForTheta(theta); + const focusedRadius = _labelPadding - 4.0; canvas.drawCircle(centerPoint, 4.0, selectorPaint); canvas.drawCircle(focusedPoint, focusedRadius, selectorPaint); selectorPaint.strokeWidth = 2.0; @@ -871,13 +864,13 @@ class _DialPainter extends CustomPainter { // This checks that the selector's theta is between two labels. A remainder // between 0.1 and 0.45 indicates that the selector is roughly not above any // labels. The values were derived by manually testing the dial. - final double labelThetaIncrement = -_kTwoPi / primaryLabels.length; + final labelThetaIncrement = -_kTwoPi / primaryLabels.length; if (theta % labelThetaIncrement > 0.1 && theta % labelThetaIncrement < 0.45) { canvas.drawCircle(focusedPoint, 2.0, selectorPaint..color = dotColor); } - final Rect focusedRect = Rect.fromCircle( + final focusedRect = Rect.fromCircle( center: focusedPoint, radius: focusedRadius, ); @@ -972,8 +965,8 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { } void _animateTo(double targetTheta) { - final double currentTheta = _theta.value; - double beginTheta = + final currentTheta = _theta.value; + var beginTheta = _nearest(targetTheta, currentTheta, currentTheta + _kTwoPi); beginTheta = _nearest(targetTheta, beginTheta, currentTheta - _kTwoPi); _thetaTween @@ -985,17 +978,17 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { } double _getThetaForTime(TimeOfDay time) { - final int hoursFactor = widget.use24HourDials + final hoursFactor = widget.use24HourDials ? TimeOfDay.hoursPerDay : TimeOfDay.hoursPerPeriod; - final double fraction = widget.mode == _TimePickerMode.hour + final fraction = widget.mode == _TimePickerMode.hour ? (time.hour / hoursFactor) % hoursFactor : (time.minute / TimeOfDay.minutesPerHour) % TimeOfDay.minutesPerHour; return (math.pi / 2.0 - fraction * _kTwoPi) % _kTwoPi; } TimeOfDay _getTimeForTheta(double theta, {bool roundMinutes = false}) { - final double fraction = (0.25 - (theta % _kTwoPi) / _kTwoPi) % 1.0; + final fraction = (0.25 - (theta % _kTwoPi) / _kTwoPi) % 1.0; if (widget.mode == _TimePickerMode.hour) { int newHour; if (widget.use24HourDials) { @@ -1008,7 +1001,7 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { } return widget.selectedTime.replacing(hour: newHour); } else { - int minute = (fraction * TimeOfDay.minutesPerHour).round() % + var minute = (fraction * TimeOfDay.minutesPerHour).round() % TimeOfDay.minutesPerHour; if (roundMinutes) { // Round the minutes to nearest 5 minute interval. @@ -1019,8 +1012,7 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { } TimeOfDay _notifyOnChangedIfNeeded({bool roundMinutes = false}) { - final TimeOfDay current = - _getTimeForTheta(_theta.value, roundMinutes: roundMinutes); + final current = _getTimeForTheta(_theta.value, roundMinutes: roundMinutes); if (widget.onChanged == null) return current; if (current != widget.selectedTime) widget.onChanged(current); return current; @@ -1028,9 +1020,8 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { void _updateThetaForPan({bool roundMinutes = false}) { setState(() { - final Offset offset = _position - _center; - double angle = - (math.atan2(offset.dx, offset.dy) - math.pi / 2.0) % _kTwoPi; + final offset = _position - _center; + var angle = (math.atan2(offset.dx, offset.dy) - math.pi / 2.0) % _kTwoPi; if (roundMinutes) { angle = _getThetaForTime( _getTimeForTheta(angle, roundMinutes: roundMinutes)); @@ -1047,7 +1038,7 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { void _handlePanStart(DragStartDetails details) { assert(!_dragging); _dragging = true; - final RenderBox box = context.findRenderObject() as RenderBox; + final box = context.findRenderObject() as RenderBox; _position = box.globalToLocal(details.globalPosition); _center = box.size.center(Offset.zero); _updateThetaForPan(); @@ -1074,11 +1065,11 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { } void _handleTapUp(TapUpDetails details) { - final RenderBox box = context.findRenderObject() as RenderBox; + final box = context.findRenderObject() as RenderBox; _position = box.globalToLocal(details.globalPosition); _center = box.size.center(Offset.zero); _updateThetaForPan(roundMinutes: true); - final TimeOfDay newTime = _notifyOnChangedIfNeeded(roundMinutes: true); + final newTime = _notifyOnChangedIfNeeded(roundMinutes: true); if (widget.mode == _TimePickerMode.hour) { if (widget.use24HourDials) { _announceToAccessibility( @@ -1115,7 +1106,7 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { minute: widget.selectedTime.minute); } } - final double angle = _getThetaForTime(time); + final angle = _getThetaForTime(time); _thetaTween ..begin = angle ..end = angle; @@ -1124,11 +1115,11 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { void _selectMinute(int minute) { _announceToAccessibility(context, localizations.formatDecimal(minute)); - final TimeOfDay time = TimeOfDay( + final time = TimeOfDay( hour: widget.selectedTime.hour, minute: minute, ); - final double angle = _getThetaForTime(time); + final angle = _getThetaForTime(time); _thetaTween ..begin = angle ..end = angle; @@ -1167,8 +1158,8 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { _TappableLabel _buildTappableLabel(TextTheme textTheme, Color color, int value, String label, VoidCallback onTap) { - final TextStyle style = textTheme.subtitle1.copyWith(color: color); - final double labelScaleFactor = + final style = textTheme.subtitle1.copyWith(color: color); + final labelScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 2.0); return _TappableLabel( value: value, @@ -1212,7 +1203,7 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { ]; List<_TappableLabel> _buildMinutes(TextTheme textTheme, Color color) { - const List _minuteMarkerValues = [ + const _minuteMarkerValues = [ TimeOfDay(hour: 0, minute: 0), TimeOfDay(hour: 0, minute: 5), TimeOfDay(hour: 0, minute: 10), @@ -1243,15 +1234,14 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); - final TimePickerThemeData pickerTheme = TimePickerTheme.of(context); - final Color backgroundColor = pickerTheme.dialBackgroundColor ?? + final theme = Theme.of(context); + final pickerTheme = TimePickerTheme.of(context); + final backgroundColor = pickerTheme.dialBackgroundColor ?? themeData.colorScheme.onBackground.withOpacity(0.12); - final Color accentColor = - pickerTheme.dialHandColor ?? themeData.accentColor; - final Color primaryLabelColor = MaterialStateProperty.resolveAs( + final accentColor = pickerTheme.dialHandColor ?? themeData.accentColor; + final primaryLabelColor = MaterialStateProperty.resolveAs( pickerTheme.dialTextColor, {}); - final Color secondaryLabelColor = MaterialStateProperty.resolveAs( + final secondaryLabelColor = MaterialStateProperty.resolveAs( pickerTheme.dialTextColor, {MaterialState.selected}); List<_TappableLabel> primaryLabels; List<_TappableLabel> secondaryLabels; @@ -1339,7 +1329,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { return null; } - int newHour = int.tryParse(value); + var newHour = int.tryParse(value); if (newHour == null) { return null; } @@ -1366,7 +1356,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { return null; } - final int newMinute = int.tryParse(value); + final newMinute = int.tryParse(value); if (newMinute == null) { return null; } @@ -1378,7 +1368,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { } void _handleHourSavedSubmitted(String value) { - final int newHour = _parseHour(value); + final newHour = _parseHour(value); if (newHour != null) { _selectedTime = TimeOfDay(hour: newHour, minute: _selectedTime.minute); widget.onChanged(_selectedTime); @@ -1386,7 +1376,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { } void _handleHourChanged(String value) { - final int newHour = _parseHour(value); + final newHour = _parseHour(value); if (newHour != null && value.length == 2) { // If a valid hour is typed, move focus to the minute TextField. FocusScope.of(context).nextFocus(); @@ -1394,7 +1384,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { } void _handleMinuteSavedSubmitted(String value) { - final int newMinute = _parseMinute(value); + final newMinute = _parseMinute(value); if (newMinute != null) { _selectedTime = TimeOfDay(hour: _selectedTime.hour, minute: int.parse(value)); @@ -1408,7 +1398,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { } String _validateHour(String value) { - final int newHour = _parseHour(value); + final newHour = _parseHour(value); setState(() { hourHasError = newHour == null; }); @@ -1419,7 +1409,7 @@ class _TimePickerInputState extends State<_TimePickerInput> { } String _validateMinute(String value) { - final int newMinute = _parseMinute(value); + final newMinute = _parseMinute(value); setState(() { minuteHasError = newMinute == null; }); @@ -1432,14 +1422,13 @@ class _TimePickerInputState extends State<_TimePickerInput> { @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - final MediaQueryData media = MediaQuery.of(context); - final TimeOfDayFormat timeOfDayFormat = MaterialLocalizations.of(context) + final media = MediaQuery.of(context); + final timeOfDayFormat = MaterialLocalizations.of(context) .timeOfDayFormat(alwaysUse24HourFormat: media.alwaysUse24HourFormat); - final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; - final ThemeData theme = Theme.of(context); - final TextStyle hourMinuteStyle = - TimePickerTheme.of(context).hourMinuteTextStyle ?? - theme.textTheme.headline2; + final use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; + final theme = Theme.of(context); + final hourMinuteStyle = TimePickerTheme.of(context).hourMinuteTextStyle ?? + theme.textTheme.headline2; return Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), @@ -1588,10 +1577,8 @@ class _HourMinuteTextFieldState extends State<_HourMinuteTextField> { } String get _formattedValue { - final bool alwaysUse24HourFormat = - MediaQuery.of(context).alwaysUse24HourFormat; - final MaterialLocalizations localizations = - MaterialLocalizations.of(context); + final alwaysUse24HourFormat = MediaQuery.of(context).alwaysUse24HourFormat; + final localizations = MaterialLocalizations.of(context); return !widget.isHour ? localizations.formatMinute(widget.selectedTime) : localizations.formatHour( @@ -1602,18 +1589,17 @@ class _HourMinuteTextFieldState extends State<_HourMinuteTextField> { @override Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); - final TimePickerThemeData timePickerTheme = TimePickerTheme.of(context); - final ColorScheme colorScheme = theme.colorScheme; + final theme = Theme.of(context); + final timePickerTheme = TimePickerTheme.of(context); + final colorScheme = theme.colorScheme; - final InputDecorationTheme inputDecorationTheme = - timePickerTheme.inputDecorationTheme; + final inputDecorationTheme = timePickerTheme.inputDecorationTheme; InputDecoration inputDecoration; if (inputDecorationTheme != null) { inputDecoration = const InputDecoration().applyDefaults(inputDecorationTheme); } else { - final Color unfocusedFillColor = timePickerTheme.hourMinuteColor ?? + final unfocusedFillColor = timePickerTheme.hourMinuteColor ?? colorScheme.onSurface.withOpacity(0.12); inputDecoration = InputDecoration( contentPadding: EdgeInsets.zero, @@ -1807,9 +1793,8 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { void _announceInitialTimeOnce() { if (_announcedInitialTime) return; - final MediaQueryData media = MediaQuery.of(context); - final MaterialLocalizations localizations = - MaterialLocalizations.of(context); + final media = MediaQuery.of(context); + final localizations = MaterialLocalizations.of(context); _announceToAccessibility( context, localizations.formatTimeOfDay(widget.initialTime, @@ -1837,7 +1822,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { void _handleOk() { if (_entryMode == TimePickerEntryMode.input) { - final FormState form = _formKey.currentState; + final form = _formKey.currentState; if (!form.validate()) { setState(() { _autoValidate = true; @@ -1850,12 +1835,12 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { } Size _dialogSize(BuildContext context) { - final Orientation orientation = MediaQuery.of(context).orientation; - final ThemeData theme = Theme.of(context); + final orientation = MediaQuery.of(context).orientation; + final theme = Theme.of(context); // Constrain the textScaleFactor to prevent layout issues. Since only some // parts of the time picker scale up with textScaleFactor, we cap the factor // to 1.1 as that provides enough space to reasonably fit all the content. - final double textScaleFactor = + final textScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 1.1); double timePickerWidth; @@ -1890,14 +1875,13 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - final MediaQueryData media = MediaQuery.of(context); - final TimeOfDayFormat timeOfDayFormat = localizations.timeOfDayFormat( + final media = MediaQuery.of(context); + final timeOfDayFormat = localizations.timeOfDayFormat( alwaysUse24HourFormat: media.alwaysUse24HourFormat); - final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; - final ThemeData theme = Theme.of(context); - final ShapeBorder shape = - TimePickerTheme.of(context).shape ?? _kDefaultShape; - final Orientation orientation = media.orientation; + final use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h; + final theme = Theme.of(context); + final shape = TimePickerTheme.of(context).shape ?? _kDefaultShape; + final orientation = media.orientation; final Widget actions = Row( children: [ @@ -1924,7 +1908,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { onPressed: _handleCancel, child: Text( widget.cancelText ?? localizations.cancelButtonLabel, - style: TextStyle(color: Theme.of(context).accentColor), + style: TextStyle(color: Colors.grey[600]), ), ), FlatButton( @@ -2029,7 +2013,7 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { break; } - final Size dialogSize = _dialogSize(context); + final dialogSize = _dialogSize(context); return Dialog( shape: shape, elevation: 2, @@ -2166,7 +2150,7 @@ Future showCustomTimePicker({ ? Color.fromRGBO(113, 113, 113, 1) : Color.fromRGBO(15, 15, 15, 1), ), - child: Builder(builder: (BuildContext context) { + child: Builder(builder: (context) { return builder == null ? dialog : builder(context, dialog); }), //routeSettings: routeSettings, diff --git a/lib/util/custom_widget.dart b/lib/util/custom_widget.dart index 31d3599..5f051c2 100644 --- a/lib/util/custom_widget.dart +++ b/lib/util/custom_widget.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:math' as math; import 'package:flutter/material.dart'; +import 'package:tsacdop/type/episodebrief.dart'; import 'episodegrid.dart'; import 'extension_helper.dart'; @@ -587,9 +588,8 @@ class _LineLoaderState extends State } class ImageRotate extends StatefulWidget { - final String title; - final String path; - ImageRotate({this.title, this.path, Key key}) : super(key: key); + final EpisodeBrief episodeItem; + ImageRotate({this.episodeItem, Key key}) : super(key: key); @override _ImageRotateState createState() => _ImageRotateState(); } @@ -599,6 +599,7 @@ class _ImageRotateState extends State Animation _animation; AnimationController _controller; double _value; + @override void initState() { super.initState(); @@ -635,16 +636,14 @@ class _ImageRotateState extends State Widget build(BuildContext context) { return Transform.rotate( angle: 2 * math.pi * _value, - child: Container( - padding: EdgeInsets.all(10.0), - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(15.0)), - child: Container( - height: 30.0, - width: 30.0, - color: Colors.white, - child: Image.file(File("${widget.path}")), - ), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 10.0), + child: SizedBox( + width: 30, + height: 30, + child: CircleAvatar( + backgroundColor: widget.episodeItem.backgroudColor(context), + backgroundImage: widget.episodeItem.avatarImage), ), ), ); diff --git a/lib/util/episodegrid.dart b/lib/util/episodegrid.dart index aa16476..55dc545 100644 --- a/lib/util/episodegrid.dart +++ b/lib/util/episodegrid.dart @@ -1,4 +1,3 @@ -import 'dart:io'; import 'dart:ui'; import 'package:auto_animated/auto_animated.dart'; @@ -134,8 +133,7 @@ class EpisodeGrid extends StatelessWidget { ? Center() : CircleAvatar( backgroundColor: color.withOpacity(0.5), - backgroundImage: FileImage(File("${episode.imagePath}")), - ), + backgroundImage: episode.avatarImage), ); Widget _downloadIndicater(BuildContext context, @@ -227,9 +225,7 @@ class EpisodeGrid extends StatelessWidget { crossAxisSpacing: 6.0, ), itemBuilder: (context, index, animation) { - var _c = (Theme.of(context).brightness == Brightness.light) - ? episodes[index].primaryColor.colorizedark() - : episodes[index].primaryColor.colorizeLight(); + final c = episodes[index].backgroudColor(context); scrollController.addListener(() {}); return FadeTransition( @@ -463,11 +459,11 @@ class EpisodeGrid extends StatelessWidget { layout != Layout.one ? _circleImage(context, episode: episodes[index], - color: _c, + color: c, boo: boo) : _pubDate(context, episode: episodes[index], - color: _c), + color: c), Spacer(), // _listenIndicater(context, // episode: episodes[index], @@ -477,7 +473,7 @@ class EpisodeGrid extends StatelessWidget { episode: episodes[index], isDownloaded: isDownloaded), _numberIndicater(context, - index: index, color: _c) + index: index, color: c) ], ), ), @@ -491,7 +487,7 @@ class EpisodeGrid extends StatelessWidget { children: [ _circleImage(context, episode: episodes[index], - color: _c, + color: c, boo: boo), SizedBox( width: 5, @@ -513,7 +509,7 @@ class EpisodeGrid extends StatelessWidget { if (layout != Layout.one) _pubDate(context, episode: episodes[index], - color: _c), + color: c), Spacer(), if (layout != Layout.three && episodes[index].duration != 0) @@ -600,9 +596,7 @@ class OpenContainerWrapper extends StatelessWidget { builder: (_, data, __) => OpenContainer( playerRunning: data.item1, playerHeight: kMinPlayerHeight[data.item2.index], - flightWidget: CircleAvatar( - backgroundImage: FileImage(File("${episode.imagePath}")), - ), + flightWidget: CircleAvatar(backgroundImage: episode.avatarImage), transitionDuration: Duration(milliseconds: 400), beginColor: Theme.of(context).primaryColor, endColor: Theme.of(context).primaryColor, diff --git a/lib/util/extension_helper.dart b/lib/util/extension_helper.dart index 92b8564..1cb407b 100644 --- a/lib/util/extension_helper.dart +++ b/lib/util/extension_helper.dart @@ -73,28 +73,26 @@ extension StringExtension on String { } Color colorizedark() { - Color _c; + Color c; var color = json.decode(this); if (color[0] > 200 && color[1] > 200 && color[2] > 200) { - _c = - Color.fromRGBO((255 - color[0]), 255 - color[1], 255 - color[2], 1.0); + c = Color.fromRGBO((255 - color[0]), 255 - color[1], 255 - color[2], 1.0); } else { - _c = Color.fromRGBO(color[0], color[1] > 200 ? 190 : color[1], + c = Color.fromRGBO(color[0], color[1] > 200 ? 190 : color[1], color[2] > 200 ? 190 : color[2], 1); } - return _c; + return c; } Color colorizeLight() { - Color _c; + Color c; var color = json.decode(this); if (color[0] < 50 && color[1] < 50 && color[2] < 50) { - _c = - Color.fromRGBO((255 - color[0]), 255 - color[1], 255 - color[2], 1.0); + c = Color.fromRGBO((255 - color[0]), 255 - color[1], 255 - color[2], 1.0); } else { - _c = Color.fromRGBO(color[0] < 50 ? 100 : color[0], + c = Color.fromRGBO(color[0] < 50 ? 100 : color[0], color[1] < 50 ? 100 : color[1], color[2] < 50 ? 100 : color[2], 1.0); } - return _c; + return c; } }