1
0
mirror of https://github.com/stonega/tsacdop synced 2025-02-18 04:20:37 +01:00

modified: lib/class/settingstate.dart

modified:   lib/episodes/episodedetail.dart
	modified:   lib/home/appbar/about.dart
modified:   lib/home/appbar/addpodcast.dart
	modified:   lib/home/appbar/importompl.dart
	modified:   lib/home/appbar/popupmenu.dart
	modified:   lib/home/audio_player.dart
	modified:   lib/home/audiopanel.dart
	modified:   lib/home/homescroll.dart
	modified:   lib/home/hometab.dart
	modified:   lib/local_storage/key_value_storage.dart
	modified:   lib/main.dart
	modified:   lib/podcasts/podcastdetail.dart
	modified:   lib/podcasts/podcastgroup.dart
	modified:   lib/podcasts/podcastlist.dart
	modified:   lib/podcasts/podcastmanage.dart
	modified:   lib/util/episodegrid.dart
This commit is contained in:
stonegate 2020-02-22 20:25:06 +08:00
parent 9d4bbc895a
commit 7ba0552717
17 changed files with 966 additions and 791 deletions

View File

@ -1,13 +1,30 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
//two types podcast update, backhome nedd to back to default grooup.
enum Update {backhome, justupdate}
class SettingState extends ChangeNotifier{
Update _subscribeupdate;
Update get subscribeupdate => _subscribeupdate;
set subscribeUpdate(Update s){
_subscribeupdate = s;
import 'package:tsacdop/local_storage/key_value_storage.dart';
class SettingState extends ChangeNotifier {
KeyValueStorage storage = KeyValueStorage('themes');
int _theme;
int get theme => _theme;
void setTheme(int theme) {
_theme = theme;
notifyListeners();
_saveTheme(theme);
}
@override
void addListener(VoidCallback listener) {
super.addListener(listener);
_getTheme();
}
_getTheme() async {
_theme = await storage.getTheme();
}
_saveTheme(theme) async {
await storage.saveTheme(theme);
}
}

View File

@ -2,6 +2,7 @@ import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:url_launcher/url_launcher.dart';
@ -15,8 +16,7 @@ import 'episodedownload.dart';
class EpisodeDetail extends StatefulWidget {
final EpisodeBrief episodeItem;
final String heroTag;
EpisodeDetail({this.episodeItem, this.heroTag, Key key})
: super(key: key);
EpisodeDetail({this.episodeItem, this.heroTag, Key key}) : super(key: key);
@override
_EpisodeDetailState createState() => _EpisodeDetailState();
@ -53,16 +53,21 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar(
title: Text(widget.episodeItem.feedTitle),
elevation: 0.0,
centerTitle: true,
backgroundColor: Colors.grey[100],
),
body: Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
@ -87,7 +92,9 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
height: 30.0,
child: Text(
'Published ' +
DateFormat.yMMMd().format( DateTime.fromMillisecondsSinceEpoch(widget.episodeItem.pubDate)),
DateFormat.yMMMd().format(
DateTime.fromMillisecondsSinceEpoch(
widget.episodeItem.pubDate)),
style: TextStyle(color: Colors.blue[500])),
),
Container(
@ -117,7 +124,8 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
padding: EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.center,
child: Text(
(widget.episodeItem.duration).toString() + 'mins',
(widget.episodeItem.duration).toString() +
'mins',
style: textstyle),
),
Container(
@ -130,7 +138,8 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
padding: EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.center,
child: Text(
((widget.episodeItem.enclosureLength) ~/ 1000000)
((widget.episodeItem.enclosureLength) ~/
1000000)
.toString() +
'MB',
style: textstyle),
@ -168,6 +177,8 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
],
),
),
),
),
);
}
}
@ -175,8 +186,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
class MenuBar extends StatefulWidget {
final EpisodeBrief episodeItem;
final String heroTag;
MenuBar({this.episodeItem, this.heroTag, Key key})
: super(key: key);
MenuBar({this.episodeItem, this.heroTag, Key key}) : super(key: key);
@override
_MenuBarState createState() => _MenuBarState();
}
@ -227,7 +237,7 @@ class _MenuBarState extends State<MenuBar> {
return Container(
height: 50.0,
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
child: Row(
@ -249,9 +259,9 @@ class _MenuBarState extends State<MenuBar> {
child: Container(
height: 30.0,
width: 30.0,
color: Colors.white,
child: Image.file(File(
"${widget.episodeItem.imagePath}")),
color: Theme.of(context).scaffoldBackgroundColor,
child:
Image.file(File("${widget.episodeItem.imagePath}")),
),
),
),
@ -276,8 +286,7 @@ class _MenuBarState extends State<MenuBar> {
],
),
DownloadButton(episodeBrief: widget.episodeItem),
_buttonOnMenu(Icon(Icons.playlist_add, color: Colors.grey[700]),
() {
_buttonOnMenu(Icon(Icons.playlist_add, color: Colors.grey[700]), () {
Fluttertoast.showToast(
msg: 'Not support yet',
gravity: ToastGravity.BOTTOM,
@ -303,13 +312,13 @@ class _MenuBarState extends State<MenuBar> {
children: <Widget>[
Text('Play Now',
style: TextStyle(
color: Colors.blue,
color: Theme.of(context).accentColor,
fontSize: 15,
fontWeight: FontWeight.bold,
)),
Icon(
Icons.play_arrow,
color: Colors.blue,
color: Theme.of(context).accentColor,
),
],
),
@ -320,8 +329,8 @@ class _MenuBarState extends State<MenuBar> {
audioplay.audioState == AudioState.play)
? Container(
padding: EdgeInsets.only(right: 30),
child: SizedBox(
width: 20, height: 15, child: WaveLoader()))
child:
SizedBox(width: 20, height: 15, child: WaveLoader()))
: Container(
padding: EdgeInsets.only(right: 30),
child: SizedBox(

View File

@ -1,31 +1,37 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class AboutApp extends StatelessWidget {
TextSpan buildTextSpan() {
return TextSpan(children: [
TextSpan(text: 'Tsacdop\n',style: TextStyle(fontSize: 20)),
TextSpan(text: 'Tsacdop\n', style: TextStyle(fontSize: 20)),
TextSpan(
text:
'Tsacdop is a podcast client developed by flutter, is a simple, easy-use player.\n'),
TextSpan(
text:
'Github https://github.com/stonga/tsacdop .\n'),
TextSpan(text: 'Github https://github.com/stonga/tsacdop .\n'),
]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[100],
title: Text('Tsacdop'),
centerTitle: true,
elevation: 0,
),
body: Container(
padding: EdgeInsets.all(20),
alignment: Alignment.topLeft,
child: Text.rich(buildTextSpan()),
));
)),
),
);
}
}

View File

@ -34,16 +34,15 @@ class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.grey[100],
statusBarColor: Colors.green,
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
elevation: 0,
centerTitle: true,
backgroundColor: Colors.grey[100],
brightness: Brightness.light,
leading: IconButton(
tooltip: 'Add',
icon: const Icon(Icons.add_circle_outline),
@ -64,6 +63,7 @@ class _MyHomePageState extends State<MyHomePage> {
),
body: Home(),
),
),
);
}
}
@ -84,6 +84,9 @@ class _MyHomePageDelegate extends SearchDelegate<int> {
return searchResult.results;
}
@override
ThemeData appBarTheme(BuildContext context) => Theme.of(context);
@override
Widget buildLeading(BuildContext context) {
return IconButton(
@ -327,7 +330,7 @@ class _SearchResultState extends State<SearchResult> {
? !_adding
? OutlineButton(
child: Text('Subscribe',
style: TextStyle(color: Colors.blue)),
style: TextStyle(color: Theme.of(context).accentColor)),
onPressed: () {
importOmpl.rssTitle = widget.onlinePodcast.title;
savePodcast(widget.onlinePodcast.rss);
@ -351,7 +354,7 @@ class _SearchResultState extends State<SearchResult> {
? Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: Colors.grey[300],
color: Theme.of(context).primaryColorDark,
borderRadius: BorderRadius.only(
topRight: Radius.circular(15.0),
bottomLeft: Radius.circular(15.0),

View File

@ -7,7 +7,7 @@ class Import extends StatelessWidget {
Widget build(BuildContext context) {
return Consumer<ImportOmpl>(
builder: (context, importOmpl, _) => Container(
color: Colors.grey[300],
color: Theme.of(context).primaryColorDark,
child: importOmpl.importState == ImportState.start
? Column(
mainAxisAlignment: MainAxisAlignment.start,

View File

@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/podcast_group.dart';
import 'package:tsacdop/class/settingstate.dart';
import 'package:xml/xml.dart' as xml;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/services.dart';
@ -47,6 +48,7 @@ class PopupMenu extends StatelessWidget {
Widget build(BuildContext context) {
ImportOmpl importOmpl = Provider.of<ImportOmpl>(context, listen: false);
GroupList groupList = Provider.of<GroupList>(context, listen: false);
SettingState setting = Provider.of<SettingState>(context);
_refreshAll() async {
var dbHelper = DBHelper();
List<PodcastLocal> podcastList = await dbHelper.getPodcastLocalAll();
@ -113,8 +115,7 @@ class PopupMenu extends StatelessWidget {
await Future.delayed(Duration(seconds: 5));
importOmpl.importState = ImportState.stop;
}
}
else {
} else {
importOmpl.importState = ImportState.error;
Fluttertoast.showToast(
@ -144,8 +145,9 @@ class PopupMenu extends StatelessWidget {
for (int i = 0; i < total.length; i++) {
if (total[i].xmlUrl != null) {
importOmpl.rssTitle = total[i].text;
try{await saveOmpl(total[i].xmlUrl);}
catch (e){
try {
await saveOmpl(total[i].xmlUrl);
} catch (e) {
print(e.toString());
}
print(total[i].text);
@ -183,17 +185,23 @@ class PopupMenu extends StatelessWidget {
),
PopupMenuItem(
value: 3,
child: setting.theme != 2 ? Text('Night Mode') : Text('Light Mode'),
),
PopupMenuItem(
value: 4,
child: Text('About'),
),
],
onSelected: (value) {
if (value == 3) {
if (value == 4) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AboutApp()));
} else if (value == 2) {
_getFilePath();
} else if (value == 1) {
_refreshAll();
} else if (value == 3) {
setting.theme != 2 ? setting.setTheme(2) : setting.setTheme(1);
}
},
);

View File

@ -65,9 +65,10 @@ class _PlayerWidgetState extends State<PlayerWidget> {
_remoteAudioLoading = true;
Provider.of<AudioPlay>(context, listen: false).audioState = AudioState.load;
if (_backgroundAudioPlaying == true)
{ _backgroundAudio?.pause();
AudioSystem.instance.stopBackgroundDisplay();}
if (_backgroundAudioPlaying == true) {
_backgroundAudio?.pause();
AudioSystem.instance.stopBackgroundDisplay();
}
_backgroundAudio?.dispose();
_backgroundAudio = Audio.loadFromRemoteUrl(url,
onDuration: (double durationSeconds) {
@ -118,9 +119,10 @@ class _PlayerWidgetState extends State<PlayerWidget> {
_remoteAudioLoading = true;
ByteData audio = getAudio(path);
Provider.of<AudioPlay>(context, listen: false).audioState = AudioState.load;
if (_backgroundAudioPlaying == true)
{_backgroundAudio?.pause();
AudioSystem.instance.stopBackgroundDisplay();}
if (_backgroundAudioPlaying == true) {
_backgroundAudio?.pause();
AudioSystem.instance.stopBackgroundDisplay();
}
_backgroundAudio?.dispose();
_backgroundAudio = Audio.loadFromByteData(audio,
onDuration: (double durationSeconds) {
@ -192,11 +194,6 @@ class _PlayerWidgetState extends State<PlayerWidget> {
setState(() {
this.url = url;
episode = Provider.of<AudioPlay>(context).episode;
var color = json.decode(episode?.primaryColor);
(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(color[0], color[1], color[2], 1.0);
_backgroundAudioPlaying = true;
_isLoading = true;
_getFile(url).then((result) {
@ -270,11 +267,10 @@ class _PlayerWidgetState extends State<PlayerWidget> {
'playnow', likeButtonId, 'ic_stat_play_circle_filled');
Future<void> _setNotification() async {
final Uint8List imageBytes =
File('${episode.imagePath}').readAsBytesSync();
final Uint8List imageBytes = File('${episode.imagePath}').readAsBytesSync();
AudioSystem.instance.setMetadata(AudioMetadata(
title: episode.title,
artist:episode.feedTitle,
artist: episode.feedTitle,
album: episode.feedTitle,
genre: "Podcast",
durationSeconds: _backgroundAudioDurationSeconds,
@ -309,8 +305,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Provider.of<AudioPlay>(context, listen: false).audioState =
AudioState.play;
});
final Uint8List imageBytes =
File('${episode.imagePath}').readAsBytesSync();
final Uint8List imageBytes = File('${episode.imagePath}').readAsBytesSync();
AudioSystem.instance.setMetadata(AudioMetadata(
title: episode.title,
artist: episode.feedTitle,
@ -383,9 +378,9 @@ class _PlayerWidgetState extends State<PlayerWidget> {
AudioSystem.instance.setPlaybackState(true, forwardposition);
}
Widget _expandedPanel() => Container(
Widget _expandedPanel(BuildContext context) => Container(
height: 300,
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
@ -459,7 +454,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
color: const Color(0xFFFF0000)))
: Text(
_remoteAudioLoading ? 'Buffring...' : '',
style: TextStyle(color: Colors.blue),
style: TextStyle(
color: Theme.of(context).accentColor),
),
),
),
@ -474,6 +470,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
height: 100,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Material(
color: Colors.transparent,
@ -484,7 +481,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
: null,
iconSize: 32.0,
icon: Icon(Icons.replay_10),
color: Colors.black),
color: Theme.of(context).tabBarTheme.labelColor),
),
_backgroundAudioPlaying
? Material(
@ -498,7 +495,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
: null,
iconSize: 40.0,
icon: Icon(Icons.pause_circle_filled),
color: Colors.black),
color:
Theme.of(context).tabBarTheme.labelColor),
)
: Material(
color: Colors.transparent,
@ -511,7 +509,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
},
iconSize: 40.0,
icon: Icon(Icons.play_circle_filled),
color: Colors.black),
color:
Theme.of(context).tabBarTheme.labelColor),
),
Material(
color: Colors.transparent,
@ -522,7 +521,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
: null,
iconSize: 32.0,
icon: Icon(Icons.forward_30),
color: Colors.black),
color: Theme.of(context).tabBarTheme.labelColor),
),
],
),
@ -533,7 +532,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
margin: EdgeInsets.symmetric(vertical: 10.0),
padding: EdgeInsets.symmetric(horizontal: 10.0),
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
child: Row(
@ -547,10 +546,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
child: Container(
height: 30.0,
width: 30.0,
color: Colors.white,
child: Image.file(
File("${episode.imagePath}"))
),
child: Image.file(File("${episode.imagePath}"))),
),
),
Spacer(),
@ -565,17 +561,31 @@ class _PlayerWidgetState extends State<PlayerWidget> {
))
]),
);
Widget _miniPanel(double width) => Container(
Widget _miniPanel(double width, BuildContext context) {
var color = json.decode(episode?.primaryColor);
if (color) {
if (Theme.of(context).brightness == Brightness.light) {
_c = (color[0] > 200 && color[1] > 200 && color[2] > 200)
? Color.fromRGBO(
(255 - color[0]), 255 - color[1], 255 - color[2], 1.0)
: Color.fromRGBO(color[0], color[1], color[2], 1.0);
} else {
_c = (color[0] < 50 && color[1] < 50 && color[2] < 50)
? Color.fromRGBO(
(255 - color[0]), 255 - color[1], 255 - color[2], 1.0)
: Color.fromRGBO(color[0], color[1], color[2], 1.0);
}
}
return Container(
height: 60,
color: Colors.grey[100],
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
color: Theme.of(context).primaryColor,
child:
Column(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
SizedBox(
height: 2,
child: LinearProgressIndicator(
value: _seekSliderValue,
backgroundColor: Colors.grey[100],
backgroundColor: Theme.of(context).primaryColor,
valueColor: AlwaysStoppedAnimation<Color>(_c),
)),
Expanded(
@ -603,8 +613,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
startPadding: 30.0,
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.linear,
decelerationDuration:
Duration(milliseconds: 500),
decelerationDuration: Duration(milliseconds: 500),
decelerationCurve: Curves.easeOut,
)
: Text(
@ -622,7 +631,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
child: _remoteAudioLoading
? Text(
'Buffring...',
style: TextStyle(color: Colors.blue),
style:
TextStyle(color: Theme.of(context).accentColor),
)
: Row(
children: <Widget>[
@ -658,7 +668,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
: null,
iconSize: 25.0,
icon: Icon(Icons.pause_circle_filled),
color: Colors.black),
color:
Theme.of(context).tabBarTheme.labelColor),
)
: Material(
color: Colors.transparent,
@ -670,7 +681,8 @@ class _PlayerWidgetState extends State<PlayerWidget> {
},
iconSize: 25.0,
icon: Icon(Icons.play_circle_filled),
color: Colors.black),
color:
Theme.of(context).tabBarTheme.labelColor),
),
Material(
color: Colors.transparent,
@ -680,7 +692,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
: null,
iconSize: 25.0,
icon: Icon(Icons.forward_30),
color: Colors.black),
color: Theme.of(context).tabBarTheme.labelColor),
),
],
),
@ -691,12 +703,16 @@ class _PlayerWidgetState extends State<PlayerWidget> {
),
]),
);
}
@override
Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width;
return !_isLoading
? Center()
: AudioPanel(
miniPanel: _miniPanel(_width), expandedPanel: _expandedPanel());
miniPanel: _miniPanel(_width, context),
expandedPanel: _expandedPanel(context));
}
}

View File

@ -46,7 +46,7 @@ class _AudioPanelState extends State<AudioPanel>
child: GestureDetector(
onTap: () => _backToMini(),
child: Container(
color: Colors.white.withOpacity(0.5),
color: Theme.of(context).scaffoldBackgroundColor.withOpacity(0.5),
),
),
)
@ -64,7 +64,7 @@ class _AudioPanelState extends State<AudioPanel>
: (_animation.value <= minSize) ? minSize : _animation.value,
child: _animation.value < minSize + 30
? Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
child: Opacity(
opacity: _animation.value > minSize
? (minSize + 30 - _animation.value) / 40
@ -75,7 +75,7 @@ class _AudioPanelState extends State<AudioPanel>
),
)
: Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
child: SingleChildScrollView(
child: Opacity(
opacity: _animation.value < (maxSize - 50)

View File

@ -87,9 +87,10 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
EdgeInsets.symmetric(horizontal: 15.0),
child: Text(
groups[_groupIndex].name,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red[300]),
style: Theme.of(context)
.textTheme
.bodyText1
.copyWith(color: Colors.red[300]),
)),
Spacer(),
Container(
@ -106,19 +107,22 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
child: Container(
height: 30,
padding: EdgeInsets.all(5.0),
child: Text('See All',
style: TextStyle(
color: Colors.red[300],
fontWeight: FontWeight.bold,
child: Text(
'See All',
style: Theme.of(context)
.textTheme
.bodyText1
.copyWith(
color: Theme.of(context)
.accentColor),
)),
),
),
),
],
),
),
Container(
color: Colors.white10,
// color: Colors.white10,
height: 70,
width: _width,
alignment: Alignment.centerLeft,
@ -153,14 +157,15 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
height: (_width - 20) / 3 + 40,
margin: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
color: Colors.white,
color: Theme.of(context).scaffoldBackgroundColor,
),
child: TabBarView(
children: groups[_groupIndex]
.podcasts
.map<Widget>((PodcastLocal podcastLocal) {
return Container(
decoration: BoxDecoration(color: Colors.grey[100]),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor),
margin: EdgeInsets.symmetric(horizontal: 5.0),
key: ObjectKey(podcastLocal.title),
child: PodcastPreview(
@ -193,18 +198,21 @@ class _PodcastPreviewState extends State<PodcastPreview> {
}
Color _c;
@override
void initState() {
super.initState();
Widget build(BuildContext context) {
var color = json.decode(widget.podcastLocal.primaryColor);
if (Theme.of(context).brightness == Brightness.light) {
(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(color[0], color[1], color[2], 1.0);
} else {
(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(color[0], color[1], color[2], 1.0);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
@ -294,10 +302,18 @@ class ShowEpisode extends StatelessWidget {
(BuildContext context, int index) {
Color _c;
var color = json.decode(podcast[index].primaryColor);
if (Theme.of(context).brightness == Brightness.light) {
(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(color[0], color[1], color[2], 1.0);
} else {
(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(color[0], color[1], color[2], 1.0);
}
return InkWell(
onTap: () {
Navigator.push(
@ -315,12 +331,12 @@ class ShowEpisode extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(5.0)),
color: Theme.of(context).scaffoldBackgroundColor,
border: Border.all(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
width: 3.0,
),
boxShadow: [
BoxShadow(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
blurRadius: 1.0,
spreadRadius: 0.5,
),

View File

@ -12,11 +12,16 @@ class MainTab extends StatefulWidget {
class _MainTabState extends State<MainTab> with TickerProviderStateMixin {
TabController _controller;
Decoration getIndicator() {
return const UnderlineTabIndicator(
borderSide: BorderSide(color: Colors.red, width: 2),
insets: EdgeInsets.only(left:10.0,right: 10.0, top:10.0,)
);}
Decoration getIndicator(BuildContext context) {
return UnderlineTabIndicator(
borderSide: BorderSide(color: Theme.of(context).accentColor, width: 2),
insets: EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 10.0,
));
}
@override
void initState() {
super.initState();
@ -41,16 +46,22 @@ class _MainTabState extends State<MainTab> with TickerProviderStateMixin {
alignment: Alignment.centerLeft,
child: TabBar(
isScrollable: true,
labelPadding:
EdgeInsets.all(10.0),
labelPadding: EdgeInsets.all(10.0),
controller: _controller,
labelColor: Colors.red,
unselectedLabelColor: Colors.black,
indicator: getIndicator(),
indicator: getIndicator(context),
tabs: <Widget>[
Text('Recent Update',style: TextStyle(fontWeight: FontWeight.bold),),
Text('Favorites',style: TextStyle(fontWeight: FontWeight.bold),),
Text('Downloads',style: TextStyle(fontWeight: FontWeight.bold),),
Text(
'Recent Update',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
'Favorites',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
'Downloads',
style: TextStyle(fontWeight: FontWeight.bold),
),
],
),
),
@ -96,7 +107,13 @@ class _RecentUpdateState extends State<RecentUpdate> {
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return (snapshot.hasData)
? EpisodeGrid(podcast: snapshot.data, showDownload: false, showFavorite: false, showNumber: false, heroTag: 'recent',)
? EpisodeGrid(
podcast: snapshot.data,
showDownload: false,
showFavorite: false,
showNumber: false,
heroTag: 'recent',
)
: Center(child: CircularProgressIndicator());
},
);
@ -111,7 +128,7 @@ class MyFavorite extends StatefulWidget {
class _MyFavoriteState extends State<MyFavorite> {
Future<List<EpisodeBrief>> _getLikedRssItem() async {
var dbHelper = DBHelper();
List<EpisodeBrief> episodes =await dbHelper.getLikedRssItem();
List<EpisodeBrief> episodes = await dbHelper.getLikedRssItem();
return episodes;
}
@ -122,23 +139,28 @@ class _MyFavoriteState extends State<MyFavorite> {
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return (snapshot.hasData)
? EpisodeGrid(podcast: snapshot.data, showDownload: false, showFavorite: false, showNumber: false, heroTag: 'favorite',)
? EpisodeGrid(
podcast: snapshot.data,
showDownload: false,
showFavorite: false,
showNumber: false,
heroTag: 'favorite',
)
: Center(child: CircularProgressIndicator());
},
);
}
}
class MyDownload extends StatefulWidget {
class MyDownload extends StatefulWidget {
@override
_MyDownloadState createState() => _MyDownloadState();
}
class _MyDownloadState extends State<MyDownload> {
Future<List<EpisodeBrief>> _getDownloadedRssItem() async {
var dbHelper = DBHelper();
List<EpisodeBrief> episodes =await dbHelper.getDownloadedRssItem();
List<EpisodeBrief> episodes = await dbHelper.getDownloadedRssItem();
return episodes;
}
@ -149,10 +171,15 @@ class _MyDownloadState extends State<MyDownload> {
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return (snapshot.hasData)
? EpisodeGrid(podcast: snapshot.data, showDownload: true, showFavorite: false, showNumber: false, heroTag: 'download',)
? EpisodeGrid(
podcast: snapshot.data,
showDownload: true,
showFavorite: false,
showNumber: false,
heroTag: 'download',
)
: Center(child: CircularProgressIndicator());
},
);
}
}

View File

@ -31,4 +31,15 @@ class KeyValueStorage {
json.encode(
{'groups': groupList.map((group) => group.toJson()).toList()}));
}
Future<bool> saveTheme(int setting) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setInt(key, setting);
}
Future<int> getTheme() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
if(prefs.getInt(key) == null) await prefs.setInt(key, 0);
return prefs.getInt(key);
}
}

View File

@ -28,14 +28,35 @@ void main() async {
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(statusBarColor: Colors.grey[100]));
var theme = Provider.of<SettingState>(context).theme;
return MaterialApp(
themeMode: theme == 0
? ThemeMode.system
: theme == 1 ? ThemeMode.dark : ThemeMode.light,
debugShowCheckedModeBanner: false,
title: 'TsacDop',
theme: ThemeData(
primaryColor: Colors.white,
accentColorBrightness: Brightness.dark,
primaryColor: Colors.grey[100],
accentColor: Colors.blue[400],
primaryColorLight: Colors.white,
primaryColorDark: Colors.grey[300],
dialogBackgroundColor: Colors.white,
backgroundColor: Colors.grey[100],
appBarTheme: AppBarTheme(
color: Colors.grey[100],
elevation: 0,
),
textTheme: TextTheme(
headline1: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
bodyText2: TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal),
),
tabBarTheme: TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[400],
),
),
darkTheme: ThemeData.dark(),
home: MyHomePage(),
);
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:tsacdop/class/podcastlocal.dart';
@ -21,8 +22,8 @@ class _PodcastDetailState extends State<PodcastDetail> {
Future _updateRssItem(PodcastLocal podcastLocal) async {
var dbHelper = DBHelper();
final result = await dbHelper.updatePodcastRss(podcastLocal);
result == 0 ?
Fluttertoast.showToast(
result == 0
? Fluttertoast.showToast(
msg: 'No Update',
gravity: ToastGravity.TOP,
)
@ -30,24 +31,30 @@ class _PodcastDetailState extends State<PodcastDetail> {
msg: 'Updated $result Episodes',
gravity: ToastGravity.TOP,
);
if(mounted) setState(() {});
if (mounted) setState(() {});
}
Future<List<EpisodeBrief>> _getRssItem(PodcastLocal podcastLocal) async {
print(podcastLocal.id);
var dbHelper = DBHelper();
List<EpisodeBrief> episodes = await
dbHelper.getRssItem(podcastLocal.id);
List<EpisodeBrief> episodes = await dbHelper.getRssItem(podcastLocal.id);
return episodes;
}
@override
Widget build(BuildContext context) {
return Scaffold(
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(widget.podcastLocal.title,),
elevation: 0.0,
backgroundColor: Colors.grey[100],
title: Text(
widget.podcastLocal.title,
),
centerTitle: true,
),
body: RefreshIndicator(
@ -59,10 +66,18 @@ class _PodcastDetailState extends State<PodcastDetail> {
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return (snapshot.hasData)
? EpisodeGrid(podcast: snapshot.data, showDownload: true, showFavorite: true, showNumber: true, heroTag: 'podcast',)
? EpisodeGrid(
podcast: snapshot.data,
showDownload: true,
showFavorite: true,
showNumber: true,
heroTag: 'podcast',
)
: Center(child: CircularProgressIndicator());
},
)),
),
),
);
}
}

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/podcast_group.dart';
@ -38,12 +39,13 @@ class _PodcastGroupListState extends State<PodcastGroupList> {
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
boxShadow: [BoxShadow(
boxShadow: [
BoxShadow(
color: Colors.grey[700],
blurRadius: 5,
offset: Offset(1, 1),
),]
),
]),
alignment: Alignment.center,
child: Text(
'Save',
@ -68,10 +70,10 @@ class _PodcastGroupListState extends State<PodcastGroupList> {
Widget build(BuildContext context) {
return widget.group.podcastList.length == 0
? Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
)
: Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
child: Stack(
children: <Widget>[
ReorderableListView(
@ -89,7 +91,8 @@ class _PodcastGroupListState extends State<PodcastGroupList> {
children: widget.group.podcasts
.map<Widget>((PodcastLocal podcastLocal) {
return Container(
decoration: BoxDecoration(color: Colors.grey[100]),
decoration:
BoxDecoration(color: Theme.of(context).primaryColor),
key: ObjectKey(podcastLocal.title),
child: PodcastCard(
podcastLocal: podcastLocal,
@ -147,10 +150,17 @@ class _PodcastCardState extends State<PodcastCard> {
@override
Widget build(BuildContext context) {
var color = json.decode(widget.podcastLocal.primaryColor);
if (Theme.of(context).brightness == Brightness.light) {
(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(color[0], color[1], color[2], 1.0);
} else {
(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(color[0], color[1], color[2], 1.0);
}
double _width = MediaQuery.of(context).size.width;
var _groupList = Provider.of<GroupList>(context);
_belongGroups = _groupList.getPodcastGroup(widget.podcastLocal.id);
@ -219,6 +229,12 @@ class _PodcastCardState extends State<PodcastCard> {
onPressed: () {
showDialog(
context: context,
child: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor:
Colors.black.withOpacity(0.5),
statusBarColor: Colors.red,
),
child: AlertDialog(
elevation: 2.0,
title: Text('Remove confirm'),
@ -231,7 +247,8 @@ class _PodcastCardState extends State<PodcastCard> {
),
FlatButton(
onPressed: () {
_groupList.removePodcast(widget.podcastLocal.id);
_groupList
.removePodcast(widget.podcastLocal.id);
Navigator.of(context).pop();
},
child: Text(
@ -240,6 +257,7 @@ class _PodcastCardState extends State<PodcastCard> {
),
)
],
),
));
},
),
@ -251,10 +269,12 @@ class _PodcastCardState extends State<PodcastCard> {
: Container(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
border: Border(
bottom: BorderSide(color: Colors.grey[300]),
top: BorderSide(color: Colors.grey[300]))),
bottom: BorderSide(
color: Theme.of(context).primaryColorDark),
top: BorderSide(
color: Theme.of(context).primaryColorDark))),
height: 50,
child: _addGroup
? Row(

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/podcast_group.dart';
@ -52,7 +53,6 @@ class _AboutPodcastState extends State<AboutPodcast> {
_groupList.removePodcast(widget.podcastLocal.id);
Navigator.of(context).pop();
},
color: Colors.grey[200],
textColor: Colors.red,
child: Text(
'UNSUBSCRIBE',
@ -83,7 +83,6 @@ class PodcastList extends StatefulWidget {
}
class _PodcastListState extends State<PodcastList> {
Future<List<PodcastLocal>> getPodcastLocal() async {
var dbHelper = DBHelper();
var podcastList = await dbHelper.getPodcastLocalAll();
@ -93,15 +92,20 @@ class _PodcastListState extends State<PodcastList> {
@override
Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width;
return Scaffold(
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Podcasts'),
centerTitle: true,
backgroundColor: Colors.grey[100],
elevation: 0,
),
body: Container(
color: Colors.grey[100],
color: Theme.of(context).primaryColor,
child: FutureBuilder<List<PodcastLocal>>(
future: getPodcastLocal(),
builder: (context, snapshot) {
@ -112,7 +116,8 @@ class _PodcastListState extends State<PodcastList> {
SliverPadding(
padding: const EdgeInsets.all(10.0),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.8,
crossAxisCount: 3,
),
@ -131,7 +136,8 @@ class _PodcastListState extends State<PodcastList> {
onLongPress: () {
showDialog(
context: context,
builder: (BuildContext context) => AboutPodcast(
builder: (BuildContext context) =>
AboutPodcast(
podcastLocal: snapshot.data[index]),
).then((_) => setState(() {}));
},
@ -158,10 +164,7 @@ class _PodcastListState extends State<PodcastList> {
child: Text(
snapshot.data[index].title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.0,
color: Colors.black.withOpacity(0.5),
),
style: Theme.of(context).textTheme.bodyText1,
maxLines: 2,
),
),
@ -181,21 +184,8 @@ class _PodcastListState extends State<PodcastList> {
},
),
),
);
}
}
class Podcast extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[100],
elevation: 0,
centerTitle: true,
title: Text('Podcasts'),
),
body: Container(child: PodcastList()),
),
);
}
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/podcast_group.dart';
import 'package:tsacdop/podcasts/podcastgroup.dart';
@ -26,13 +27,23 @@ class _PodcastManageState extends State<PodcastManage> {
@override
Widget build(BuildContext context) {
return Scaffold(
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
statusBarColor: Theme.of(context).primaryColor,
),
child: SafeArea(
child: Scaffold(
appBar: AppBar(
elevation: 0,
centerTitle: true,
backgroundColor: Colors.grey[100],
title: Text('Groups'),
actions: <Widget>[
IconButton(
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) => AddGroup()),
icon: Icon(Icons.add)),
OrderMenu(),
],
),
@ -47,17 +58,13 @@ class _PodcastManageState extends State<PodcastManage> {
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 4,
child: Container(
Container(
height: 50,
padding: EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
child: TabBar(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[500],
// labelColor: Colors.black,
// unselectedLabelColor: Colors.grey[500],
labelPadding: EdgeInsets.all(5.0),
indicator: getIndicator(),
isScrollable: true,
@ -65,13 +72,16 @@ class _PodcastManageState extends State<PodcastManage> {
return Tab(
child: Container(
height: 30.0,
padding: EdgeInsets.symmetric(
horizontal: 10.0),
padding:
EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.all(
Radius.circular(15)),
color: Theme.of(context).brightness ==
Brightness.light
? Theme.of(context).primaryColorDark
: Colors.grey[800],
borderRadius:
BorderRadius.all(Radius.circular(15)),
),
child: Text(
group.name,
@ -80,18 +90,6 @@ class _PodcastManageState extends State<PodcastManage> {
}).toList(),
),
),
),
Expanded(
flex: 1,
child: IconButton(
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) =>
AddGroup()),
icon: Icon(Icons.add)),
),
],
),
Expanded(
child: Container(
child: TabBarView(
@ -106,6 +104,8 @@ class _PodcastManageState extends State<PodcastManage> {
],
));
}),
),
),
);
}
}
@ -166,7 +166,12 @@ class _AddGroupState extends State<AddGroup> {
Widget build(BuildContext context) {
var groupList = Provider.of<GroupList>(context);
List list = groupList.groups.map((e) => e.name).toList();
return AlertDialog(
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: Colors.black.withOpacity(0.5),
statusBarColor: Colors.red,
),
child: AlertDialog(
elevation: 1,
contentPadding: EdgeInsets.symmetric(horizontal: 20),
titlePadding: EdgeInsets.only(top: 20, left: 20, right: 20, bottom: 20),
@ -176,7 +181,7 @@ class _AddGroupState extends State<AddGroup> {
onPressed: () => Navigator.of(context).pop(),
child: Text(
'CANCEL',
style: TextStyle(color: Colors.grey[700]),
style: TextStyle(color: Colors.grey[600]),
),
),
FlatButton(
@ -202,7 +207,7 @@ class _AddGroupState extends State<AddGroup> {
hintStyle: TextStyle(fontSize: 18),
filled: true,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white, width: 2.0),
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2.0),
@ -227,6 +232,7 @@ class _AddGroupState extends State<AddGroup> {
),
],
),
),
);
}
}

View File

@ -45,10 +45,17 @@ class EpisodeGrid extends StatelessWidget {
(BuildContext context, int index) {
Color _c;
var color = json.decode(podcast[index].primaryColor);
if (Theme.of(context).brightness == Brightness.light) {
(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(color[0], color[1], color[2], 1.0);
} else {
(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(color[0], color[1], color[2], 1.0);
}
return Material(
color: Colors.transparent,
child: InkWell(
@ -67,13 +74,16 @@ class EpisodeGrid extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(5.0)),
color: Theme.of(context).scaffoldBackgroundColor,
border: Border.all(
color: Colors.grey[100],
color:
Theme.of(context).brightness == Brightness.light
? Theme.of(context).primaryColor
: Theme.of(context).scaffoldBackgroundColor,
width: 3.0,
),
boxShadow: [
BoxShadow(
color: Colors.grey[100],
blurRadius: 1.0,
color: Theme.of(context).primaryColor,
blurRadius: 0.5,
spreadRadius: 0.5,
),
]),