Add feed titile in episode page, tap avatar to open podcast page.

This commit is contained in:
stonega 2020-10-29 01:32:29 +08:00
parent e62c222efe
commit 06ec6ee5a1
5 changed files with 84 additions and 129 deletions

View File

@ -1,28 +0,0 @@
version: 2
jobs:
build:
docker:
- image: cirrusci/flutter:stable
branches:
only: master
steps:
- checkout
- run:
name: Run Flutter doctor
command: flutter doctor
- run:
name: Update package
command: flutter pub upgrade
- run: echo $ENCODED_KEYSTORE | base64 -di > ${HOME}/keystore.jks
- run: echo 'export KEYSTORE=${HOME}/keystore.jks' >> $BASH_ENV
- run: dart tool/env.dart
- run:
name: Build the Android apk
command: flutter build apk --split-per-abi --obfuscate --split-debug-info=debug/
- run:
name: Build the Android version
command: flutter build appbundle --obfuscate --split-debug-info=debug/
- store_artifacts:
path: build/app/outputs/

View File

@ -114,7 +114,13 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
: Center(),
: Text(
widget.episodeItem.feedTitle,
maxLines: 1,
style: TextStyle(
fontSize: 15,
color: context.textColor.withOpacity(0.7)),
),
leading: CustomBackButton(),
elevation: _showTitle ? 1 : 0,
//actions: [
@ -175,6 +181,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
scrollDirection: Axis.vertical,
controller: _controller,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
@ -187,30 +194,28 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
),
),
),
Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(
left: 20.0, right: 20, top: 10, bottom: 10),
Padding(
padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Row(
children: [
Text(
s.published(DateFormat.yMMMd().format(
DateTime.fromMillisecondsSinceEpoch(
widget.episodeItem.pubDate))),
style: TextStyle(
color: Theme.of(context).accentColor)),
style: TextStyle(color: context.accentColor)),
SizedBox(width: 10),
if (widget.episodeItem.explicit == 1)
Text('E',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red))
color: Colors.red)),
Spacer(),
],
),
),
Padding(
padding: EdgeInsets.only(
left: 20.0, right: 20, top: 5, bottom: 5),
padding:
EdgeInsets.symmetric(horizontal: 20, vertical: 5),
child: Row(
children: <Widget>[
if (widget.episodeItem.duration != 0)

View File

@ -8,6 +8,8 @@ import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/podcasts/podcast_detail.dart';
import 'package:tsacdop/util/pageroute.dart';
import 'package:tuple/tuple.dart';
import '../local_storage/key_value_storage.dart';
@ -975,74 +977,6 @@ class _RecentUpdateState extends State<_RecentUpdate>
SliverToBoxAdapter(
child: SizedBox(
height: 40,
// color: context.primaryColor,
// child: Material(
// color: Colors.transparent,
// child: Row(
// children: <Widget>[
// _switchGroupButton(),
// Spacer(),
// _addNewButton(),
// Material(
// color: Colors.transparent,
// child: IconButton(
// tooltip: s
// .hideListenedSetting,
// icon: SizedBox(
// width: 30,
// height: 15,
// child: HideListened(
// hideListened:
// _hideListened ??
// false,
// ),
// ),
// onPressed: () {
// setState(() =>
// _hideListened =
// !_hideListened);
// },
// ),
// ),
// Material(
// color: Colors.transparent,
// child: LayoutButton(
// layout: _layout,
// onPressed: (layout) =>
// setState(() {
// _layout = layout;
// }),
// ),
// ),
// Material(
// color:
// Colors.transparent,
// clipBehavior:
// Clip.hardEdge,
// borderRadius:
// BorderRadius
// .circular(100),
// child: IconButton(
// icon: SizedBox(
// width: 20,
// height: 10,
// child: CustomPaint(
// painter: MultiSelectPainter(
// color: context
// .accentColor)),
// ),
// onPressed: () {
// setState(() {
// _selectedEpisodes =
// [];
// _multiSelect =
// true;
// });
// },
// )),
// ],
// ),
// ),
),
),
EpisodeGrid(
@ -1050,6 +984,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
layout: _layout,
initNum: _scroll ? 0 : 12,
multiSelect: _multiSelect,
openPodcast: true,
selectedList:
_selectedEpisodes ?? [],
onSelect: (value) => setState(() {
@ -1272,6 +1207,7 @@ class _MyFavoriteState extends State<_MyFavorite>
episodes: snapshot.data,
layout: _layout,
initNum: 0,
openPodcast: true,
multiSelect: _multiSelect,
selectedList: _selectedEpisodes ?? [],
onSelect: (value) => setState(() {
@ -1549,6 +1485,7 @@ class _MyDownloadState extends State<_MyDownload>
: EpisodeGrid(
episodes: episodes,
layout: _layout,
openPodcast: true,
initNum: 0,
),
],

View File

@ -91,7 +91,7 @@ class DBHelper {
list = await dbClient.rawQuery(
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath , provider,
link ,update_count, episode_count FROM PodcastLocal WHERE id = ? AND
never_update = 0""", [s]);
never_update = 1""", [s]);
} else {
list = await dbClient.rawQuery(
"""SELECT id, title, imageUrl, rssUrl, primaryColor, author, imagePath , provider,
@ -149,6 +149,29 @@ class DBHelper {
return podcastLocal;
}
Future<PodcastLocal> getPodcastWithUrl(String url) async {
var dbClient = await database;
List<Map> list = await dbClient.rawQuery(
"""SELECT P.id, P.title, P.imageUrl, P.rssUrl, P.primaryColor, P.author, P.imagePath,
P.provider, P.link ,P.update_count, P.episode_count FROM PodcastLocal P INNER JOIN
Episodes E ON P.id = E.feed_id WHERE E.enclosure_url = ?""", [url]);
if (list.isNotEmpty) {
return PodcastLocal(
list.first['title'],
list.first['imageUrl'],
list.first['rssUrl'],
list.first['primaryColor'],
list.first['author'],
list.first['id'],
list.first['imagePath'],
list.first['provider'],
list.first['link'],
upateCount: list.first['update_count'],
episodeCount: list.first['episode_count']);
}
return null;
}
Future<int> getPodcastCounts(String id) async {
var dbClient = await database;
List<Map> list = await dbClient

View File

@ -16,14 +16,17 @@ import '../episodes/episode_detail.dart';
import '../home/audioplayer.dart';
import '../local_storage/key_value_storage.dart';
import '../local_storage/sqflite_localpodcast.dart';
import '../podcasts/podcast_detail.dart';
import '../state/audio_state.dart';
import '../state/download_state.dart';
import '../type/episodebrief.dart';
import '../type/play_histroy.dart';
import '../type/podcastlocal.dart';
import 'custom_widget.dart';
import 'extension_helper.dart';
import 'general_dialog.dart';
import 'open_container.dart';
import 'pageroute.dart';
enum Layout { three, two, one }
@ -38,6 +41,7 @@ class EpisodeGrid extends StatelessWidget {
final bool reverse;
final bool multiSelect;
final ValueChanged<List<EpisodeBrief>> onSelect;
final bool openPodcast;
final List<EpisodeBrief> selectedList;
/// Count of animation items.
@ -53,16 +57,17 @@ class EpisodeGrid extends StatelessWidget {
this.episodeCount = 0,
this.layout = Layout.three,
this.reverse,
this.openPodcast = false,
this.multiSelect = false,
this.onSelect,
this.selectedList})
: super(key: key);
List<EpisodeBrief> _selectedList = [];
final _dbHelper = DBHelper();
Future<int> _isListened(EpisodeBrief episode) async {
var dbHelper = DBHelper();
return await dbHelper.isListened(episode.enclosureUrl);
return await _dbHelper.isListened(episode.enclosureUrl);
}
Future<Tuple5<int, bool, bool, bool, List<int>>> _initData(
@ -76,8 +81,7 @@ class EpisodeGrid extends StatelessWidget {
}
Future<bool> _isLiked(EpisodeBrief episode) async {
var dbHelper = DBHelper();
return await dbHelper.isLiked(episode.enclosureUrl);
return await _dbHelper.isLiked(episode.enclosureUrl);
}
Future<List<int>> _getEpisodeMenu() async {
@ -87,8 +91,7 @@ class EpisodeGrid extends StatelessWidget {
}
Future<bool> _isDownloaded(EpisodeBrief episode) async {
var dbHelper = DBHelper();
return await dbHelper.isDownloaded(episode.enclosureUrl);
return await _dbHelper.isDownloaded(episode.enclosureUrl);
}
Future<bool> _getTapToOpenPopupMenu() async {
@ -98,24 +101,20 @@ class EpisodeGrid extends StatelessWidget {
}
Future<void> _markListened(EpisodeBrief episode) async {
var dbHelper = DBHelper();
final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1);
await dbHelper.saveHistory(history);
await _dbHelper.saveHistory(history);
}
Future<void> _markNotListened(String url) async {
var dbHelper = DBHelper();
await dbHelper.markNotListened(url);
await _dbHelper.markNotListened(url);
}
Future<void> _saveLiked(String url) async {
var dbHelper = DBHelper();
await dbHelper.setLiked(url);
await _dbHelper.setLiked(url);
}
Future<void> _setUnliked(String url) async {
var dbHelper = DBHelper();
await dbHelper.setUniked(url);
await _dbHelper.setUniked(url);
}
Future<void> _requestDownload(BuildContext context,
@ -186,6 +185,11 @@ class EpisodeGrid extends StatelessWidget {
return ifUseData;
}
Future<PodcastLocal> _getPodcast(String url) async {
var podcasts = await _dbHelper.getPodcastWithUrl(url);
return podcasts;
}
/// Episode title widget.
Widget _title(EpisodeBrief episode) => Container(
alignment:
@ -202,14 +206,28 @@ class EpisodeGrid extends StatelessWidget {
/// Circel avatar widget.
Widget _circleImage(BuildContext context,
{EpisodeBrief episode, Color color, bool boo, double radius}) =>
Container(
height: radius ?? context.width / 16,
width: radius ?? context.width / 16,
child: boo
? Center()
: CircleAvatar(
backgroundColor: color.withOpacity(0.5),
backgroundImage: episode.avatarImage),
InkWell(
onTap: () async {
if (openPodcast) {
final podcast = await _getPodcast(episode.enclosureUrl);
Navigator.push(
context,
SlideLeftRoute(
page: PodcastDetail(
podcastLocal: podcast,
)),
);
}
},
child: Container(
height: radius ?? context.width / 16,
width: radius ?? context.width / 16,
child: boo
? Center()
: CircleAvatar(
backgroundColor: color.withOpacity(0.5),
backgroundImage: episode.avatarImage),
),
);
Widget _downloadIndicater(BuildContext context,