modified: lib/state/subscribe_podcast.dart

Change search to enter to search
This commit is contained in:
stonegate 2020-05-21 17:15:38 +08:00
parent b1a686987d
commit e7c175fef2
7 changed files with 338 additions and 420 deletions

View File

@ -1,54 +0,0 @@
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: '12.x'
- uses: subosito/flutter-action@v1
with:
flutter-version: '1.18.0-11.1.pre'
channel: 'beta'
env:
KEY_ALIAS: ${{ secrets.KEY_ALIAS}}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
ENCODED_KEYSTORE: ${{ secrets.ENCODED_KEYSTORE }}
# Runs a single command using the runners shell
- name: Run flutter doctor
run: flutter doctor
# Runs a set of commands using the runners shell
- name: Update package
run: flutter update-packages --force-upgrade
- name: Configure env
run: |
echo $ENCODED_KEYSTORE | base64 -di > /home/runner/work/tsacdop/tsacdop/android/app/keystore.jks
dart tool/env.dart
- name: Build android version
run: flutter build appbundle --no-shrink
- uses: actions/upload-artifact@v1
with:
name: release-apk
path: build/app/outputs/bundle/release/app-release.aab

View File

@ -49,7 +49,7 @@ android {
applicationId "com.stonegate.tsacdop" applicationId "com.stonegate.tsacdop"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 28 targetSdkVersion 28
versionCode 12 versionCode 14
versionName flutterVersionName versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@ -4,7 +4,7 @@ import 'package:tsacdop/util/custompaint.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:line_icons/line_icons.dart'; import 'package:line_icons/line_icons.dart';
const String version = '0.3.0'; const String version = '0.3.1';
class AboutApp extends StatelessWidget { class AboutApp extends StatelessWidget {
_launchUrl(String url) async { _launchUrl(String url) async {

View File

@ -24,8 +24,7 @@ class MyHomePageDelegate extends SearchDelegate<int> {
String apiKey = environment['apiKey']; String apiKey = environment['apiKey'];
String url = String url =
"https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" + "https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" +
searchText + "$searchText&sort_by_date=0&type=podcast";
"&sort_by_date=0&type=podcast";
Response response = await Dio().get(url, Response response = await Dio().get(url,
options: Options(headers: { options: Options(headers: {
'X-Mashape-Key': "$apiKey", 'X-Mashape-Key': "$apiKey",
@ -81,57 +80,57 @@ class MyHomePageDelegate extends SearchDelegate<int> {
@override @override
Widget buildSuggestions(BuildContext context) { Widget buildSuggestions(BuildContext context) {
if (query.isEmpty) // if (query.isEmpty)
return Center( return Center(
child: Container( child: Container(
padding: EdgeInsets.only(top: 400), padding: EdgeInsets.only(top: 400),
child: Image( child: Image(
image: Theme.of(context).brightness == Brightness.light image: Theme.of(context).brightness == Brightness.light
? AssetImage('assets/listennotes.png') ? AssetImage('assets/listennotes.png')
: AssetImage('assets/listennotes_light.png'), : AssetImage('assets/listennotes_light.png'),
height: 20, height: 20,
), ),
)); ));
else if (rssExp.stringMatch(query) != null) // else if (rssExp.stringMatch(query) != null)
return FutureBuilder( // return FutureBuilder(
future: getRss(rssExp.stringMatch(query)), // future: getRss(rssExp.stringMatch(query)),
builder: (context, snapshot) { // builder: (context, snapshot) {
if (snapshot.hasError) // if (snapshot.hasError)
return invalidRss(); // return invalidRss();
else if (snapshot.hasData) // else if (snapshot.hasData)
return SearchResult( // return SearchResult(
onlinePodcast: snapshot.data, // onlinePodcast: snapshot.data,
); // );
else // else
return Container( // return Container(
padding: EdgeInsets.only(top: 200), // padding: EdgeInsets.only(top: 200),
alignment: Alignment.topCenter, // alignment: Alignment.topCenter,
child: CircularProgressIndicator(), // child: CircularProgressIndicator(),
); // );
}, // },
); // );
else // else
return FutureBuilder( // return FutureBuilder(
future: getList(query), // future: getList(query),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) { // builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (!snapshot.hasData && query != null) // if (!snapshot.hasData && query != null)
return Container( // return Container(
padding: EdgeInsets.only(top: 200), // padding: EdgeInsets.only(top: 200),
alignment: Alignment.topCenter, // alignment: Alignment.topCenter,
child: CircularProgressIndicator(), // child: CircularProgressIndicator(),
); // );
List content = snapshot.data; // List content = snapshot.data;
return ListView.builder( // return ListView.builder(
scrollDirection: Axis.vertical, // scrollDirection: Axis.vertical,
itemCount: content.length, // itemCount: content.length,
itemBuilder: (BuildContext context, int index) { // itemBuilder: (BuildContext context, int index) {
return SearchResult( // return SearchResult(
onlinePodcast: content[index], // onlinePodcast: content[index],
); // );
}, // },
); // );
}, // },
); // );
} }
@override @override
@ -257,7 +256,8 @@ class _SearchResultState extends State<SearchResult>
var subscribeWorker = Provider.of<SubscribeWorker>(context, listen: false); var subscribeWorker = Provider.of<SubscribeWorker>(context, listen: false);
savePodcast(OnlinePodcast podcast) { savePodcast(OnlinePodcast podcast) {
SubscribeItem item = SubscribeItem(podcast.rss, podcast.title, imgUrl: podcast.image); SubscribeItem item =
SubscribeItem(podcast.rss, podcast.title, imgUrl: podcast.image);
subscribeWorker.setSubscribeItem(item); subscribeWorker.setSubscribeItem(item);
} }
@ -309,8 +309,7 @@ class _SearchResultState extends State<SearchResult>
child: !_issubscribe child: !_issubscribe
? OutlineButton( ? OutlineButton(
highlightedBorderColor: context.accentColor, highlightedBorderColor: context.accentColor,
splashColor: splashColor: context.accentColor.withOpacity(0.8),
context.accentColor.withOpacity(0.8),
child: Text('Subscribe', child: Text('Subscribe',
style: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor)), color: Theme.of(context).accentColor)),

View File

@ -447,256 +447,257 @@ class _RecentUpdateState extends State<_RecentUpdate>
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
return FutureBuilder<List<EpisodeBrief>>( return Selector<SubscribeWorker, bool>(
future: _getRssItem(_top, _group), selector: (_, worker) => worker.created,
builder: (context, snapshot) { builder: (context, created, child) {
if (snapshot.hasError) print(snapshot.error); return FutureBuilder<List<EpisodeBrief>>(
return (snapshot.hasData) future: _getRssItem(_top, _group),
? snapshot.data.length == 0 builder: (context, snapshot) {
? Center( if (snapshot.hasError) print(snapshot.error);
child: Column( return (snapshot.hasData)
mainAxisAlignment: MainAxisAlignment.center, ? snapshot.data.length == 0
children: [ ? Center(
Icon(LineIcons.cloud_download_alt_solid, child: Column(
size: 80, color: Colors.grey[500]), mainAxisAlignment: MainAxisAlignment.center,
Padding(padding: EdgeInsets.symmetric(vertical: 10)), children: [
Text( Icon(LineIcons.cloud_download_alt_solid,
'No episode received yet', size: 80, color: Colors.grey[500]),
style: TextStyle(color: Colors.grey[500]), Padding(
padding: EdgeInsets.symmetric(vertical: 10)),
Text(
'No episode received yet',
style: TextStyle(color: Colors.grey[500]),
)
],
),
) )
], : NotificationListener<ScrollNotification>(
), onNotification: (ScrollNotification scrollInfo) {
) if (scrollInfo.metrics.pixels ==
: NotificationListener<ScrollNotification>( scrollInfo.metrics.maxScrollExtent &&
onNotification: (ScrollNotification scrollInfo) { snapshot.data.length == _top)
if (scrollInfo.metrics.pixels == _loadMoreEpisode();
scrollInfo.metrics.maxScrollExtent && return true;
snapshot.data.length == _top) _loadMoreEpisode(); },
return true; child: CustomScrollView(
}, key: PageStorageKey<String>('update'),
child: Selector<SubscribeWorker, bool>( physics: const AlwaysScrollableScrollPhysics(),
selector: (_, worker) => worker.created, slivers: <Widget>[
builder: (context, created, child) { SliverToBoxAdapter(
return CustomScrollView( child: Container(
key: PageStorageKey<String>('update'), height: 40,
physics: const AlwaysScrollableScrollPhysics(), color: context.primaryColor,
slivers: <Widget>[ child: Material(
SliverToBoxAdapter( color: Colors.transparent,
child: Container( child: Row(
height: 40, children: <Widget>[
color: context.primaryColor, Consumer<GroupList>(
child: Material( builder:
color: Colors.transparent, (context, groupList, child) =>
child: Row( Material(
children: <Widget>[ color: Colors.transparent,
Consumer<GroupList>( child: PopupMenuButton<String>(
builder: shape: RoundedRectangleBorder(
(context, groupList, child) => borderRadius:
Material( BorderRadius.all(
color: Colors.transparent, Radius.circular(
child: PopupMenuButton<String>( 10))),
shape: RoundedRectangleBorder( elevation: 1,
borderRadius: tooltip: 'Groups fliter',
BorderRadius.all( child: Container(
Radius.circular( padding:
10))), EdgeInsets.symmetric(
elevation: 1, horizontal: 20),
tooltip: 'Groups fliter', height: 50,
child: Container( child: Row(
padding: mainAxisSize:
EdgeInsets.symmetric( MainAxisSize.min,
horizontal: 20), children: <Widget>[
height: 50, Text(_groupName),
child: Row( Padding(
mainAxisSize: padding: EdgeInsets
MainAxisSize.min, .symmetric(
children: <Widget>[ horizontal:
Text(_groupName), 5),
Padding( ),
padding: EdgeInsets Icon(
.symmetric( LineIcons
horizontal: .filter_solid,
5), size: 18,
), )
Icon( ],
LineIcons )),
.filter_solid, itemBuilder: (context) => [
size: 18, PopupMenuItem(
) child: Text('All'),
], value: 'All')
)), ]..addAll(groupList.groups
itemBuilder: (context) => [ .map<
PopupMenuItem( PopupMenuEntry<
child: Text('All'), String>>((e) =>
value: 'All') PopupMenuItem(
]..addAll(groupList.groups value: e.name,
.map< child:
PopupMenuEntry< Text(e.name)))
String>>((e) => .toList()),
PopupMenuItem( onSelected: (value) {
value: e.name, if (value == 'All') {
child: setState(() {
Text(e.name))) _groupName = 'All';
.toList()), _group = ['All'];
onSelected: (value) { });
if (value == 'All') { } else {
setState(() { groupList.groups
_groupName = 'All'; .forEach((group) {
_group = ['All']; if (group.name ==
}); value) {
} else { setState(() {
groupList.groups _groupName = value;
.forEach((group) { _group = group
if (group.name == value) { .podcastList;
setState(() { });
_groupName = value; }
_group = });
group.podcastList; }
}); },
} ),
});
}
},
), ),
), ),
), Spacer(),
Spacer(), FutureBuilder<int>(
FutureBuilder<int>( future:
future: _getUpdateCounts(_group), _getUpdateCounts(_group),
initialData: 0, initialData: 0,
builder: (context, snapshot) { builder: (context, snapshot) {
return snapshot.data != 0 return snapshot.data != 0
? Material( ? Material(
color: color: Colors
Colors.transparent, .transparent,
child: IconButton( child: IconButton(
tooltip: tooltip:
'Add new episodes to playlist', 'Add new episodes to playlist',
icon: icon:
// Icon(Icons.playlist_add), // Icon(Icons.playlist_add),
SizedBox( SizedBox(
height: 16, height:
width: 21, 16,
child: CustomPaint( width: 21,
painter: AddToPlaylistPainter( child: CustomPaint(
context painter: AddToPlaylistPainter(
.textTheme.bodyText1.color, context.textTheme.bodyText1.color,
Colors Colors.red))),
.red))), onPressed: () async {
onPressed: await audio
() async { .addNewEpisode(
await audio _group);
.addNewEpisode( if (mounted)
_group); setState(
if (mounted) () {});
setState(() {}); Fluttertoast
Fluttertoast .showToast(
.showToast( msg: _groupName ==
msg: _groupName == 'All'
'All' ? '${snapshot.data} episode added to playlist'
? '${snapshot.data} episode added to playlist' : '${snapshot.data} episode in $_groupName added to playlist',
: '${snapshot.data} episode in $_groupName added to playlist', gravity:
gravity: ToastGravity
ToastGravity .BOTTOM,
.BOTTOM, );
); }),
}), )
) : Material(
: Material( color: Colors
color: .transparent,
Colors.transparent, child: IconButton(
child: IconButton( tooltip:
tooltip: 'Add new episodes to playlist',
'Add new episodes to playlist', icon:
icon: // Icon(Icons.playlist_add),
// Icon(Icons.playlist_add), SizedBox(
SizedBox( height:
height: 16, 16,
width: 21, width: 21,
child: CustomPaint( child: CustomPaint(
painter: AddToPlaylistPainter( painter: AddToPlaylistPainter(
context context
.textTheme .textTheme
.bodyText1 .bodyText1
.color, .color,
context context
.textTheme .textTheme
.bodyText1 .bodyText1
.color, .color,
))), ))),
onPressed: () {}), onPressed: () {}),
); );
}), }),
Material( Material(
color: Colors.transparent, color: Colors.transparent,
child: IconButton( child: IconButton(
tooltip: 'Change layout', tooltip: 'Change layout',
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
if (_layout == Layout.three) if (_layout == Layout.three)
setState(() { setState(() {
_layout = Layout.two; _layout = Layout.two;
}); });
else else
setState(() { setState(() {
_layout = Layout.three; _layout = Layout.three;
}); });
}, },
icon: _layout == Layout.three icon: _layout == Layout.three
? SizedBox( ? SizedBox(
height: 10, height: 10,
width: 30, width: 30,
child: CustomPaint( child: CustomPaint(
painter: painter: LayoutPainter(
LayoutPainter( 0,
0, context
context .textTheme
.textTheme .bodyText1
.bodyText1 .color),
.color), ),
)
: SizedBox(
height: 10,
width: 30,
child: CustomPaint(
painter: LayoutPainter(
1,
context
.textTheme
.bodyText1
.color),
),
), ),
) )),
: SizedBox( ],
height: 10, ),
width: 30, )),
child: CustomPaint(
painter:
LayoutPainter(
1,
context
.textTheme
.bodyText1
.color),
),
),
)),
],
),
)),
),
EpisodeGrid(
episodes: snapshot.data,
layout: _layout,
initNum: 9,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return _loadMore
? Container(
height: 2,
child: LinearProgressIndicator())
: Center();
},
childCount: 1,
), ),
), EpisodeGrid(
]); episodes: snapshot.data,
}, layout: _layout,
)) initNum: 9,
: Center(); ),
}, SliverList(
); delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return _loadMore
? Container(
height: 2,
child: LinearProgressIndicator())
: Center();
},
childCount: 1,
),
),
]))
: Center();
},
);
});
} }
@override @override
@ -970,29 +971,31 @@ class _MyDownloadState extends State<_MyDownload>
.toList() .toList()
.reversed .reversed
.toList(); .toList();
return episodes.length == 0 return
? SliverToBoxAdapter( //episodes.length == 0
child: Padding( // ? SliverToBoxAdapter(
padding: EdgeInsets.only(top: 100), // child: Padding(
child: Column( // padding: EdgeInsets.only(top: 100),
mainAxisAlignment: MainAxisAlignment.center, // child: Column(
children: [ // mainAxisAlignment: MainAxisAlignment.center,
Icon(LineIcons.download_solid, // children: [
size: 80, color: Colors.grey[500]), // Icon(LineIcons.download_solid,
Padding(padding: EdgeInsets.symmetric(vertical: 10)), // size: 80, color: Colors.grey[500]),
Text( // Padding(padding: EdgeInsets.symmetric(vertical: 10)),
'No episode collected yet', // Text(
style: TextStyle(color: Colors.grey[500]), // 'No episode collected yet',
) // style: TextStyle(color: Colors.grey[500]),
], // )
), // ],
), // ),
) // ),
: EpisodeGrid( // )
episodes: episodes, // :
layout: _layout, EpisodeGrid(
initNum: 0, episodes: episodes,
); layout: _layout,
initNum: 0,
);
}, },
), ),
], ],

View File

@ -36,7 +36,7 @@ class SubscribeWorker extends ChangeNotifier {
SubscribeItem _subscribeItem; SubscribeItem _subscribeItem;
SubscribeItem _currentSubscribeItem = SubscribeItem('', ''); SubscribeItem _currentSubscribeItem = SubscribeItem('', '');
bool _created = false; bool _created = false;
bool get created => _created; bool get created=> _created;
setSubscribeItem(SubscribeItem item) async { setSubscribeItem(SubscribeItem item) async {
_subscribeItem = item; _subscribeItem = item;

View File

@ -1,7 +1,7 @@
name: tsacdop name: tsacdop
description: An easy-use podacasts player. description: An easy-use podacasts player.
version: 0.3.0 version: 0.3.1
environment: environment:
sdk: ">=2.6.0 <3.0.0" sdk: ">=2.6.0 <3.0.0"
@ -9,14 +9,9 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
cupertino_icons: ^0.1.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
cupertino_icons: ^0.1.3
json_annotation: ^3.0.1 json_annotation: ^3.0.1
sqflite: ^1.3.0 sqflite: ^1.3.0
flutter_html: ^0.11.1 flutter_html: ^0.11.1
@ -55,43 +50,18 @@ dev_dependencies:
line_icons: line_icons:
git: git:
url: https://github.com/galonsos/line_icons.git url: https://github.com/galonsos/line_icons.git
dev_dependencies:
flutter_test:
sdk: flutter
dependency_overrides: dependency_overrides:
flutter_isolate: '1.0.0+13' flutter_isolate: "1.0.0+13"
xml: '4.1.0' xml: "4.1.0"
flutter: flutter:
assets: assets:
- assets/ - assets/
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages
flutter_intl: flutter_intl:
enabled: true enabled: true