fix: update material you theme
This commit is contained in:
parent
92dd3dd34e
commit
d032979263
|
@ -104,7 +104,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -120,6 +120,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||||
widget.episodeItem!.cardColor(context),
|
widget.episodeItem!.cardColor(context),
|
||||||
floating: true,
|
floating: true,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
|
scrolledUnderElevation: 0,
|
||||||
title: _showTitle
|
title: _showTitle
|
||||||
? Text(
|
? Text(
|
||||||
widget.episodeItem?.title ?? '',
|
widget.episodeItem?.title ?? '',
|
||||||
|
@ -195,8 +196,8 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||||
s.minsCount(
|
s.minsCount(
|
||||||
widget.episodeItem!.duration! ~/ 60,
|
widget.episodeItem!.duration! ~/ 60,
|
||||||
),
|
),
|
||||||
style:
|
style: TextStyle(
|
||||||
TextStyle(color: context.onPrimary),
|
color: context.background),
|
||||||
)),
|
)),
|
||||||
if (widget.episodeItem!.enclosureLength !=
|
if (widget.episodeItem!.enclosureLength !=
|
||||||
null &&
|
null &&
|
||||||
|
@ -214,7 +215,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||||
child: Text(
|
child: Text(
|
||||||
'${widget.episodeItem!.enclosureLength! ~/ 1000000}MB',
|
'${widget.episodeItem!.enclosureLength! ~/ 1000000}MB',
|
||||||
style:
|
style:
|
||||||
TextStyle(color: context.onPrimary),
|
TextStyle(color: context.background),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FutureBuilder<PlayHistory>(
|
FutureBuilder<PlayHistory>(
|
||||||
|
|
|
@ -30,16 +30,16 @@ class AboutApp extends StatelessWidget {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: context.onPrimary,
|
statusBarColor: context.background,
|
||||||
statusBarIconBrightness: context.iconBrightness,
|
statusBarIconBrightness: context.iconBrightness,
|
||||||
systemNavigationBarColor: context.onPrimary,
|
systemNavigationBarColor: context.background,
|
||||||
systemNavigationBarIconBrightness: context.iconBrightness,
|
systemNavigationBarIconBrightness: context.iconBrightness,
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
title: Text(s.homeToprightMenuAbout),
|
title: Text(s.homeToprightMenuAbout),
|
||||||
scrolledUnderElevation: 1,
|
scrolledUnderElevation: 1,
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
|
|
|
@ -97,8 +97,8 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
systemNavigationBarIconBrightness: context.brightness,
|
systemNavigationBarIconBrightness: context.brightness,
|
||||||
statusBarIconBrightness: context.iconBrightness,
|
statusBarIconBrightness: context.iconBrightness,
|
||||||
systemNavigationBarColor: context.onPrimary,
|
systemNavigationBarColor: context.background,
|
||||||
statusBarColor: context.onPrimary,
|
statusBarColor: context.background,
|
||||||
),
|
),
|
||||||
child: WillPopScope(
|
child: WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
|
@ -115,7 +115,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SafeArea(
|
SafeArea(
|
||||||
|
@ -163,8 +163,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
|
||||||
Theme.of(context).brightness ==
|
Theme.of(context).brightness ==
|
||||||
Brightness.light
|
Brightness.light
|
||||||
? settings.setTheme = ThemeMode.dark
|
? settings.setTheme = ThemeMode.dark
|
||||||
: settings.setTheme =
|
: settings.setTheme = ThemeMode.light
|
||||||
ThemeMode.light
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Tsacdop',
|
'Tsacdop',
|
||||||
|
|
|
@ -94,113 +94,115 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onVerticalDragEnd: (event) {
|
onVerticalDragEnd: (event) {
|
||||||
if (event.primaryVelocity! > 200) {
|
if (event.primaryVelocity! > 200) {
|
||||||
if (groups.length == 1) {
|
if (groups.length == 1) {
|
||||||
Fluttertoast.showToast(
|
Fluttertoast.showToast(
|
||||||
msg: s.addSomeGroups,
|
msg: s.addSomeGroups,
|
||||||
gravity: ToastGravity.BOTTOM,
|
gravity: ToastGravity.BOTTOM,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
(_groupIndex != 0)
|
(_groupIndex != 0)
|
||||||
? _groupIndex--
|
? _groupIndex--
|
||||||
: _groupIndex = groups.length - 1;
|
: _groupIndex = groups.length - 1;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (event.primaryVelocity! < -200) {
|
|
||||||
if (groups.length == 1) {
|
|
||||||
Fluttertoast.showToast(
|
|
||||||
msg: s.addSomeGroups,
|
|
||||||
gravity: ToastGravity.BOTTOM,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (mounted) {
|
|
||||||
setState(
|
|
||||||
() {
|
|
||||||
(_groupIndex < groups.length - 1)
|
|
||||||
? _groupIndex++
|
|
||||||
: _groupIndex = 0;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
} else if (event.primaryVelocity! < -200) {
|
||||||
child: Column(
|
if (groups.length == 1) {
|
||||||
children: <Widget>[
|
Fluttertoast.showToast(
|
||||||
SizedBox(
|
msg: s.addSomeGroups,
|
||||||
height: 30,
|
gravity: ToastGravity.BOTTOM,
|
||||||
child: Row(
|
);
|
||||||
children: <Widget>[
|
} else {
|
||||||
Padding(
|
if (mounted) {
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15.0),
|
setState(
|
||||||
child: Text(
|
() {
|
||||||
groups[_groupIndex]!.name!,
|
(_groupIndex < groups.length - 1)
|
||||||
style: context.textTheme.bodyText1!
|
? _groupIndex++
|
||||||
.copyWith(color: context.accentColor),
|
: _groupIndex = 0;
|
||||||
),
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
SizedBox(
|
||||||
|
height: 30,
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15.0),
|
||||||
|
child: Text(
|
||||||
|
groups[_groupIndex]!.name!,
|
||||||
|
style: context.textTheme.bodyText1!
|
||||||
|
.copyWith(color: context.accentColor),
|
||||||
),
|
),
|
||||||
Spacer(),
|
),
|
||||||
Padding(
|
Spacer(),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
Padding(
|
||||||
child: InkWell(
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
onTap: () {
|
child: InkWell(
|
||||||
if (!import) {
|
borderRadius: BorderRadius.circular(15),
|
||||||
Navigator.push(
|
onTap: () {
|
||||||
context,
|
if (!import) {
|
||||||
SlideLeftRoute(
|
Navigator.push(
|
||||||
page: context
|
context,
|
||||||
.read<SettingState>()
|
SlideLeftRoute(
|
||||||
.openAllPodcastDefalt!
|
page: context
|
||||||
? PodcastList()
|
.read<SettingState>()
|
||||||
: PodcastManage(),
|
.openAllPodcastDefalt!
|
||||||
),
|
? PodcastList()
|
||||||
);
|
: PodcastManage(),
|
||||||
}
|
),
|
||||||
},
|
);
|
||||||
onLongPress: () {
|
}
|
||||||
if (!import) {
|
},
|
||||||
Navigator.push(
|
onLongPress: () {
|
||||||
context,
|
if (!import) {
|
||||||
SlideLeftRoute(page: PodcastList()),
|
Navigator.push(
|
||||||
);
|
context,
|
||||||
}
|
SlideLeftRoute(page: PodcastList()),
|
||||||
},
|
);
|
||||||
borderRadius: BorderRadius.circular(5),
|
}
|
||||||
child: Padding(
|
},
|
||||||
padding: const EdgeInsets.all(5.0),
|
child: Padding(
|
||||||
child: Text(
|
padding: const EdgeInsets.all(5.0),
|
||||||
s.homeGroupsSeeAll,
|
child: Text(
|
||||||
style: context.textTheme.bodyText1!
|
s.homeGroupsSeeAll,
|
||||||
.copyWith(
|
style:
|
||||||
color: import
|
context.textTheme.bodyText1!.copyWith(
|
||||||
? context.primaryColorDark
|
color: import
|
||||||
: context.accentColor),
|
? context.primaryColorDark
|
||||||
|
: context.accentColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
Container(
|
),
|
||||||
height: 70,
|
Container(
|
||||||
color: context.background,
|
height: 70,
|
||||||
child: Row(
|
color: context.background,
|
||||||
children: <Widget>[
|
child: Row(
|
||||||
_circleContainer(context),
|
children: <Widget>[
|
||||||
_circleContainer(context),
|
_circleContainer(context),
|
||||||
_circleContainer(context)
|
_circleContainer(context),
|
||||||
],
|
_circleContainer(context)
|
||||||
)),
|
],
|
||||||
],
|
)),
|
||||||
)),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
height: (width - 20) / 3 + 40,
|
height: (width - 20) / 3 + 40,
|
||||||
color: context.onPrimary,
|
color: context.background,
|
||||||
margin: EdgeInsets.symmetric(horizontal: 15),
|
margin: EdgeInsets.symmetric(horizontal: 15),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: _groupIndex == 0
|
child: _groupIndex == 0
|
||||||
|
@ -297,39 +299,39 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!import) {
|
if (!import) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
SlideLeftRoute(
|
SlideLeftRoute(
|
||||||
page: context
|
page: context
|
||||||
.read<SettingState>()
|
.read<SettingState>()
|
||||||
.openAllPodcastDefalt!
|
.openAllPodcastDefalt!
|
||||||
? PodcastList()
|
? PodcastList()
|
||||||
: PodcastManage()),
|
: PodcastManage()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (!import) {
|
if (!import) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
SlideLeftRoute(page: PodcastList()),
|
SlideLeftRoute(page: PodcastList()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
s.homeGroupsSeeAll,
|
s.homeGroupsSeeAll,
|
||||||
style: context.textTheme.bodyText1!
|
style: context.textTheme.bodyText1!.copyWith(
|
||||||
.copyWith(
|
color: import
|
||||||
color: import
|
? context.primaryColorDark
|
||||||
? context.primaryColorDark
|
: context.accentColor),
|
||||||
: context.accentColor),
|
),
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -338,7 +340,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
height: 70,
|
height: 70,
|
||||||
width: width,
|
width: width,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
color: context.onPrimary,
|
color: context.background,
|
||||||
child: TabBar(
|
child: TabBar(
|
||||||
labelPadding: EdgeInsets.fromLTRB(6.0, 5.0, 6.0, 10.0),
|
labelPadding: EdgeInsets.fromLTRB(6.0, 5.0, 6.0, 10.0),
|
||||||
indicator: CircleTabIndicator(
|
indicator: CircleTabIndicator(
|
||||||
|
@ -370,47 +372,45 @@ class _ScrollPodcastsState extends State<ScrollPodcasts>
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: (width - 20) / 3 + 40,
|
height: (width - 20) / 3 + 40,
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: context.background,
|
color: context.background,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
child: ScrollConfiguration(
|
child: TabBarView(
|
||||||
behavior: NoGrowBehavior(),
|
children: groups[_groupIndex]!.podcasts.map<Widget>(
|
||||||
child: TabBarView(
|
(podcastLocal) {
|
||||||
children: groups[_groupIndex]!.podcasts.map<Widget>(
|
return Container(
|
||||||
(podcastLocal) {
|
decoration: BoxDecoration(
|
||||||
return Container(
|
color: context.brightness == Brightness.light
|
||||||
decoration: BoxDecoration(
|
? context.primaryColor
|
||||||
color: context.brightness == Brightness.light
|
: Colors.black12),
|
||||||
? context.primaryColor
|
margin: EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
: Colors.black12),
|
key: ObjectKey(podcastLocal.title),
|
||||||
margin: EdgeInsets.symmetric(horizontal: 5.0),
|
child: Material(
|
||||||
key: ObjectKey(podcastLocal.title),
|
color: Colors.transparent,
|
||||||
child: Material(
|
child: InkWell(
|
||||||
color: Colors.transparent,
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: InkWell(
|
onTap: () {
|
||||||
onTap: () {
|
Navigator.push(
|
||||||
Navigator.push(
|
context,
|
||||||
context,
|
HidePlayerRoute(
|
||||||
HidePlayerRoute(
|
PodcastDetail(
|
||||||
PodcastDetail(
|
podcastLocal: podcastLocal,
|
||||||
podcastLocal: podcastLocal,
|
),
|
||||||
),
|
PodcastDetail(
|
||||||
PodcastDetail(
|
podcastLocal: podcastLocal, hide: true),
|
||||||
podcastLocal: podcastLocal,
|
duration: Duration(milliseconds: 300),
|
||||||
hide: true),
|
),
|
||||||
duration: Duration(milliseconds: 300),
|
);
|
||||||
));
|
},
|
||||||
},
|
child: PodcastPreview(
|
||||||
child: PodcastPreview(
|
podcastLocal: podcastLocal,
|
||||||
podcastLocal: podcastLocal,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
).toList(),
|
},
|
||||||
),
|
).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -494,7 +494,9 @@ class _PodcastPreviewState extends State<PodcastPreview> {
|
||||||
episodes: snapshot.data,
|
episodes: snapshot.data,
|
||||||
podcastLocal: widget.podcastLocal,
|
podcastLocal: widget.podcastLocal,
|
||||||
)
|
)
|
||||||
: Padding(padding: const EdgeInsets.all(5.0));
|
: Padding(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -561,8 +563,8 @@ class ShowEpisode extends StatelessWidget {
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
childAspectRatio: 1.5,
|
childAspectRatio: 1.5,
|
||||||
crossAxisCount: 2,
|
crossAxisCount: 2,
|
||||||
mainAxisSpacing: 8.0,
|
mainAxisSpacing: 20,
|
||||||
crossAxisSpacing: 6.0,
|
crossAxisSpacing: 14,
|
||||||
),
|
),
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, index) {
|
(context, index) {
|
||||||
|
|
|
@ -27,17 +27,6 @@ class DiscoveryPageState extends State<DiscoveryPage> {
|
||||||
final List<OnlinePodcast> _podcastList = [];
|
final List<OnlinePodcast> _podcastList = [];
|
||||||
Future? _searchTopPodcast;
|
Future? _searchTopPodcast;
|
||||||
Future? _getIfHideDiscovery;
|
Future? _getIfHideDiscovery;
|
||||||
Future<List<String?>?> _getSearchHistory() {
|
|
||||||
final storage = KeyValueStorage(searchHistoryKey);
|
|
||||||
final history = storage.getStringList();
|
|
||||||
return history;
|
|
||||||
}
|
|
||||||
|
|
||||||
void backToHome() {
|
|
||||||
setState(() {
|
|
||||||
_selectedGenre = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -46,95 +35,257 @@ class DiscoveryPageState extends State<DiscoveryPage> {
|
||||||
_getIfHideDiscovery = _getHideDiscovery();
|
_getIfHideDiscovery = _getHideDiscovery();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _loadTopPodcasts() => Container(
|
@override
|
||||||
decoration: BoxDecoration(
|
Widget build(BuildContext context) {
|
||||||
borderRadius: BorderRadius.circular(10), color: context.primaryColor),
|
return FutureBuilder<bool>(
|
||||||
width: 120,
|
future: _getIfHideDiscovery!.then((value) => value as bool),
|
||||||
margin: EdgeInsets.fromLTRB(10, 10, 0, 10),
|
builder: (context, snapshot) {
|
||||||
padding: EdgeInsets.all(4),
|
if (!snapshot.hasData) {
|
||||||
alignment: Alignment.topCenter,
|
return Center();
|
||||||
child: Column(
|
} else if (snapshot.data! || environment['apiKey'] == '') {
|
||||||
children: [
|
return SingleChildScrollView(
|
||||||
Expanded(
|
|
||||||
flex: 2,
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
height: 50,
|
|
||||||
width: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
color: context.primaryColorDark,
|
|
||||||
),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 2,
|
|
||||||
child: LinearProgressIndicator(value: 0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
_historyList(),
|
||||||
width: 80,
|
SizedBox(
|
||||||
height: context.textTheme.bodyText1!.fontSize,
|
height: 150,
|
||||||
decoration: BoxDecoration(
|
child: Center(
|
||||||
color: context.primaryColorDark,
|
child: Icon(
|
||||||
borderRadius: BorderRadius.circular(4)),
|
Icons.search,
|
||||||
|
size: 80,
|
||||||
|
color: Colors.grey[400],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
SizedBox(
|
||||||
Container(
|
height: 50,
|
||||||
width: 40,
|
child: Row(
|
||||||
height: context.textTheme.bodyText1!.fontSize,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
decoration: BoxDecoration(
|
children: [
|
||||||
color: context.primaryColorDark,
|
Icon(
|
||||||
borderRadius: BorderRadius.circular(4)),
|
LineIcons.microphone,
|
||||||
|
size: 30,
|
||||||
|
color: Colors.lightBlue,
|
||||||
|
),
|
||||||
|
SizedBox(width: 50),
|
||||||
|
Icon(
|
||||||
|
LineIcons.broadcastTower,
|
||||||
|
size: 30,
|
||||||
|
color: Colors.deepPurple,
|
||||||
|
),
|
||||||
|
SizedBox(width: 50),
|
||||||
|
Icon(
|
||||||
|
LineIcons.rssSquare,
|
||||||
|
size: 30,
|
||||||
|
color: Colors.blueGrey,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(50, 20, 50, 20),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
context.s.searchHelper,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: context.textTheme.headline6!
|
||||||
|
.copyWith(color: Colors.grey[400]),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
Expanded(
|
} else {
|
||||||
flex: 1,
|
return PodcastSlideup(
|
||||||
child: Center(
|
searchEngine: SearchEngine.listenNotes,
|
||||||
child: SizedBox(
|
child: Selector<SearchState, Genre?>(
|
||||||
height: 32,
|
selector: (_, searchState) => searchState.genre,
|
||||||
child: OutlinedButton(
|
builder: (_, genre, __) => IndexedStack(
|
||||||
style: OutlinedButton.styleFrom(
|
index: genre == null ? 0 : 1,
|
||||||
primary: context.accentColor.withOpacity(0.5),
|
children: [
|
||||||
shape: RoundedRectangleBorder(
|
SingleChildScrollView(
|
||||||
borderRadius: BorderRadius.circular(100.0),
|
child: Column(
|
||||||
side: BorderSide(color: Colors.grey[500]!)),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
// highlightedBorderColor: Colors.grey[500],
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// disabledTextColor: Colors.grey[500],
|
children: [
|
||||||
// disabledBorderColor: Colors.grey[500],
|
_historyList(),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: FutureBuilder<List<OnlinePodcast>>(
|
||||||
|
future: _searchTopPodcast!.then(
|
||||||
|
(value) => value as List<OnlinePodcast>),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return ScrollConfiguration(
|
||||||
|
behavior: NoGrowBehavior(),
|
||||||
|
child: ListView(
|
||||||
|
addAutomaticKeepAlives: true,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: snapshot.hasData
|
||||||
|
? snapshot.data!
|
||||||
|
.map<Widget>((podcast) {
|
||||||
|
return _podcastCard(
|
||||||
|
podcast,
|
||||||
|
onTap: () {
|
||||||
|
context
|
||||||
|
.read<SearchState>()
|
||||||
|
.selectedPodcast =
|
||||||
|
podcast;
|
||||||
|
widget.onTap!('');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}).toList()
|
||||||
|
: [
|
||||||
|
_loadTopPodcasts(),
|
||||||
|
_loadTopPodcasts(),
|
||||||
|
_loadTopPodcasts(),
|
||||||
|
_loadTopPodcasts(),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(20, 10, 10, 4),
|
||||||
|
child: Text('Categories',
|
||||||
|
style: context.textTheme.headline6!
|
||||||
|
.copyWith(color: context.accentColor)),
|
||||||
|
),
|
||||||
|
ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: NeverScrollableScrollPhysics(),
|
||||||
|
children: genres
|
||||||
|
.map<Widget>((e) => ListTile(
|
||||||
|
contentPadding:
|
||||||
|
EdgeInsets.fromLTRB(20, 0, 20, 0),
|
||||||
|
onTap: () {
|
||||||
|
widget.onTap!('');
|
||||||
|
context.read<SearchState>().setGenre = e;
|
||||||
|
},
|
||||||
|
title: Text(e.name!,
|
||||||
|
style: context.textTheme.headline6),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: Center(
|
||||||
|
child: Image(
|
||||||
|
image: context.brightness == Brightness.light
|
||||||
|
? AssetImage('assets/listennotes.png')
|
||||||
|
: AssetImage('assets/listennotes_light.png'),
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: Text(context.s.subscribe),
|
),
|
||||||
onPressed: () {}),
|
genre == null ? Center() : _TopPodcastList(genre: genre),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
],
|
}
|
||||||
));
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _loadTopPodcasts() => Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
color: context.primaryColor),
|
||||||
|
width: 120,
|
||||||
|
margin: EdgeInsets.fromLTRB(10, 10, 0, 10),
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
height: 50,
|
||||||
|
width: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 2,
|
||||||
|
child: LinearProgressIndicator(value: 0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 80,
|
||||||
|
height: context.textTheme.bodyText1!.fontSize,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
borderRadius: BorderRadius.circular(4)),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Container(
|
||||||
|
width: 40,
|
||||||
|
height: context.textTheme.bodyText1!.fontSize,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: context.primaryColorDark,
|
||||||
|
borderRadius: BorderRadius.circular(4)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
height: 32,
|
||||||
|
child: OutlinedButton(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
primary: context.accentColor.withOpacity(0.5),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100.0),
|
||||||
|
side: BorderSide(color: Colors.grey[500]!)),
|
||||||
|
// highlightedBorderColor: Colors.grey[500],
|
||||||
|
// disabledTextColor: Colors.grey[500],
|
||||||
|
// disabledBorderColor: Colors.grey[500],
|
||||||
|
),
|
||||||
|
child: Text(context.s.subscribe),
|
||||||
|
onPressed: () {}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Widget _historyList() => FutureBuilder<List<String?>?>(
|
Widget _historyList() => FutureBuilder<List<String?>?>(
|
||||||
future: _getSearchHistory(),
|
future: _getSearchHistory(),
|
||||||
initialData: [],
|
initialData: [],
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||||
final history = snapshot.data!;
|
final history = snapshot.data!;
|
||||||
return Wrap(
|
return Wrap(
|
||||||
direction: Axis.horizontal,
|
direction: Axis.horizontal,
|
||||||
children: history
|
children: history
|
||||||
.map<Widget>((e) => Padding(
|
.map<Widget>(
|
||||||
|
(e) => Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(8, 2, 0, 0),
|
padding: const EdgeInsets.fromLTRB(8, 2, 0, 0),
|
||||||
child: FlatButton.icon(
|
child: TextButton.icon(
|
||||||
color: Colors.accents[history.indexOf(e)].withAlpha(70),
|
style: TextButton.styleFrom(
|
||||||
shape: RoundedRectangleBorder(
|
primary: Colors.accents[history.indexOf(e)],
|
||||||
borderRadius: BorderRadius.circular(100.0),
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100.0),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => widget.onTap!(e),
|
onPressed: () => widget.onTap!(e),
|
||||||
label: Text(e!),
|
label: Text(e!),
|
||||||
|
@ -143,32 +294,32 @@ class DiscoveryPageState extends State<DiscoveryPage> {
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
))
|
),
|
||||||
.toList(),
|
)
|
||||||
);
|
.toList(),
|
||||||
}
|
);
|
||||||
return SizedBox(
|
}
|
||||||
height: 0,
|
return Center();
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
Widget _podcastCard(OnlinePodcast podcast, {VoidCallback? onTap}) {
|
Widget _podcastCard(OnlinePodcast podcast, {VoidCallback? onTap}) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(20),
|
||||||
color: context.primaryColor,
|
color: context.background,
|
||||||
border:
|
border:
|
||||||
Border.all(color: context.textColor.withOpacity(0.1), width: 1)),
|
Border.all(color: context.textColor.withOpacity(0.1), width: 1)),
|
||||||
width: 120,
|
width: 140,
|
||||||
margin: EdgeInsets.fromLTRB(10, 10, 0, 10),
|
margin: EdgeInsets.fromLTRB(20, 10, 0, 10),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(20),
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(4.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -200,6 +351,18 @@ class DiscoveryPageState extends State<DiscoveryPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<String?>?> _getSearchHistory() {
|
||||||
|
final storage = KeyValueStorage(searchHistoryKey);
|
||||||
|
final history = storage.getStringList();
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
|
void backToHome() {
|
||||||
|
setState(() {
|
||||||
|
_selectedGenre = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<OnlinePodcast>> _getTopPodcasts({int? page}) async {
|
Future<List<OnlinePodcast>> _getTopPodcasts({int? page}) async {
|
||||||
if (environment['apiKey'] == '') return [];
|
if (environment['apiKey'] == '') return [];
|
||||||
final searchEngine = ListenNotesSearch();
|
final searchEngine = ListenNotesSearch();
|
||||||
|
@ -222,167 +385,6 @@ class DiscoveryPageState extends State<DiscoveryPage> {
|
||||||
final storage = KeyValueStorage(hidePodcastDiscoveryKey);
|
final storage = KeyValueStorage(hidePodcastDiscoveryKey);
|
||||||
return await storage.getBool(defaultValue: false);
|
return await storage.getBool(defaultValue: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return FutureBuilder<bool>(
|
|
||||||
future: _getIfHideDiscovery!.then((value) => value as bool),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return Center();
|
|
||||||
} else if (snapshot.data! || environment['apiKey'] == '') {
|
|
||||||
return ScrollConfiguration(
|
|
||||||
behavior: NoGrowBehavior(),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_historyList(),
|
|
||||||
SizedBox(
|
|
||||||
height: 150,
|
|
||||||
child: Center(
|
|
||||||
child: Icon(
|
|
||||||
Icons.search,
|
|
||||||
size: 80,
|
|
||||||
color: Colors.grey[400],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
LineIcons.microphone,
|
|
||||||
size: 30,
|
|
||||||
color: Colors.lightBlue,
|
|
||||||
),
|
|
||||||
SizedBox(width: 50),
|
|
||||||
Icon(
|
|
||||||
LineIcons.broadcastTower,
|
|
||||||
size: 30,
|
|
||||||
color: Colors.deepPurple,
|
|
||||||
),
|
|
||||||
SizedBox(width: 50),
|
|
||||||
Icon(
|
|
||||||
LineIcons.rssSquare,
|
|
||||||
size: 30,
|
|
||||||
color: Colors.blueGrey,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(50, 20, 50, 20),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
context.s.searchHelper,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: context.textTheme.headline6!
|
|
||||||
.copyWith(color: Colors.grey[400]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return PodcastSlideup(
|
|
||||||
searchEngine: SearchEngine.listenNotes,
|
|
||||||
child: Selector<SearchState, Genre?>(
|
|
||||||
selector: (_, searchState) => searchState.genre,
|
|
||||||
builder: (_, genre, __) => IndexedStack(
|
|
||||||
index: genre == null ? 0 : 1,
|
|
||||||
children: [
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_historyList(),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
SizedBox(
|
|
||||||
height: 200,
|
|
||||||
child: FutureBuilder<List<OnlinePodcast>>(
|
|
||||||
future: _searchTopPodcast!.then(
|
|
||||||
(value) => value as List<OnlinePodcast>),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return ScrollConfiguration(
|
|
||||||
behavior: NoGrowBehavior(),
|
|
||||||
child: ListView(
|
|
||||||
addAutomaticKeepAlives: true,
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
children: snapshot.hasData
|
|
||||||
? snapshot.data!
|
|
||||||
.map<Widget>((podcast) {
|
|
||||||
return _podcastCard(
|
|
||||||
podcast,
|
|
||||||
onTap: () {
|
|
||||||
context
|
|
||||||
.read<SearchState>()
|
|
||||||
.selectedPodcast =
|
|
||||||
podcast;
|
|
||||||
widget.onTap!('');
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}).toList()
|
|
||||||
: [
|
|
||||||
_loadTopPodcasts(),
|
|
||||||
_loadTopPodcasts(),
|
|
||||||
_loadTopPodcasts(),
|
|
||||||
_loadTopPodcasts(),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(20, 10, 10, 4),
|
|
||||||
child: Text('Categories',
|
|
||||||
style: context.textTheme.headline6!
|
|
||||||
.copyWith(color: context.accentColor)),
|
|
||||||
),
|
|
||||||
ListView(
|
|
||||||
shrinkWrap: true,
|
|
||||||
physics: NeverScrollableScrollPhysics(),
|
|
||||||
children: genres
|
|
||||||
.map<Widget>((e) => ListTile(
|
|
||||||
contentPadding:
|
|
||||||
EdgeInsets.fromLTRB(20, 0, 20, 0),
|
|
||||||
onTap: () {
|
|
||||||
widget.onTap!('');
|
|
||||||
context.read<SearchState>().setGenre =
|
|
||||||
e;
|
|
||||||
},
|
|
||||||
title: Text(e.name!,
|
|
||||||
style: context.textTheme.headline6),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 40,
|
|
||||||
child: Center(
|
|
||||||
child: Image(
|
|
||||||
image: context.brightness == Brightness.light
|
|
||||||
? AssetImage('assets/listennotes.png')
|
|
||||||
: AssetImage(
|
|
||||||
'assets/listennotes_light.png'),
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
genre == null ? Center() : _TopPodcastList(genre: genre),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TopPodcastList extends StatefulWidget {
|
class _TopPodcastList extends StatefulWidget {
|
||||||
|
@ -398,20 +400,6 @@ class __TopPodcastListState extends State<_TopPodcastList> {
|
||||||
Future? _searchFuture;
|
Future? _searchFuture;
|
||||||
late bool _loading;
|
late bool _loading;
|
||||||
late int _page;
|
late int _page;
|
||||||
Future<List<OnlinePodcast>> _getTopPodcasts(
|
|
||||||
{required Genre genre, int? page}) async {
|
|
||||||
final searchEngine = ListenNotesSearch();
|
|
||||||
var searchResult = await searchEngine.fetchBestPodcast(
|
|
||||||
genre: genre.id,
|
|
||||||
page: page,
|
|
||||||
);
|
|
||||||
final podcastTopList = [
|
|
||||||
for (final p in searchResult!.podcasts!) p?.toOnlinePodcast
|
|
||||||
];
|
|
||||||
_podcastList.addAll(podcastTopList.cast());
|
|
||||||
_loading = false;
|
|
||||||
return _podcastList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -462,12 +450,8 @@ class __TopPodcastListState extends State<_TopPodcastList> {
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
||||||
child: OutlinedButton(
|
child: TextButton(
|
||||||
style: OutlinedButton.styleFrom(
|
style: TextButton.styleFrom(),
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.circular(100))),
|
|
||||||
),
|
|
||||||
// highlightedBorderColor: context.accentColor,
|
// highlightedBorderColor: context.accentColor,
|
||||||
// splashColor: context.accentColor.withOpacity(0.5),
|
// splashColor: context.accentColor.withOpacity(0.5),
|
||||||
child: _loading
|
child: _loading
|
||||||
|
@ -498,4 +482,19 @@ class __TopPodcastListState extends State<_TopPodcastList> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<OnlinePodcast>> _getTopPodcasts(
|
||||||
|
{required Genre genre, int? page}) async {
|
||||||
|
final searchEngine = ListenNotesSearch();
|
||||||
|
final searchResult = await searchEngine.fetchBestPodcast(
|
||||||
|
genre: genre.id,
|
||||||
|
page: page,
|
||||||
|
);
|
||||||
|
final podcastTopList = [
|
||||||
|
for (final p in searchResult!.podcasts!) p?.toOnlinePodcast
|
||||||
|
];
|
||||||
|
_podcastList.addAll(podcastTopList.cast());
|
||||||
|
_loading = false;
|
||||||
|
return _podcastList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class MyHomePageDelegate extends SearchDelegate<int?> {
|
||||||
connectTimeout: 30000,
|
connectTimeout: 30000,
|
||||||
receiveTimeout: 90000,
|
receiveTimeout: 90000,
|
||||||
);
|
);
|
||||||
var response = await Dio(options).get(url);
|
final response = await Dio(options).get(url);
|
||||||
return RssFeed.parse(response.data);
|
return RssFeed.parse(response.data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -88,7 +88,10 @@ class MyHomePageDelegate extends SearchDelegate<int?> {
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
tooltip: context.s.back,
|
tooltip: context.s.back,
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
icon: Icon(_getIconData(Theme.of(context).platform)),
|
icon: Icon(
|
||||||
|
_getIconData(Theme.of(context).platform),
|
||||||
|
color: context.textColor,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
close(context, 1);
|
close(context, 1);
|
||||||
},
|
},
|
||||||
|
@ -164,12 +167,10 @@ class MyHomePageDelegate extends SearchDelegate<int?> {
|
||||||
switch (_searchEngine) {
|
switch (_searchEngine) {
|
||||||
case SearchEngine.listenNotes:
|
case SearchEngine.listenNotes:
|
||||||
return _ListenNotesSearch(query: query);
|
return _ListenNotesSearch(query: query);
|
||||||
break;
|
|
||||||
case SearchEngine.podcastIndex:
|
case SearchEngine.podcastIndex:
|
||||||
return _PodcastIndexSearch(query: query);
|
return _PodcastIndexSearch(query: query);
|
||||||
default:
|
default:
|
||||||
return Center();
|
return Center();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,14 +218,14 @@ class _RssResultState extends State<RssResult> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
var items = widget.rssFeed!.items!;
|
final items = widget.rssFeed!.items!;
|
||||||
return DefaultTabController(
|
return DefaultTabController(
|
||||||
length: 2,
|
length: 2,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
color: context.primaryColor,
|
color: context.primaryColor,
|
||||||
height: 140,
|
height: 160,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -314,8 +315,12 @@ class _RssResultState extends State<RssResult> {
|
||||||
url!.launchUrl;
|
url!.launchUrl;
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
|
'html': Style(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
),
|
||||||
'a': Style(
|
'a': Style(
|
||||||
color: context.accentColor,
|
color: context.accentColor,
|
||||||
|
textDecoration: TextDecoration.none,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
@ -331,13 +336,9 @@ class _RssResultState extends State<RssResult> {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: OutlinedButton(
|
child: TextButton(
|
||||||
style: OutlinedButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
// highlightedBorderColor: context.accentColor,
|
|
||||||
onSurface: context.accentColor.withOpacity(0.5),
|
onSurface: context.accentColor.withOpacity(0.5),
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.circular(100))),
|
|
||||||
),
|
),
|
||||||
child: Text(context.s.loadMore),
|
child: Text(context.s.loadMore),
|
||||||
onPressed: () => setState(
|
onPressed: () => setState(
|
||||||
|
@ -378,18 +379,12 @@ class __SearchPopupMenuState extends State<_SearchPopupMenu> {
|
||||||
_getSearchEngine();
|
_getSearchEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _getSearchEngine() async {
|
|
||||||
final storage = KeyValueStorage(searchEngineKey);
|
|
||||||
final index = await storage.getInt();
|
|
||||||
setState(() => _searchEngine = SearchEngine.values[index]);
|
|
||||||
widget.onSelected!(_searchEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return PopupMenuButton<SearchEngine>(
|
return PopupMenuButton<SearchEngine>(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
|
color: context.priamryContainer,
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
height: 25,
|
height: 25,
|
||||||
width: 25,
|
width: 25,
|
||||||
|
@ -437,11 +432,18 @@ class __SearchPopupMenuState extends State<_SearchPopupMenu> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _getSearchEngine() async {
|
||||||
|
final storage = KeyValueStorage(searchEngineKey);
|
||||||
|
final index = await storage.getInt();
|
||||||
|
setState(() => _searchEngine = SearchEngine.values[index]);
|
||||||
|
widget.onSelected!(_searchEngine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ListenNotesSearch extends StatefulWidget {
|
class _ListenNotesSearch extends StatefulWidget {
|
||||||
final String? query;
|
final String query;
|
||||||
_ListenNotesSearch({this.query, Key? key}) : super(key: key);
|
_ListenNotesSearch({required this.query, Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
__ListenNotesSearchState createState() => __ListenNotesSearchState();
|
__ListenNotesSearchState createState() => __ListenNotesSearchState();
|
||||||
|
@ -461,9 +463,9 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> {
|
||||||
_searchFuture = _getListenNotesList(widget.query, _nextOffset);
|
_searchFuture = _getListenNotesList(widget.query, _nextOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _saveHistory(String? query) async {
|
Future<void> _saveHistory(String query) async {
|
||||||
final storage = KeyValueStorage(searchHistoryKey);
|
final storage = KeyValueStorage(searchHistoryKey);
|
||||||
final history = await (storage.getStringList() as FutureOr<List<String?>>);
|
final history = await storage.getStringList();
|
||||||
if (!history.contains(query)) {
|
if (!history.contains(query)) {
|
||||||
if (history.length >= 6) {
|
if (history.length >= 6) {
|
||||||
history.removeLast();
|
history.removeLast();
|
||||||
|
@ -474,7 +476,7 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<OnlinePodcast>> _getListenNotesList(
|
Future<List<OnlinePodcast>> _getListenNotesList(
|
||||||
String? searchText, int? nextOffset) async {
|
String searchText, int? nextOffset) async {
|
||||||
if (nextOffset == 0) _saveHistory(searchText);
|
if (nextOffset == 0) _saveHistory(searchText);
|
||||||
final searchEngine = ListenNotesSearch();
|
final searchEngine = ListenNotesSearch();
|
||||||
var searchResult;
|
var searchResult;
|
||||||
|
@ -544,12 +546,13 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
OutlinedButton(
|
TextButton(
|
||||||
style: OutlinedButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
side: BorderSide(color: context.accentColor),
|
side: BorderSide(color: context.accentColor),
|
||||||
onSurface: context.accentColor.withOpacity(0.5),
|
onSurface: context.accentColor.withOpacity(0.5),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(100)),
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: _loading
|
child: _loading
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
|
@ -582,7 +585,9 @@ class __ListenNotesSearchState extends State<_ListenNotesSearch> {
|
||||||
child: Text(
|
child: Text(
|
||||||
'Powered by ListenNotes',
|
'Powered by ListenNotes',
|
||||||
style: GoogleFonts.quicksand(
|
style: GoogleFonts.quicksand(
|
||||||
color: Colors.red, textStyle: TextStyle(fontSize: 15)),
|
color: Colors.red,
|
||||||
|
textStyle: TextStyle(fontSize: 15),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// Image(
|
// Image(
|
||||||
// image: context.brightness == Brightness.light
|
// image: context.brightness == Brightness.light
|
||||||
|
@ -662,101 +667,102 @@ class __PodcastIndexSearchState extends State<_PodcastIndexSearch> {
|
||||||
return PodcastSlideup(
|
return PodcastSlideup(
|
||||||
searchEngine: SearchEngine.podcastIndex,
|
searchEngine: SearchEngine.podcastIndex,
|
||||||
child: FutureBuilder<List>(
|
child: FutureBuilder<List>(
|
||||||
future: _searchFuture.then((value) => value as List<dynamic>),
|
future: _searchFuture.then((value) => value as List<dynamic>),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData && widget.query != null) {
|
if (!snapshot.hasData && widget.query != null) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(top: 200),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: Platform.isIOS
|
||||||
|
? CupertinoActivityIndicator()
|
||||||
|
: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (snapshot.data!.isEmpty) {
|
||||||
|
if (_loadError) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.only(top: 200),
|
padding: EdgeInsets.only(top: 200),
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: Platform.isIOS
|
child: Text('Network error.',
|
||||||
? CupertinoActivityIndicator()
|
style: context.textTheme.headline6!
|
||||||
: CircularProgressIndicator(),
|
.copyWith(color: Colors.red)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(top: 200),
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: Text('No result found.',
|
||||||
|
style: context.textTheme.headline6!
|
||||||
|
.copyWith(color: context.accentColor)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (snapshot.data!.isEmpty) {
|
}
|
||||||
if (_loadError) {
|
var content = snapshot.data!;
|
||||||
return Container(
|
return CustomScrollView(
|
||||||
padding: EdgeInsets.only(top: 200),
|
slivers: [
|
||||||
alignment: Alignment.topCenter,
|
SliverList(
|
||||||
child: Text('Network error.',
|
delegate: SliverChildBuilderDelegate(
|
||||||
style: context.textTheme.headline6!
|
(context, index) {
|
||||||
.copyWith(color: Colors.red)),
|
return SearchResult(onlinePodcast: content[index]);
|
||||||
);
|
},
|
||||||
} else {
|
childCount: content.length,
|
||||||
return Container(
|
|
||||||
padding: EdgeInsets.only(top: 200),
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: Text('No result found.',
|
|
||||||
style: context.textTheme.headline6!
|
|
||||||
.copyWith(color: context.accentColor)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var content = snapshot.data!;
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return SearchResult(onlinePodcast: content[index]);
|
|
||||||
},
|
|
||||||
childCount: content.length,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
),
|
||||||
child: Row(
|
SliverToBoxAdapter(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
OutlinedButton(
|
children: [
|
||||||
style: OutlinedButton.styleFrom(
|
TextButton(
|
||||||
side: BorderSide(color: context.accentColor),
|
style: TextButton.styleFrom(
|
||||||
onSurface: context.accentColor.withOpacity(0.5),
|
side: BorderSide(color: context.accentColor),
|
||||||
shape: RoundedRectangleBorder(
|
onSurface: context.accentColor.withOpacity(0.5),
|
||||||
borderRadius: BorderRadius.circular(100)),
|
),
|
||||||
),
|
child: _loading
|
||||||
child: _loading
|
? SizedBox(
|
||||||
? SizedBox(
|
height: 20,
|
||||||
height: 20,
|
width: 20,
|
||||||
width: 20,
|
child: CircularProgressIndicator(
|
||||||
child: CircularProgressIndicator(
|
strokeWidth: 2,
|
||||||
strokeWidth: 2,
|
|
||||||
))
|
|
||||||
: Text(context.s.loadMore),
|
|
||||||
onPressed: () => _loading
|
|
||||||
? null
|
|
||||||
: setState(
|
|
||||||
() {
|
|
||||||
_loading = true;
|
|
||||||
_limit += 10;
|
|
||||||
_searchFuture = _getPodcatsIndexList(
|
|
||||||
widget.query!,
|
|
||||||
limit: _limit);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
: Text(context.s.loadMore),
|
||||||
),
|
onPressed: () => _loading
|
||||||
|
? null
|
||||||
|
: setState(
|
||||||
|
() {
|
||||||
|
_loading = true;
|
||||||
|
_limit += 10;
|
||||||
|
_searchFuture = _getPodcatsIndexList(
|
||||||
|
widget.query!,
|
||||||
|
limit: _limit);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
),
|
||||||
child: Padding(
|
SliverToBoxAdapter(
|
||||||
padding: EdgeInsets.symmetric(vertical: 10),
|
child: Padding(
|
||||||
child: Center(
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
child: Text(
|
child: Center(
|
||||||
'Powered by PODCASTINDEX',
|
child: Text(
|
||||||
style: GoogleFonts.quicksand(
|
'Powered by PODCASTINDEX',
|
||||||
color: Colors.red,
|
style: GoogleFonts.quicksand(
|
||||||
textStyle: TextStyle(fontSize: 15)),
|
color: Colors.red,
|
||||||
),
|
textStyle: TextStyle(fontSize: 15)),
|
||||||
)
|
),
|
||||||
// Image(
|
)
|
||||||
// image: AssetImage('assets/podcastindex.png'),
|
// Image(
|
||||||
// height: 15,
|
// image: AssetImage('assets/podcastindex.png'),
|
||||||
// ),
|
// height: 15,
|
||||||
))
|
// ),
|
||||||
],
|
),
|
||||||
);
|
)
|
||||||
}),
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -997,12 +1003,10 @@ class _SearchResultDetailState extends State<SearchResultDetail>
|
||||||
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
padding: const EdgeInsets.only(top: 10.0, bottom: 20.0),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
child: OutlinedButton(
|
child: TextButton(
|
||||||
style: OutlinedButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
side: BorderSide(color: context.accentColor),
|
side: BorderSide(color: context.accentColor),
|
||||||
onSurface: context.accentColor.withOpacity(0.5),
|
onSurface: context.accentColor.withOpacity(0.5),
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(100)),
|
|
||||||
),
|
),
|
||||||
child: _loading
|
child: _loading
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
|
|
|
@ -44,6 +44,10 @@ Future main() async {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
systemNavigationBarColor: Colors.transparent,
|
||||||
|
statusBarColor: Colors.transparent,
|
||||||
|
));
|
||||||
await SystemChrome.setPreferredOrientations(
|
await SystemChrome.setPreferredOrientations(
|
||||||
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tsacdop/util/extension_helper.dart';
|
||||||
|
|
||||||
class CustomTabView extends StatefulWidget {
|
class CustomTabView extends StatefulWidget {
|
||||||
final int itemCount;
|
final int itemCount;
|
||||||
|
@ -108,7 +109,7 @@ class _CustomTabsState extends State<CustomTabView>
|
||||||
unselectedLabelColor: Colors.grey[700],
|
unselectedLabelColor: Colors.grey[700],
|
||||||
indicator: BoxDecoration(
|
indicator: BoxDecoration(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(15)),
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
color: Theme.of(context).accentColor,
|
color: context.accentColor,
|
||||||
),
|
),
|
||||||
tabs: List.generate(
|
tabs: List.generate(
|
||||||
widget.itemCount,
|
widget.itemCount,
|
||||||
|
|
|
@ -122,12 +122,12 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
var autoDownload = await _dbHelper.getAutoDownload(podcastLocal.id);
|
final autoDownload = await _dbHelper.getAutoDownload(podcastLocal.id);
|
||||||
if (autoDownload) {
|
if (autoDownload) {
|
||||||
var downloader = Provider.of<DownloadState>(context, listen: false);
|
final downloader = Provider.of<DownloadState>(context, listen: false);
|
||||||
var result = await Connectivity().checkConnectivity();
|
final result = await Connectivity().checkConnectivity();
|
||||||
var autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
|
final autoDownloadStorage = KeyValueStorage(autoDownloadNetworkKey);
|
||||||
var autoDownloadNetwork = await autoDownloadStorage.getInt();
|
final autoDownloadNetwork = await autoDownloadStorage.getInt();
|
||||||
if (autoDownloadNetwork == 1) {
|
if (autoDownloadNetwork == 1) {
|
||||||
var episodes = await _dbHelper.getNewEpisodes(podcastLocal.id);
|
var episodes = await _dbHelper.getNewEpisodes(podcastLocal.id);
|
||||||
// For safety
|
// For safety
|
||||||
|
@ -232,31 +232,32 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
VoidCallback? onTap,
|
VoidCallback? onTap,
|
||||||
required Color backgroundColor}) {
|
required Color backgroundColor}) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.fromLTRB(5, 10, 5, 0),
|
padding: EdgeInsets.fromLTRB(5, 10, 5, 0),
|
||||||
width: 60.0,
|
width: 60.0,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
radius: 20,
|
radius: 20,
|
||||||
child: child,
|
child: child,
|
||||||
backgroundColor: backgroundColor.withOpacity(0.5),
|
backgroundColor: backgroundColor.withOpacity(0.5),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 4),
|
),
|
||||||
Text(
|
SizedBox(height: 4),
|
||||||
title,
|
Text(
|
||||||
style: context.textTheme.subtitle2,
|
title,
|
||||||
textAlign: TextAlign.center,
|
style: context.textTheme.subtitle2,
|
||||||
maxLines: 2,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.fade,
|
maxLines: 2,
|
||||||
),
|
overflow: TextOverflow.fade,
|
||||||
],
|
),
|
||||||
));
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _hostsList(BuildContext context, PodcastLocal podcastLocal) {
|
Widget _hostsList(BuildContext context, PodcastLocal podcastLocal) {
|
||||||
|
@ -673,11 +674,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: color,
|
statusBarColor: color, statusBarIconBrightness: Brightness.light),
|
||||||
statusBarIconBrightness: Brightness.dark,
|
|
||||||
systemNavigationBarColor: context.primaryColor,
|
|
||||||
systemNavigationBarIconBrightness: context.iconBrightness,
|
|
||||||
),
|
|
||||||
child: WillPopScope(
|
child: WillPopScope(
|
||||||
onWillPop: () {
|
onWillPop: () {
|
||||||
if (_playerKey.currentState != null &&
|
if (_playerKey.currentState != null &&
|
||||||
|
@ -690,7 +687,6 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
top: false,
|
|
||||||
child: RefreshIndicator(
|
child: RefreshIndicator(
|
||||||
key: _refreshIndicatorKey,
|
key: _refreshIndicatorKey,
|
||||||
displacement: context.paddingTop + 40,
|
displacement: context.paddingTop + 40,
|
||||||
|
@ -751,6 +747,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
scrolledUnderElevation: 0,
|
||||||
iconTheme: IconThemeData(
|
iconTheme: IconThemeData(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
|
@ -1021,17 +1018,6 @@ class AboutPodcast extends StatefulWidget {
|
||||||
class _AboutPodcastState extends State<AboutPodcast> {
|
class _AboutPodcastState extends State<AboutPodcast> {
|
||||||
late String _description;
|
late String _description;
|
||||||
late bool _load;
|
late bool _load;
|
||||||
void getDescription(String? id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
var description = await dbHelper.getFeedDescription(id);
|
|
||||||
if (description == null || description.isEmpty) {
|
|
||||||
_description = '';
|
|
||||||
} else {
|
|
||||||
var doc = parse(description);
|
|
||||||
_description = parse(doc.body!.text).documentElement!.text;
|
|
||||||
}
|
|
||||||
if (mounted) setState(() => _load = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -1042,75 +1028,30 @@ class _AboutPodcastState extends State<AboutPodcast> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return !_load
|
if (_load)
|
||||||
? Center()
|
return Linkify(
|
||||||
: Linkify(
|
text: _description,
|
||||||
text: _description,
|
onOpen: (link) {
|
||||||
onOpen: (link) {
|
link.url!.launchUrl;
|
||||||
link.url!.launchUrl;
|
},
|
||||||
},
|
linkStyle: TextStyle(
|
||||||
linkStyle: TextStyle(
|
color: context.accentColor,
|
||||||
color: Theme.of(context).accentColor,
|
decoration: TextDecoration.underline,
|
||||||
decoration: TextDecoration.underline,
|
textBaseline: TextBaseline.ideographic),
|
||||||
textBaseline: TextBaseline.ideographic),
|
);
|
||||||
);
|
return Center();
|
||||||
// LayoutBuilder(
|
}
|
||||||
// builder: (context, size) {
|
|
||||||
// final span = TextSpan(text: _description);
|
|
||||||
// final tp = TextPainter(
|
|
||||||
// text: span, maxLines: 3, textDirection: TextDirection.ltr);
|
|
||||||
// tp.layout(maxWidth: size.maxWidth);
|
|
||||||
|
|
||||||
// if (tp.didExceedMaxLines) {
|
void getDescription(String? id) async {
|
||||||
// return GestureDetector(
|
final dbHelper = DBHelper();
|
||||||
// onTap: () {
|
final description = await dbHelper.getFeedDescription(id);
|
||||||
// setState(() => _expand = !_expand);
|
if (description == null || description.isEmpty) {
|
||||||
// },
|
_description = '';
|
||||||
// child: !_expand
|
} else {
|
||||||
// ? Column(
|
final doc = parse(description);
|
||||||
// mainAxisAlignment: MainAxisAlignment.start,
|
_description = parse(doc.body!.text).documentElement!.text;
|
||||||
// mainAxisSize: MainAxisSize.min,
|
}
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
if (mounted) setState(() => _load = true);
|
||||||
// children: <Widget>[
|
|
||||||
// Linkify(
|
|
||||||
// onOpen: (link) {
|
|
||||||
// link.url.launchUrl;
|
|
||||||
// },
|
|
||||||
// text: _description,
|
|
||||||
// linkStyle: TextStyle(
|
|
||||||
// color: Theme.of(context).accentColor,
|
|
||||||
// decoration: TextDecoration.underline,
|
|
||||||
// textBaseline: TextBaseline.ideographic),
|
|
||||||
// maxLines: 3,
|
|
||||||
// overflow: TextOverflow.ellipsis,
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// )
|
|
||||||
// : Linkify(
|
|
||||||
// onOpen: (link) {
|
|
||||||
// link.url.launchUrl;
|
|
||||||
// },
|
|
||||||
// text: _description,
|
|
||||||
// linkStyle: TextStyle(
|
|
||||||
// color: Theme.of(context).accentColor,
|
|
||||||
// decoration: TextDecoration.underline,
|
|
||||||
// textBaseline: TextBaseline.ideographic),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// return Linkify(
|
|
||||||
// text: _description,
|
|
||||||
// onOpen: (link) {
|
|
||||||
// link.url.launchUrl;
|
|
||||||
// },
|
|
||||||
// linkStyle: TextStyle(
|
|
||||||
// color: Theme.of(context).accentColor,
|
|
||||||
// decoration: TextDecoration.underline,
|
|
||||||
// textBaseline: TextBaseline.ideographic),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1156,8 +1097,7 @@ class _SearchEpisodeState extends State<SearchEpisode> {
|
||||||
titlePadding: const EdgeInsets.all(20),
|
titlePadding: const EdgeInsets.all(20),
|
||||||
actionsPadding: EdgeInsets.zero,
|
actionsPadding: EdgeInsets.zero,
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: Text(
|
child: Text(
|
||||||
s.cancel,
|
s.cancel,
|
||||||
|
@ -1165,8 +1105,7 @@ class _SearchEpisodeState extends State<SearchEpisode> {
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if ((_query ?? '').isNotEmpty) {
|
if ((_query ?? '').isNotEmpty) {
|
||||||
widget.onSearch!(_query);
|
widget.onSearch!(_query);
|
||||||
|
|
|
@ -85,45 +85,6 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
int? _seconds;
|
int? _seconds;
|
||||||
int? _skipSeconds;
|
int? _skipSeconds;
|
||||||
|
|
||||||
Future<int?> _getSkipSecond(String? id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
var seconds = await dbHelper.getSkipSecondsStart(id);
|
|
||||||
_skipSeconds = seconds;
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
_saveSkipSeconds(String? id, int? seconds) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
await dbHelper.saveSkipSecondsStart(id, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setAutoDownload(String? id, bool boo) async {
|
|
||||||
var permission = await _checkPermmison();
|
|
||||||
if (permission) {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
await dbHelper.saveAutoDownload(id, boo: boo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _getAutoDownload(String? id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
return await dbHelper.getAutoDownload(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _checkPermmison() async {
|
|
||||||
var permission = await Permission.storage.status;
|
|
||||||
if (permission != PermissionStatus.granted) {
|
|
||||||
var permissions = await [Permission.storage].request();
|
|
||||||
if (permissions[Permission.storage] == PermissionStatus.granted) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -134,43 +95,20 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
_controller =
|
_controller =
|
||||||
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
|
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
|
||||||
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller)
|
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(_controller)
|
||||||
..addListener(() {
|
..addListener(
|
||||||
setState(() {
|
() {
|
||||||
_value = _animation.value;
|
setState(() {
|
||||||
});
|
_value = _animation.value;
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
Widget _buttonOnMenu(
|
|
||||||
{required Widget icon,
|
|
||||||
VoidCallback? onTap,
|
|
||||||
required String tooltip}) =>
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
height: 50.0,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: icon,
|
|
||||||
),
|
|
||||||
Text(tooltip, style: context.textTheme.subtitle2),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final c = widget.podcastLocal!.backgroudColor(context);
|
final c = widget.podcastLocal!.backgroudColor(context);
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
var groupList = context.watch<GroupList>();
|
final groupList = context.watch<GroupList>();
|
||||||
_belongGroups = groupList.getPodcastGroup(widget.podcastLocal!.id);
|
_belongGroups = groupList.getPodcastGroup(widget.podcastLocal!.id);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
@ -398,9 +336,7 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
_seconds = value.inSeconds,
|
_seconds = value.inSeconds,
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor
|
|
||||||
.withAlpha(70),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
_seconds = 0;
|
_seconds = 0;
|
||||||
|
@ -411,9 +347,7 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
color: Colors.grey[600]),
|
color: Colors.grey[600]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor
|
|
||||||
.withAlpha(70),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
_saveSkipSeconds(
|
_saveSkipSeconds(
|
||||||
|
@ -431,44 +365,42 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
_buttonOnMenu(
|
_buttonOnMenu(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.delete,
|
Icons.delete,
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
size: _value == 0 ? 1 : 20 * _value!,
|
size: _value == 0 ? 1 : 20 * _value!,
|
||||||
),
|
),
|
||||||
tooltip: s.remove,
|
tooltip: s.remove,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
generalDialog(
|
generalDialog(
|
||||||
context,
|
context,
|
||||||
title: Text(s.removeConfirm),
|
title: Text(s.removeConfirm),
|
||||||
content: Text(s.removePodcastDes),
|
content: Text(s.removePodcastDes),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor:
|
onPressed: () =>
|
||||||
context.accentColor.withAlpha(70),
|
Navigator.of(context).pop(),
|
||||||
onPressed: () =>
|
child: Text(
|
||||||
Navigator.of(context).pop(),
|
s.cancel,
|
||||||
child: Text(
|
style:
|
||||||
s.cancel,
|
TextStyle(color: Colors.grey[600]),
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
FlatButton(
|
),
|
||||||
splashColor: Colors.red.withAlpha(70),
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
groupList.removePodcast(
|
groupList.removePodcast(
|
||||||
widget.podcastLocal!);
|
widget.podcastLocal!);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
s.confirm,
|
s.confirm,
|
||||||
style: TextStyle(color: Colors.red),
|
style: TextStyle(color: Colors.red),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -477,6 +409,71 @@ class __PodcastCardState extends State<_PodcastCard>
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buttonOnMenu(
|
||||||
|
{required Widget icon,
|
||||||
|
VoidCallback? onTap,
|
||||||
|
required String tooltip}) =>
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
height: 50.0,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: icon,
|
||||||
|
),
|
||||||
|
Text(tooltip, style: context.textTheme.subtitle2),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<int?> _getSkipSecond(String? id) async {
|
||||||
|
final dbHelper = DBHelper();
|
||||||
|
final seconds = await dbHelper.getSkipSecondsStart(id);
|
||||||
|
_skipSeconds = seconds;
|
||||||
|
return seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
_saveSkipSeconds(String? id, int? seconds) async {
|
||||||
|
final dbHelper = DBHelper();
|
||||||
|
await dbHelper.saveSkipSecondsStart(id, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setAutoDownload(String? id, bool boo) async {
|
||||||
|
final permission = await _checkPermmison();
|
||||||
|
if (permission) {
|
||||||
|
final dbHelper = DBHelper();
|
||||||
|
await dbHelper.saveAutoDownload(id, boo: boo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getAutoDownload(String? id) async {
|
||||||
|
final dbHelper = DBHelper();
|
||||||
|
return await dbHelper.getAutoDownload(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _checkPermmison() async {
|
||||||
|
final permission = await Permission.storage.status;
|
||||||
|
if (permission != PermissionStatus.granted) {
|
||||||
|
final permissions = await [Permission.storage].request();
|
||||||
|
if (permissions[Permission.storage] == PermissionStatus.granted) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RenameGroup extends StatefulWidget {
|
class RenameGroup extends StatefulWidget {
|
||||||
|
@ -511,7 +508,7 @@ class _RenameGroupState extends State<RenameGroup> {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarIconBrightness: Brightness.light,
|
statusBarColor: Colors.transparent,
|
||||||
systemNavigationBarColor:
|
systemNavigationBarColor:
|
||||||
Theme.of(context).brightness == Brightness.light
|
Theme.of(context).brightness == Brightness.light
|
||||||
? Color.fromRGBO(113, 113, 113, 1)
|
? Color.fromRGBO(113, 113, 113, 1)
|
||||||
|
@ -519,27 +516,28 @@ class _RenameGroupState extends State<RenameGroup> {
|
||||||
),
|
),
|
||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
elevation: 1,
|
elevation: 1,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
titlePadding: EdgeInsets.all(20),
|
titlePadding: EdgeInsets.all(20),
|
||||||
actionsPadding: EdgeInsets.zero,
|
actionsPadding: EdgeInsets.zero,
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: Text(
|
child: Text(
|
||||||
s.cancel,
|
s.cancel,
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (list.contains(_newName)) {
|
if (list.contains(_newName)) {
|
||||||
setState(() => _error = 1);
|
setState(() => _error = 1);
|
||||||
} else {
|
} else {
|
||||||
var newGroup = PodcastGroup(_newName,
|
final newGroup = PodcastGroup(_newName,
|
||||||
color: widget.group!.color,
|
color: widget.group!.color,
|
||||||
id: widget.group!.id,
|
id: widget.group!.id,
|
||||||
podcastList: widget.group!.podcastList);
|
podcastList: widget.group!.podcastList);
|
||||||
|
@ -547,12 +545,16 @@ class _RenameGroupState extends State<RenameGroup> {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(s.confirm,
|
child: Text(
|
||||||
style: TextStyle(color: Theme.of(context).accentColor)),
|
s.confirm,
|
||||||
|
style: TextStyle(color: context.accentColor),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
title:
|
title: SizedBox(
|
||||||
SizedBox(width: context.width - 160, child: Text(s.editGroupName)),
|
width: context.width - 160,
|
||||||
|
child: Text(s.editGroupName),
|
||||||
|
),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
@ -578,7 +580,7 @@ class _RenameGroupState extends State<RenameGroup> {
|
||||||
_newName = value;
|
_newName = value;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Container(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: (_error == 1)
|
child: (_error == 1)
|
||||||
? Text(
|
? Text(
|
||||||
|
|
|
@ -42,7 +42,7 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
_menuValue = 0;
|
_menuValue = 0;
|
||||||
_index = 0;
|
_index = 0;
|
||||||
_menuController = AnimationController(
|
_menuController = AnimationController(
|
||||||
vsync: this, duration: const Duration(milliseconds: 150));
|
vsync: this, duration: const Duration(milliseconds: 300));
|
||||||
_controller = AnimationController(
|
_controller = AnimationController(
|
||||||
vsync: this, duration: const Duration(milliseconds: 500));
|
vsync: this, duration: const Duration(milliseconds: 500));
|
||||||
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
|
_animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
|
||||||
|
@ -51,8 +51,8 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
setState(() => _fraction = _animation.value);
|
setState(() => _fraction = _animation.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_menuAnimation = Tween(begin: 0.0, end: 1.0).animate(
|
_menuAnimation = Tween(begin: 0.0, end: 1.0)
|
||||||
CurvedAnimation(parent: _menuController, curve: Curves.elasticInOut))
|
.animate(CurvedAnimation(parent: _menuController, curve: Curves.ease))
|
||||||
..addListener(() {
|
..addListener(() {
|
||||||
if (mounted) setState(() => _menuValue = _menuAnimation.value);
|
if (mounted) setState(() => _menuValue = _menuAnimation.value);
|
||||||
});
|
});
|
||||||
|
@ -77,6 +77,274 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = context.s;
|
||||||
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
|
value: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: context.priamryContainer,
|
||||||
|
systemNavigationBarColor: context.background,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: context.priamryContainer,
|
||||||
|
title: Text(context.s.groups(2)),
|
||||||
|
leading: CustomBackButton(),
|
||||||
|
systemOverlayStyle: SystemUiOverlayStyle(
|
||||||
|
statusBarColor: context.priamryContainer,
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
featureDiscoveryOverlay(
|
||||||
|
context,
|
||||||
|
featureId: addGroupFeature,
|
||||||
|
tapTarget: Icon(Icons.add),
|
||||||
|
title: s.featureDiscoveryGroup,
|
||||||
|
backgroundColor: Colors.cyan[600],
|
||||||
|
description: s.featureDiscoveryGroupDes,
|
||||||
|
buttonColor: Colors.cyan[500],
|
||||||
|
child: IconButton(
|
||||||
|
splashRadius: 20,
|
||||||
|
onPressed: () => showGeneralDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: true,
|
||||||
|
barrierLabel: MaterialLocalizations.of(context)
|
||||||
|
.modalBarrierDismissLabel,
|
||||||
|
barrierColor: Colors.black54,
|
||||||
|
transitionDuration: const Duration(milliseconds: 200),
|
||||||
|
pageBuilder: (context, animaiton, secondaryAnimation) =>
|
||||||
|
AddGroup()),
|
||||||
|
icon: Icon(Icons.add_circle_outline)),
|
||||||
|
),
|
||||||
|
Selector<SettingState, bool?>(
|
||||||
|
selector: (_, setting) => setting.openAllPodcastDefalt,
|
||||||
|
builder: (_, data, __) {
|
||||||
|
return !data!
|
||||||
|
? IconButton(
|
||||||
|
splashRadius: 20,
|
||||||
|
onPressed: () => Navigator.push(
|
||||||
|
context, ScaleRoute(page: PodcastList())),
|
||||||
|
icon: Icon(Icons.all_out))
|
||||||
|
: Center();
|
||||||
|
})
|
||||||
|
// _OrderMenu(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
context.read<GroupList>().clearOrderChanged();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
child: Consumer<GroupList>(
|
||||||
|
builder: (_, groupList, __) {
|
||||||
|
// var _isLoading = groupList.isLoading;
|
||||||
|
final _groups = groupList.groups;
|
||||||
|
if (_groups.isEmpty) return Center();
|
||||||
|
return Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
ColoredBox(
|
||||||
|
color: context.priamryContainer,
|
||||||
|
child: CustomTabView(
|
||||||
|
itemCount: _groups.length,
|
||||||
|
tabBuilder: (context, index) => Tab(
|
||||||
|
child: Container(
|
||||||
|
height: 50.0,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
_groups[index]!.name!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pageBuilder: (context, index) =>
|
||||||
|
featureDiscoveryOverlay(
|
||||||
|
context,
|
||||||
|
featureId: configurePodcast,
|
||||||
|
tapTarget: Text(s.podcast(1)),
|
||||||
|
title: s.featureDiscoveryGroupPodcast,
|
||||||
|
backgroundColor: Colors.cyan[600],
|
||||||
|
buttonColor: Colors.cyan[500],
|
||||||
|
description: s.featureDiscoveryGroupPodcastDes,
|
||||||
|
child: PodcastGroupList(
|
||||||
|
group: _groups[index],
|
||||||
|
key: ValueKey<String?>(_groups[index]!.name),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPositionChange: (value) =>
|
||||||
|
// setState(() =>
|
||||||
|
_index = value,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_showSetting)
|
||||||
|
Positioned.fill(
|
||||||
|
top: 50,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await _menuController.reverse();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() => _showSetting = false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: context.background.withOpacity(
|
||||||
|
0.8 * math.min(_menuController.value * 2, 1.0)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 30,
|
||||||
|
bottom: 30,
|
||||||
|
child: _saveButton(),
|
||||||
|
),
|
||||||
|
if (_showSetting)
|
||||||
|
Positioned(
|
||||||
|
right: 100 * _menuValue - 70,
|
||||||
|
bottom: 100,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
_menuController.reverse();
|
||||||
|
setState(() => _showSetting = false);
|
||||||
|
_index == 0
|
||||||
|
? Fluttertoast.showToast(
|
||||||
|
msg: s.toastHomeGroupNotSupport,
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
)
|
||||||
|
: showGeneralDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: true,
|
||||||
|
barrierLabel:
|
||||||
|
MaterialLocalizations.of(context)
|
||||||
|
.modalBarrierDismissLabel,
|
||||||
|
barrierColor: Colors.black54,
|
||||||
|
transitionDuration:
|
||||||
|
const Duration(milliseconds: 300),
|
||||||
|
pageBuilder: (context, animaiton,
|
||||||
|
secondaryAnimation) =>
|
||||||
|
RenameGroup(
|
||||||
|
group: _groups[_index!],
|
||||||
|
));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 30.0,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[700],
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(10.0)),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(
|
||||||
|
Icons.text_fields,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 15.0,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 5.0),
|
||||||
|
),
|
||||||
|
Text(context.s.editGroupName,
|
||||||
|
style:
|
||||||
|
TextStyle(color: Colors.white)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
_menuController.reverse();
|
||||||
|
setState(() => _showSetting = false);
|
||||||
|
_index == 0
|
||||||
|
? Fluttertoast.showToast(
|
||||||
|
msg: s.toastHomeGroupNotSupport,
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
)
|
||||||
|
: generalDialog(
|
||||||
|
context,
|
||||||
|
title: Text(s.removeConfirm),
|
||||||
|
content: Text(s.groupRemoveConfirm),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
child: Text(
|
||||||
|
context.s.cancel,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_index ==
|
||||||
|
groupList.groups.length -
|
||||||
|
1) {
|
||||||
|
setState(() {
|
||||||
|
_index = _index! - 1;
|
||||||
|
});
|
||||||
|
groupList.delGroup(
|
||||||
|
_groups[_index! + 1]!);
|
||||||
|
} else {
|
||||||
|
groupList.delGroup(
|
||||||
|
_groups[_index!]!);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
context.s.confirm,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.red),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 30,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[700],
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(10.0)),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 15.0,
|
||||||
|
),
|
||||||
|
SizedBox(width: 10),
|
||||||
|
Text(s.remove,
|
||||||
|
style: TextStyle(color: Colors.red)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _saveButton() {
|
Widget _saveButton() {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return Consumer<GroupList>(
|
return Consumer<GroupList>(
|
||||||
|
@ -150,288 +418,6 @@ class _PodcastManageState extends State<PodcastManage>
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final s = context.s;
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
|
||||||
value: SystemUiOverlayStyle(
|
|
||||||
statusBarIconBrightness: context.brightness,
|
|
||||||
systemNavigationBarColor: context.primaryColor,
|
|
||||||
systemNavigationBarIconBrightness: context.iconBrightness,
|
|
||||||
// statusBarColor: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(context.s.groups(2)),
|
|
||||||
leading: CustomBackButton(),
|
|
||||||
actions: <Widget>[
|
|
||||||
featureDiscoveryOverlay(
|
|
||||||
context,
|
|
||||||
featureId: addGroupFeature,
|
|
||||||
tapTarget: Icon(Icons.add),
|
|
||||||
title: s.featureDiscoveryGroup,
|
|
||||||
backgroundColor: Colors.cyan[600],
|
|
||||||
description: s.featureDiscoveryGroupDes,
|
|
||||||
buttonColor: Colors.cyan[500],
|
|
||||||
child: IconButton(
|
|
||||||
splashRadius: 20,
|
|
||||||
onPressed: () => showGeneralDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: true,
|
|
||||||
barrierLabel: MaterialLocalizations.of(context)
|
|
||||||
.modalBarrierDismissLabel,
|
|
||||||
barrierColor: Colors.black54,
|
|
||||||
transitionDuration: const Duration(milliseconds: 200),
|
|
||||||
pageBuilder: (context, animaiton, secondaryAnimation) =>
|
|
||||||
AddGroup()),
|
|
||||||
icon: Icon(Icons.add_circle_outline)),
|
|
||||||
),
|
|
||||||
Selector<SettingState, bool?>(
|
|
||||||
selector: (_, setting) => setting.openAllPodcastDefalt,
|
|
||||||
builder: (_, data, __) {
|
|
||||||
return !data!
|
|
||||||
? IconButton(
|
|
||||||
splashRadius: 20,
|
|
||||||
onPressed: () => Navigator.push(
|
|
||||||
context, ScaleRoute(page: PodcastList())),
|
|
||||||
icon: Icon(Icons.all_out))
|
|
||||||
: Center();
|
|
||||||
})
|
|
||||||
// _OrderMenu(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: WillPopScope(
|
|
||||||
onWillPop: () async {
|
|
||||||
context.read<GroupList>().clearOrderChanged();
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
child: Consumer<GroupList>(
|
|
||||||
builder: (_, groupList, __) {
|
|
||||||
// var _isLoading = groupList.isLoading;
|
|
||||||
var _groups = groupList.groups;
|
|
||||||
return _groups.isEmpty
|
|
||||||
? Center()
|
|
||||||
: Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
color: context.background,
|
|
||||||
child: CustomTabView(
|
|
||||||
itemCount: _groups.length,
|
|
||||||
tabBuilder: (context, index) => Tab(
|
|
||||||
child: Container(
|
|
||||||
height: 30.0,
|
|
||||||
padding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 10.0),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
// color: Colors.grey[600].withOpacity(0.3),
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
_groups[index]!.name!,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
pageBuilder: (context, index) =>
|
|
||||||
featureDiscoveryOverlay(
|
|
||||||
context,
|
|
||||||
featureId: configurePodcast,
|
|
||||||
tapTarget: Text(s.podcast(1)),
|
|
||||||
title: s.featureDiscoveryGroupPodcast,
|
|
||||||
backgroundColor: Colors.cyan[600],
|
|
||||||
buttonColor: Colors.cyan[500],
|
|
||||||
description: s.featureDiscoveryGroupPodcastDes,
|
|
||||||
child: PodcastGroupList(
|
|
||||||
group: _groups[index],
|
|
||||||
key: ValueKey<String?>(_groups[index]!.name),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPositionChange: (value) =>
|
|
||||||
// setState(() =>
|
|
||||||
_index = value,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (_showSetting)
|
|
||||||
Positioned.fill(
|
|
||||||
top: 50,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () async {
|
|
||||||
await _menuController.reverse();
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => _showSetting = false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
color: context.background.withOpacity(0.8 *
|
|
||||||
math.min(_menuController.value * 2, 1.0)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
right: 30,
|
|
||||||
bottom: 30,
|
|
||||||
child: _saveButton(),
|
|
||||||
),
|
|
||||||
if (_showSetting)
|
|
||||||
Positioned(
|
|
||||||
right: 100 * _menuValue - 70,
|
|
||||||
bottom: 100,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: <Widget>[
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
_menuController.reverse();
|
|
||||||
setState(() => _showSetting = false);
|
|
||||||
_index == 0
|
|
||||||
? Fluttertoast.showToast(
|
|
||||||
msg: s.toastHomeGroupNotSupport,
|
|
||||||
gravity: ToastGravity.BOTTOM,
|
|
||||||
)
|
|
||||||
: showGeneralDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: true,
|
|
||||||
barrierLabel:
|
|
||||||
MaterialLocalizations.of(
|
|
||||||
context)
|
|
||||||
.modalBarrierDismissLabel,
|
|
||||||
barrierColor: Colors.black54,
|
|
||||||
transitionDuration:
|
|
||||||
const Duration(
|
|
||||||
milliseconds: 300),
|
|
||||||
pageBuilder: (context, animaiton,
|
|
||||||
secondaryAnimation) =>
|
|
||||||
RenameGroup(
|
|
||||||
group: _groups[_index!],
|
|
||||||
));
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 30.0,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.grey[700],
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(10.0)),
|
|
||||||
padding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(
|
|
||||||
Icons.text_fields,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 15.0,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 5.0),
|
|
||||||
),
|
|
||||||
Text(context.s.editGroupName,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
_menuController.reverse();
|
|
||||||
setState(() => _showSetting = false);
|
|
||||||
_index == 0
|
|
||||||
? Fluttertoast.showToast(
|
|
||||||
msg: s.toastHomeGroupNotSupport,
|
|
||||||
gravity: ToastGravity.BOTTOM,
|
|
||||||
)
|
|
||||||
: generalDialog(
|
|
||||||
context,
|
|
||||||
title: Text(s.removeConfirm),
|
|
||||||
content:
|
|
||||||
Text(s.groupRemoveConfirm),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context
|
|
||||||
.accentColor
|
|
||||||
.withAlpha(70),
|
|
||||||
onPressed: () =>
|
|
||||||
Navigator.of(context)
|
|
||||||
.pop(),
|
|
||||||
child: Text(
|
|
||||||
context.s.cancel,
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context
|
|
||||||
.accentColor
|
|
||||||
.withAlpha(70),
|
|
||||||
onPressed: () {
|
|
||||||
if (_index ==
|
|
||||||
groupList
|
|
||||||
.groups.length -
|
|
||||||
1) {
|
|
||||||
setState(() {
|
|
||||||
_index = _index! - 1;
|
|
||||||
});
|
|
||||||
groupList.delGroup(
|
|
||||||
_groups[
|
|
||||||
_index! + 1]!);
|
|
||||||
} else {
|
|
||||||
groupList.delGroup(
|
|
||||||
_groups[_index!]!);
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
context.s.confirm,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.red),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 30,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.grey[700],
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(10.0)),
|
|
||||||
padding:
|
|
||||||
EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(
|
|
||||||
Icons.delete,
|
|
||||||
color: Colors.red,
|
|
||||||
size: 15.0,
|
|
||||||
),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Text(s.remove,
|
|
||||||
style:
|
|
||||||
TextStyle(color: Colors.red)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OrderMenu extends StatelessWidget {
|
class _OrderMenu extends StatelessWidget {
|
||||||
|
@ -495,78 +481,81 @@ class _AddGroupState extends State<AddGroup> {
|
||||||
List list = groupList.groups.map((e) => e!.name).toList();
|
List list = groupList.groups.map((e) => e!.name).toList();
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarIconBrightness: Brightness.light,
|
statusBarColor: Colors.transparent,
|
||||||
systemNavigationBarColor:
|
systemNavigationBarColor:
|
||||||
Theme.of(context).brightness == Brightness.light
|
Theme.of(context).brightness == Brightness.light
|
||||||
? Color.fromRGBO(113, 113, 113, 1)
|
? Color.fromRGBO(113, 113, 113, 1)
|
||||||
: Color.fromRGBO(5, 5, 5, 1),
|
: Color.fromRGBO(5, 5, 5, 1),
|
||||||
),
|
),
|
||||||
child: AlertDialog(
|
child: SafeArea(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
top: false,
|
||||||
elevation: 1,
|
child: AlertDialog(
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
shape: RoundedRectangleBorder(
|
||||||
titlePadding: EdgeInsets.all(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
actionsPadding: EdgeInsets.zero,
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
child: Text(
|
|
||||||
s.cancel,
|
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
FlatButton(
|
elevation: 1,
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
onPressed: () async {
|
titlePadding: EdgeInsets.all(20),
|
||||||
if (list.contains(_newGroup)) {
|
actionsPadding: EdgeInsets.zero,
|
||||||
setState(() => _error = 1);
|
actions: <Widget>[
|
||||||
} else {
|
TextButton(
|
||||||
groupList.addGroup(PodcastGroup(_newGroup));
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
Navigator.of(context).pop();
|
child: Text(
|
||||||
}
|
s.cancel,
|
||||||
},
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
child:
|
|
||||||
Text(s.confirm, style: TextStyle(color: context.accentColor)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
title: SizedBox(width: context.width - 160, child: Text(s.newGroup)),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
hintText: s.newGroup,
|
|
||||||
hintStyle: TextStyle(fontSize: 18),
|
|
||||||
filled: true,
|
|
||||||
focusedBorder: UnderlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: context.accentColor, width: 2.0),
|
|
||||||
),
|
|
||||||
enabledBorder: UnderlineInputBorder(
|
|
||||||
borderSide:
|
|
||||||
BorderSide(color: context.accentColor, width: 2.0),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
cursorRadius: Radius.circular(2),
|
),
|
||||||
autofocus: true,
|
TextButton(
|
||||||
maxLines: 1,
|
onPressed: () async {
|
||||||
controller: _controller,
|
if (list.contains(_newGroup)) {
|
||||||
onChanged: (value) {
|
setState(() => _error = 1);
|
||||||
_newGroup = value;
|
} else {
|
||||||
|
groupList.addGroup(PodcastGroup(_newGroup));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
child:
|
||||||
Container(
|
Text(s.confirm, style: TextStyle(color: context.accentColor)),
|
||||||
alignment: Alignment.centerLeft,
|
)
|
||||||
child: (_error == 1)
|
|
||||||
? Text(
|
|
||||||
s.groupExisted,
|
|
||||||
style: TextStyle(color: Colors.red[400]),
|
|
||||||
)
|
|
||||||
: Center(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
|
title: SizedBox(width: context.width - 160, child: Text(s.newGroup)),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
hintText: s.newGroup,
|
||||||
|
hintStyle: TextStyle(fontSize: 18),
|
||||||
|
filled: true,
|
||||||
|
focusedBorder: UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: context.accentColor, width: 2.0),
|
||||||
|
),
|
||||||
|
enabledBorder: UnderlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: context.accentColor, width: 2.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cursorRadius: Radius.circular(2),
|
||||||
|
autofocus: true,
|
||||||
|
maxLines: 1,
|
||||||
|
controller: _controller,
|
||||||
|
onChanged: (value) {
|
||||||
|
_newGroup = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: (_error == 1)
|
||||||
|
? Text(
|
||||||
|
s.groupExisted,
|
||||||
|
style: TextStyle(color: Colors.red[400]),
|
||||||
|
)
|
||||||
|
: Center(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -52,153 +52,6 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
_showEndTimePicker = false;
|
_showEndTimePicker = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _setAutoDownload(bool boo) async {
|
|
||||||
var permission = await _checkPermmison();
|
|
||||||
if (permission) {
|
|
||||||
await _dbHelper.saveAutoDownload(widget.podcastLocal!.id, boo: boo);
|
|
||||||
}
|
|
||||||
if (mounted) setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _setNeverUpdate(bool boo) async {
|
|
||||||
await _dbHelper.saveNeverUpdate(widget.podcastLocal!.id, boo: boo);
|
|
||||||
if (mounted) setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _setHideNewMark(bool boo) async {
|
|
||||||
await _dbHelper.saveHideNewMark(widget.podcastLocal!.id, boo: boo);
|
|
||||||
if (mounted) setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _saveSkipSecondsStart(int? seconds) async {
|
|
||||||
await _dbHelper.saveSkipSecondsStart(widget.podcastLocal!.id, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _saveSkipSecondsEnd(int seconds) async {
|
|
||||||
await _dbHelper.saveSkipSecondsEnd(widget.podcastLocal!.id, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _getAutoDownload(String? id) async {
|
|
||||||
return await _dbHelper.getAutoDownload(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _getNeverUpdate(String? id) async {
|
|
||||||
return await _dbHelper.getNeverUpdate(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _getHideNewMark(String? id) async {
|
|
||||||
return await _dbHelper.getHideNewMark(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int?> _getSkipSecondStart(String? id) async {
|
|
||||||
return await _dbHelper.getSkipSecondsStart(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int?> _getSkipSecondEnd(String id) async {
|
|
||||||
return await _dbHelper.getSkipSecondsEnd(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _markListened(String? podcastId) async {
|
|
||||||
setState(() {
|
|
||||||
_markStatus = MarkStatus.start;
|
|
||||||
});
|
|
||||||
final episodes = await _dbHelper.getRssItem(podcastId, -1,
|
|
||||||
reverse: true, hideListened: true);
|
|
||||||
for (var episode in episodes) {
|
|
||||||
final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1);
|
|
||||||
await _dbHelper.saveHistory(history);
|
|
||||||
}
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_markStatus = MarkStatus.complete;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _refreshArtWork() async {
|
|
||||||
setState(() => _coverStatus = RefreshCoverStatus.start);
|
|
||||||
var options = BaseOptions(
|
|
||||||
connectTimeout: 30000,
|
|
||||||
receiveTimeout: 90000,
|
|
||||||
);
|
|
||||||
var dir = await getApplicationDocumentsDirectory();
|
|
||||||
var filePath = "${dir.path}/${widget.podcastLocal!.id}.png";
|
|
||||||
var dio = Dio(options);
|
|
||||||
String? imageUrl;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var response = await dio.get(widget.podcastLocal!.rssUrl);
|
|
||||||
try {
|
|
||||||
var p = RssFeed.parse(response.data);
|
|
||||||
imageUrl = p.itunes!.image!.href ?? p.image!.url;
|
|
||||||
} catch (e) {
|
|
||||||
developer.log(e.toString());
|
|
||||||
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
developer.log(e.toString());
|
|
||||||
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
|
||||||
}
|
|
||||||
if (imageUrl != null && imageUrl.contains('http')) {
|
|
||||||
try {
|
|
||||||
img.Image thumbnail;
|
|
||||||
var imageResponse = await dio.get<List<int>>(imageUrl,
|
|
||||||
options: Options(
|
|
||||||
responseType: ResponseType.bytes,
|
|
||||||
));
|
|
||||||
var image = img.decodeImage(imageResponse.data!)!;
|
|
||||||
thumbnail = img.copyResize(image, width: 300);
|
|
||||||
if (thumbnail != null) {
|
|
||||||
File(filePath)..writeAsBytesSync(img.encodePng(thumbnail));
|
|
||||||
_dbHelper.updatePodcastImage(
|
|
||||||
id: widget.podcastLocal!.id, filePath: filePath);
|
|
||||||
print('saved image');
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => _coverStatus = RefreshCoverStatus.complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
developer.log(e.toString());
|
|
||||||
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
|
||||||
}
|
|
||||||
} else if (_coverStatus == RefreshCoverStatus.start && mounted) {
|
|
||||||
setState(() => _coverStatus = RefreshCoverStatus.complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> _checkPermmison() async {
|
|
||||||
var permission = await Permission.storage.status;
|
|
||||||
if (permission != PermissionStatus.granted) {
|
|
||||||
var permissions = await [Permission.storage].request();
|
|
||||||
if (permissions[Permission.storage] == PermissionStatus.granted) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _getRefreshStatusIcon(RefreshCoverStatus status) {
|
|
||||||
switch (status) {
|
|
||||||
case RefreshCoverStatus.none:
|
|
||||||
return Center();
|
|
||||||
break;
|
|
||||||
case RefreshCoverStatus.start:
|
|
||||||
return CircularProgressIndicator(strokeWidth: 2);
|
|
||||||
break;
|
|
||||||
case RefreshCoverStatus.complete:
|
|
||||||
return Icon(Icons.done);
|
|
||||||
break;
|
|
||||||
case RefreshCoverStatus.error:
|
|
||||||
return Icon(Icons.refresh, color: Colors.red);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return Center();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
|
@ -341,42 +194,43 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
child: _getRefreshStatusIcon(_coverStatus)))),
|
child: _getRefreshStatusIcon(_coverStatus)))),
|
||||||
Divider(height: 1),
|
Divider(height: 1),
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_removeConfirm = false;
|
_removeConfirm = false;
|
||||||
_showStartTimePicker = false;
|
_showStartTimePicker = false;
|
||||||
_showEndTimePicker = false;
|
_showEndTimePicker = false;
|
||||||
_markConfirm = !_markConfirm;
|
_markConfirm = !_markConfirm;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
dense: true,
|
dense: true,
|
||||||
title: Row(
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 18,
|
height: 18,
|
||||||
width: 18,
|
width: 18,
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
painter: ListenedAllPainter(context.accentColor, stroke: 2),
|
painter: ListenedAllPainter(context.accentColor, stroke: 2),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
),
|
||||||
Text(s.menuMarkAllListened,
|
SizedBox(width: 20),
|
||||||
style: textStyle.copyWith(
|
Text(s.menuMarkAllListened,
|
||||||
color: context.accentColor,
|
style: textStyle.copyWith(
|
||||||
fontWeight: FontWeight.bold)),
|
color: context.accentColor, fontWeight: FontWeight.bold)),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
trailing: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: _markStatus == MarkStatus.none
|
||||||
|
? Center()
|
||||||
|
: _markStatus == MarkStatus.start
|
||||||
|
? CircularProgressIndicator(strokeWidth: 2)
|
||||||
|
: Icon(Icons.done),
|
||||||
),
|
),
|
||||||
trailing: Padding(
|
),
|
||||||
padding: const EdgeInsets.only(right: 10.0),
|
),
|
||||||
child: SizedBox(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
child: _markStatus == MarkStatus.none
|
|
||||||
? Center()
|
|
||||||
: _markStatus == MarkStatus.start
|
|
||||||
? CircularProgressIndicator(strokeWidth: 2)
|
|
||||||
: Icon(Icons.done)),
|
|
||||||
)),
|
|
||||||
if (_markConfirm)
|
if (_markConfirm)
|
||||||
Container(
|
Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
@ -384,7 +238,7 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: () => setState(() {
|
onPressed: () => setState(() {
|
||||||
_markConfirm = false;
|
_markConfirm = false;
|
||||||
}),
|
}),
|
||||||
|
@ -392,7 +246,7 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
s.cancel,
|
s.cancel,
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
)),
|
)),
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_markStatus != MarkStatus.start) {
|
if (_markStatus != MarkStatus.start) {
|
||||||
_markListened(widget.podcastLocal!.id);
|
_markListened(widget.podcastLocal!.id);
|
||||||
|
@ -402,7 +256,7 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Text(s.confirm,
|
child: Text(s.confirm,
|
||||||
style: TextStyle(color: context.accentColor))),
|
style: TextStyle(color: context.error))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -433,15 +287,14 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: () => setState(() {
|
onPressed: () => setState(() {
|
||||||
_removeConfirm = false;
|
_removeConfirm = false;
|
||||||
}),
|
}),
|
||||||
child:
|
child:
|
||||||
Text(s.cancel, style: TextStyle(color: Colors.grey[600])),
|
Text(s.cancel, style: TextStyle(color: Colors.grey[600])),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: Colors.red.withAlpha(70),
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await groupList.removePodcast(widget.podcastLocal!);
|
await groupList.removePodcast(widget.podcastLocal!);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
@ -454,6 +307,147 @@ class _PodcastSettingState extends State<PodcastSetting> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _setAutoDownload(bool boo) async {
|
||||||
|
var permission = await _checkPermmison();
|
||||||
|
if (permission) {
|
||||||
|
await _dbHelper.saveAutoDownload(widget.podcastLocal!.id, boo: boo);
|
||||||
|
}
|
||||||
|
if (mounted) setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _setNeverUpdate(bool boo) async {
|
||||||
|
await _dbHelper.saveNeverUpdate(widget.podcastLocal!.id, boo: boo);
|
||||||
|
if (mounted) setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _setHideNewMark(bool boo) async {
|
||||||
|
await _dbHelper.saveHideNewMark(widget.podcastLocal!.id, boo: boo);
|
||||||
|
if (mounted) setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _saveSkipSecondsStart(int? seconds) async {
|
||||||
|
await _dbHelper.saveSkipSecondsStart(widget.podcastLocal!.id, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _saveSkipSecondsEnd(int seconds) async {
|
||||||
|
await _dbHelper.saveSkipSecondsEnd(widget.podcastLocal!.id, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getAutoDownload(String? id) async {
|
||||||
|
return await _dbHelper.getAutoDownload(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getNeverUpdate(String? id) async {
|
||||||
|
return await _dbHelper.getNeverUpdate(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _getHideNewMark(String? id) async {
|
||||||
|
return await _dbHelper.getHideNewMark(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int?> _getSkipSecondStart(String? id) async {
|
||||||
|
return await _dbHelper.getSkipSecondsStart(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int?> _getSkipSecondEnd(String id) async {
|
||||||
|
return await _dbHelper.getSkipSecondsEnd(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _markListened(String? podcastId) async {
|
||||||
|
setState(() {
|
||||||
|
_markStatus = MarkStatus.start;
|
||||||
|
});
|
||||||
|
final episodes = await _dbHelper.getRssItem(podcastId, -1,
|
||||||
|
reverse: true, hideListened: true);
|
||||||
|
for (var episode in episodes) {
|
||||||
|
final history = PlayHistory(episode.title, episode.enclosureUrl, 0, 1);
|
||||||
|
await _dbHelper.saveHistory(history);
|
||||||
|
}
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_markStatus = MarkStatus.complete;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _refreshArtWork() async {
|
||||||
|
setState(() => _coverStatus = RefreshCoverStatus.start);
|
||||||
|
var options = BaseOptions(
|
||||||
|
connectTimeout: 30000,
|
||||||
|
receiveTimeout: 90000,
|
||||||
|
);
|
||||||
|
var dir = await getApplicationDocumentsDirectory();
|
||||||
|
var filePath = "${dir.path}/${widget.podcastLocal!.id}.png";
|
||||||
|
var dio = Dio(options);
|
||||||
|
String? imageUrl;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var response = await dio.get(widget.podcastLocal!.rssUrl);
|
||||||
|
try {
|
||||||
|
var p = RssFeed.parse(response.data);
|
||||||
|
imageUrl = p.itunes!.image!.href ?? p.image!.url;
|
||||||
|
} catch (e) {
|
||||||
|
developer.log(e.toString());
|
||||||
|
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
developer.log(e.toString());
|
||||||
|
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
||||||
|
}
|
||||||
|
if (imageUrl != null && imageUrl.contains('http')) {
|
||||||
|
try {
|
||||||
|
img.Image thumbnail;
|
||||||
|
var imageResponse = await dio.get<List<int>>(imageUrl,
|
||||||
|
options: Options(
|
||||||
|
responseType: ResponseType.bytes,
|
||||||
|
));
|
||||||
|
var image = img.decodeImage(imageResponse.data!)!;
|
||||||
|
thumbnail = img.copyResize(image, width: 300);
|
||||||
|
File(filePath)..writeAsBytesSync(img.encodePng(thumbnail));
|
||||||
|
_dbHelper.updatePodcastImage(
|
||||||
|
id: widget.podcastLocal!.id, filePath: filePath);
|
||||||
|
print('saved image');
|
||||||
|
if (mounted) {
|
||||||
|
setState(() => _coverStatus = RefreshCoverStatus.complete);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
developer.log(e.toString());
|
||||||
|
if (mounted) setState(() => _coverStatus = RefreshCoverStatus.error);
|
||||||
|
}
|
||||||
|
} else if (_coverStatus == RefreshCoverStatus.start && mounted) {
|
||||||
|
setState(() => _coverStatus = RefreshCoverStatus.complete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _checkPermmison() async {
|
||||||
|
var permission = await Permission.storage.status;
|
||||||
|
if (permission != PermissionStatus.granted) {
|
||||||
|
var permissions = await [Permission.storage].request();
|
||||||
|
if (permissions[Permission.storage] == PermissionStatus.granted) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _getRefreshStatusIcon(RefreshCoverStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case RefreshCoverStatus.none:
|
||||||
|
return Center();
|
||||||
|
case RefreshCoverStatus.start:
|
||||||
|
return CircularProgressIndicator(strokeWidth: 2);
|
||||||
|
case RefreshCoverStatus.complete:
|
||||||
|
return Icon(Icons.done);
|
||||||
|
case RefreshCoverStatus.error:
|
||||||
|
return Icon(Icons.refresh, color: Colors.red);
|
||||||
|
default:
|
||||||
|
return Center();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TimePicker extends StatelessWidget {
|
class _TimePicker extends StatelessWidget {
|
||||||
|
@ -477,15 +471,16 @@ class _TimePicker extends StatelessWidget {
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
FlatButton(
|
TextButton(
|
||||||
onPressed: onCancel,
|
onPressed: onCancel,
|
||||||
child: Text(
|
child: Text(
|
||||||
s.cancel,
|
s.cancel,
|
||||||
style: TextStyle(color: Colors.grey[600]),
|
style: TextStyle(color: Colors.grey[600]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
FlatButton(
|
TextButton(
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
style: TextButton.styleFrom(
|
||||||
|
surfaceTintColor: context.priamryContainer),
|
||||||
onPressed: onConfirm,
|
onPressed: onConfirm,
|
||||||
child: Text(
|
child: Text(
|
||||||
s.confirm,
|
s.confirm,
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_html/flutter_html.dart';
|
import 'package:flutter_html/flutter_html.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -20,78 +18,6 @@ import 'podcast_detail.dart';
|
||||||
import 'podcast_manage.dart';
|
import 'podcast_manage.dart';
|
||||||
import 'podcast_settings.dart';
|
import 'podcast_settings.dart';
|
||||||
|
|
||||||
class AboutPodcast extends StatefulWidget {
|
|
||||||
final PodcastLocal? podcastLocal;
|
|
||||||
AboutPodcast({this.podcastLocal, Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_AboutPodcastState createState() => _AboutPodcastState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AboutPodcastState extends State<AboutPodcast> {
|
|
||||||
String? _description;
|
|
||||||
late bool _load;
|
|
||||||
|
|
||||||
void getDescription(String? id) async {
|
|
||||||
var dbHelper = DBHelper();
|
|
||||||
var description = await dbHelper.getFeedDescription(id);
|
|
||||||
_description = description;
|
|
||||||
setState(() {
|
|
||||||
_load = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_load = false;
|
|
||||||
getDescription(widget.podcastLocal!.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
var _groupList = Provider.of<GroupList>(context, listen: false);
|
|
||||||
final s = context.s;
|
|
||||||
return AlertDialog(
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
|
|
||||||
titlePadding: EdgeInsets.only(
|
|
||||||
top: 20, left: 20, right: context.width / 3, bottom: 20),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
splashColor: context.accentColor.withAlpha(70),
|
|
||||||
padding: EdgeInsets.all(10.0),
|
|
||||||
onPressed: () {
|
|
||||||
_groupList.removePodcast(widget.podcastLocal!);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
textColor: Colors.red,
|
|
||||||
child: Text(
|
|
||||||
s.remove,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
title: Text(widget.podcastLocal!.title!),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.vertical,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
!_load
|
|
||||||
? Center()
|
|
||||||
: _description != null
|
|
||||||
? Html(data: _description)
|
|
||||||
: Center(),
|
|
||||||
if (widget.podcastLocal!.author != null)
|
|
||||||
Text(widget.podcastLocal!.author!,
|
|
||||||
style: TextStyle(color: Colors.blue))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PodcastList extends StatefulWidget {
|
class PodcastList extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_PodcastListState createState() => _PodcastListState();
|
_PodcastListState createState() => _PodcastListState();
|
||||||
|
@ -108,32 +34,34 @@ class _PodcastListState extends State<PodcastList> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final width = context.width;
|
final width = context.width;
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: context.overlay,
|
||||||
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
|
child: SafeArea(
|
||||||
systemNavigationBarColor: context.primaryColor,
|
child: Scaffold(
|
||||||
systemNavigationBarIconBrightness:
|
backgroundColor: context.background,
|
||||||
Theme.of(context).accentColorBrightness,
|
appBar: AppBar(
|
||||||
),
|
backgroundColor: context.background,
|
||||||
child: Scaffold(
|
title: Text(context.s.podcast(2)),
|
||||||
appBar: AppBar(
|
leading: CustomBackButton(),
|
||||||
title: Text(context.s.podcast(2)),
|
actions: [
|
||||||
leading: CustomBackButton(),
|
Selector<SettingState, bool?>(
|
||||||
actions: [
|
|
||||||
Selector<SettingState, bool?>(
|
|
||||||
selector: (_, setting) => setting.openAllPodcastDefalt,
|
selector: (_, setting) => setting.openAllPodcastDefalt,
|
||||||
builder: (_, data, __) {
|
builder: (_, data, __) {
|
||||||
return data!
|
if (!data!) return Center();
|
||||||
? IconButton(
|
return IconButton(
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
icon: Icon(Icons.all_out),
|
icon: Icon(Icons.all_out),
|
||||||
onPressed: () => Navigator.push(
|
onPressed: () => Navigator.push(
|
||||||
context, ScaleRoute(page: PodcastManage())))
|
context,
|
||||||
: Center();
|
ScaleRoute(
|
||||||
})
|
page: PodcastManage(),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
);
|
||||||
child: Container(
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
color: context.primaryColor,
|
color: context.primaryColor,
|
||||||
child: FutureBuilder<List<PodcastLocal>>(
|
child: FutureBuilder<List<PodcastLocal>>(
|
||||||
future: _getPodcastLocal(),
|
future: _getPodcastLocal(),
|
||||||
|
@ -212,9 +140,10 @@ class _PodcastListState extends State<PodcastList> {
|
||||||
}
|
}
|
||||||
return Center(
|
return Center(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20,
|
width: 20,
|
||||||
child: CircularProgressIndicator()),
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -45,7 +45,7 @@ class _DataBackupState extends State<DataBackup> {
|
||||||
systemNavigationBarIconBrightness: context.brightness,
|
systemNavigationBarIconBrightness: context.brightness,
|
||||||
),
|
),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
title: Text(s.settingsBackup),
|
title: Text(s.settingsBackup),
|
||||||
|
|
|
@ -44,7 +44,7 @@ class _PlayedHistoryState extends State<PlayedHistory>
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: context.overlay,
|
value: context.overlay,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: NestedScrollView(
|
child: NestedScrollView(
|
||||||
headerSliverBuilder: (context, innerBoxScrolled) {
|
headerSliverBuilder: (context, innerBoxScrolled) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ class _LayoutSettingState extends State<LayoutSetting> {
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: context.overlay,
|
value: context.overlay,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(s.settingsLayout),
|
title: Text(s.settingsLayout),
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
|
|
|
@ -46,7 +46,7 @@ class _PlaySettingState extends State<PlaySetting> {
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: context.overlay,
|
value: context.overlay,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(s.play),
|
title: Text(s.play),
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
|
|
|
@ -72,16 +72,16 @@ class _SettingsState extends State<Settings> {
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarIconBrightness: context.brightness,
|
statusBarIconBrightness: context.brightness,
|
||||||
systemNavigationBarColor: context.onPrimary,
|
systemNavigationBarColor: context.background,
|
||||||
systemNavigationBarIconBrightness: context.iconBrightness,
|
systemNavigationBarIconBrightness: context.iconBrightness,
|
||||||
),
|
),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(s.settings),
|
title: Text(s.settings),
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
elevation: _showTitle ? 1 : 0,
|
elevation: _showTitle ? 1 : 0,
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
|
|
|
@ -46,7 +46,7 @@ class _StorageSettingState extends State<StorageSetting>
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: context.overlay,
|
value: context.overlay,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(s.settingStorage),
|
title: Text(s.settingStorage),
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
|
|
|
@ -11,16 +11,16 @@ class ThemeSetting extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
var settings = Provider.of<SettingState>(context, listen: false);
|
final settings = Provider.of<SettingState>(context, listen: false);
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: context.overlay,
|
value: context.overlay,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(s.settingsAppearance),
|
title: Text(s.settingsAppearance),
|
||||||
leading: CustomBackButton(),
|
leading: CustomBackButton(),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
backgroundColor: context.onPrimary,
|
backgroundColor: context.background,
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
@ -52,7 +52,7 @@ class ThemeSetting extends StatelessWidget {
|
||||||
pageBuilder: (context, animaiton, secondaryAnimation) =>
|
pageBuilder: (context, animaiton, secondaryAnimation) =>
|
||||||
AnnotatedRegion<SystemUiOverlayStyle>(
|
AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarIconBrightness: Brightness.light,
|
statusBarColor: Colors.transparent,
|
||||||
systemNavigationBarColor:
|
systemNavigationBarColor:
|
||||||
Theme.of(context).brightness == Brightness.light
|
Theme.of(context).brightness == Brightness.light
|
||||||
? Color.fromRGBO(113, 113, 113, 1)
|
? Color.fromRGBO(113, 113, 113, 1)
|
||||||
|
@ -151,13 +151,18 @@ class ThemeSetting extends StatelessWidget {
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () => generalDialog(
|
onTap: () => generalDialog(
|
||||||
context,
|
context,
|
||||||
title: Text.rich(TextSpan(text: s.chooseA, children: [
|
title: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: ' ${s.color}',
|
text: s.chooseA,
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontWeight: FontWeight.bold,
|
TextSpan(
|
||||||
color: context.accentColor))
|
text: ' ${s.color}',
|
||||||
])),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: context.accentColor))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
content: _ColorPicker(
|
content: _ColorPicker(
|
||||||
onColorChanged: (value) => settings.setAccentColor = value,
|
onColorChanged: (value) => settings.setAccentColor = value,
|
||||||
),
|
),
|
||||||
|
@ -253,29 +258,6 @@ class __ColorPickerState extends State<_ColorPicker>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _colorCircle(Color color) => Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
|
||||||
onTap: () => widget.onColorChanged!(color),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: color == context.accentColor
|
|
||||||
? Border.all(color: Colors.grey[400]!, width: 4)
|
|
||||||
: null,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
|
||||||
color: color),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
List<Widget> _accentList(MaterialAccentColor color) => [
|
|
||||||
_colorCircle(color.shade100),
|
|
||||||
_colorCircle(color.shade200),
|
|
||||||
_colorCircle(color.shade400),
|
|
||||||
_colorCircle(color.shade700)
|
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
|
@ -397,4 +379,27 @@ class __ColorPickerState extends State<_ColorPicker>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _colorCircle(Color color) => Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
onTap: () => widget.onColorChanged!(color),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: color == context.accentColor
|
||||||
|
? Border.all(color: Colors.grey[400]!, width: 4)
|
||||||
|
: null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
color: color),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _accentList(MaterialAccentColor color) => [
|
||||||
|
_colorCircle(color.shade100),
|
||||||
|
_colorCircle(color.shade200),
|
||||||
|
_colorCircle(color.shade400),
|
||||||
|
_colorCircle(color.shade700)
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@ extension ContextExtension on BuildContext {
|
||||||
double get paddingTop => MediaQuery.of(this).padding.top;
|
double get paddingTop => MediaQuery.of(this).padding.top;
|
||||||
TextTheme get textTheme => Theme.of(this).textTheme;
|
TextTheme get textTheme => Theme.of(this).textTheme;
|
||||||
SystemUiOverlayStyle get overlay => SystemUiOverlayStyle(
|
SystemUiOverlayStyle get overlay => SystemUiOverlayStyle(
|
||||||
statusBarColor: onPrimary,
|
statusBarColor: background,
|
||||||
statusBarIconBrightness: iconBrightness,
|
statusBarIconBrightness: iconBrightness,
|
||||||
systemNavigationBarColor: onPrimary,
|
systemNavigationBarColor: background,
|
||||||
systemNavigationBarIconBrightness: iconBrightness,
|
systemNavigationBarIconBrightness: iconBrightness,
|
||||||
);
|
);
|
||||||
S get s => S.of(this)!;
|
S get s => S.of(this)!;
|
||||||
|
|
|
@ -72,11 +72,11 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
|
|
||||||
Future<Tuple5<int, bool, bool, bool, List<int>>> _initData(
|
Future<Tuple5<int, bool, bool, bool, List<int>>> _initData(
|
||||||
EpisodeBrief episode) async {
|
EpisodeBrief episode) async {
|
||||||
var menuList = await _getEpisodeMenu();
|
final menuList = await _getEpisodeMenu();
|
||||||
var tapToOpen = await _getTapToOpenPopupMenu();
|
final tapToOpen = await _getTapToOpenPopupMenu();
|
||||||
var listened = await _isListened(episode);
|
final listened = await _isListened(episode);
|
||||||
var liked = await _isLiked(episode);
|
final liked = await _isLiked(episode);
|
||||||
var downloaded = await _isDownloaded(episode);
|
final downloaded = await _isDownloaded(episode);
|
||||||
return Tuple5(listened, liked, downloaded, tapToOpen, menuList);
|
return Tuple5(listened, liked, downloaded, tapToOpen, menuList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +85,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<int>> _getEpisodeMenu() async {
|
Future<List<int>> _getEpisodeMenu() async {
|
||||||
var popupMenuStorage = KeyValueStorage(episodePopupMenuKey);
|
final popupMenuStorage = KeyValueStorage(episodePopupMenuKey);
|
||||||
var list = await popupMenuStorage.getMenu();
|
final list = await popupMenuStorage.getMenu();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _getTapToOpenPopupMenu() async {
|
Future<bool> _getTapToOpenPopupMenu() async {
|
||||||
var tapToOpenPopupMenuStorage = KeyValueStorage(tapToOpenPopupMenuKey);
|
final tapToOpenPopupMenuStorage = KeyValueStorage(tapToOpenPopupMenuKey);
|
||||||
var boo = await tapToOpenPopupMenuStorage.getBool(defaultValue: false);
|
final boo = await tapToOpenPopupMenuStorage.getBool(defaultValue: false);
|
||||||
return boo;
|
return boo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,102 +307,131 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
Color? color,
|
Color? color,
|
||||||
bool? isLiked,
|
bool? isLiked,
|
||||||
bool? isDownloaded,
|
bool? isDownloaded,
|
||||||
|
Color? cardColor,
|
||||||
|
required int isListened,
|
||||||
bool? boo}) {
|
bool? boo}) {
|
||||||
var width = context.width;
|
final width = context.width;
|
||||||
if (layout == Layout.one) {
|
if (layout == Layout.one) {
|
||||||
return _layoutOneCard(context,
|
return _layoutOneCard(context,
|
||||||
index: index!,
|
index: index!,
|
||||||
color: color,
|
color: color,
|
||||||
isLiked: isLiked!,
|
isLiked: isLiked!,
|
||||||
|
cardColor: cardColor,
|
||||||
|
isListened: isListened,
|
||||||
isDownloaded: isDownloaded,
|
isDownloaded: isDownloaded,
|
||||||
boo: boo!);
|
boo: boo!);
|
||||||
}
|
}
|
||||||
return Padding(
|
return Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
decoration: BoxDecoration(
|
||||||
child: Column(
|
color: cardColor,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
children: <Widget>[
|
),
|
||||||
Expanded(
|
clipBehavior: Clip.hardEdge,
|
||||||
flex: layout == Layout.one ? 1 : 2,
|
child: Stack(
|
||||||
child: Row(
|
alignment: AlignmentDirectional.bottomCenter,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
if (isListened > 0)
|
||||||
children: <Widget>[
|
Container(
|
||||||
layout != Layout.one
|
height: 4,
|
||||||
? _circleImage(context,
|
color: context.accentColor,
|
||||||
episode: episodes![index!], color: color, boo: boo!)
|
|
||||||
: _pubDate(context,
|
|
||||||
episode: episodes![index!], color: color),
|
|
||||||
Spacer(),
|
|
||||||
_isNewIndicator(episodes![index]),
|
|
||||||
_downloadIndicater(context,
|
|
||||||
episode: episodes![index], isDownloaded: isDownloaded),
|
|
||||||
_numberIndicater(context, index: index, color: color)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Expanded(
|
padding: const EdgeInsets.all(8.0),
|
||||||
flex: layout == Layout.one ? 3 : 5,
|
child: Column(
|
||||||
child: layout != Layout.one
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
? _title(episodes![index])
|
mainAxisSize: MainAxisSize.min,
|
||||||
: Row(
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
flex: layout == Layout.one ? 1 : 2,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: <Widget>[
|
||||||
_circleImage(context,
|
layout != Layout.one
|
||||||
episode: episodes![index], color: color, boo: boo!),
|
? _circleImage(context,
|
||||||
SizedBox(
|
episode: episodes![index!],
|
||||||
width: 5,
|
color: color,
|
||||||
),
|
boo: boo!)
|
||||||
Expanded(child: _title(episodes![index]))
|
: _pubDate(context,
|
||||||
|
episode: episodes![index!], color: color),
|
||||||
|
Spacer(),
|
||||||
|
_isNewIndicator(episodes![index]),
|
||||||
|
_downloadIndicater(context,
|
||||||
|
episode: episodes![index],
|
||||||
|
isDownloaded: isDownloaded),
|
||||||
|
_numberIndicater(context, index: index, color: color)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: layout == Layout.one ? 3 : 5,
|
||||||
|
child: layout != Layout.one
|
||||||
|
? _title(episodes![index])
|
||||||
|
: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_circleImage(context,
|
||||||
|
episode: episodes![index],
|
||||||
|
color: color,
|
||||||
|
boo: boo!),
|
||||||
|
SizedBox(
|
||||||
|
width: 5,
|
||||||
|
),
|
||||||
|
Expanded(child: _title(episodes![index]))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
if (layout != Layout.one)
|
||||||
|
_pubDate(context,
|
||||||
|
episode: episodes![index], color: color),
|
||||||
|
Spacer(),
|
||||||
|
if (layout != Layout.three &&
|
||||||
|
episodes![index].duration != 0)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
episodes![index].duration!.toTime,
|
||||||
|
style: TextStyle(fontSize: width / 35),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (episodes![index].duration != 0 &&
|
||||||
|
episodes![index].enclosureLength != null &&
|
||||||
|
episodes![index].enclosureLength != 0 &&
|
||||||
|
layout != Layout.three)
|
||||||
|
Text(
|
||||||
|
'|',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: width / 35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (layout != Layout.three &&
|
||||||
|
episodes![index].enclosureLength != null &&
|
||||||
|
episodes![index].enclosureLength != 0)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'${episodes![index].enclosureLength! ~/ 1000000}MB',
|
||||||
|
style: TextStyle(fontSize: width / 35),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(1),
|
||||||
|
),
|
||||||
|
if ((showFavorite || layout != Layout.three) && isLiked!)
|
||||||
|
Icon(
|
||||||
|
Icons.favorite,
|
||||||
|
color: Colors.red,
|
||||||
|
size: width / 35,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
if (layout != Layout.one)
|
|
||||||
_pubDate(context, episode: episodes![index], color: color),
|
|
||||||
Spacer(),
|
|
||||||
if (layout != Layout.three && episodes![index].duration != 0)
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(
|
|
||||||
episodes![index].duration!.toTime,
|
|
||||||
style: TextStyle(fontSize: width / 35),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (episodes![index].duration != 0 &&
|
|
||||||
episodes![index].enclosureLength != null &&
|
|
||||||
episodes![index].enclosureLength != 0 &&
|
|
||||||
layout != Layout.three)
|
|
||||||
Text(
|
|
||||||
'|',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: width / 35,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (layout != Layout.three &&
|
|
||||||
episodes![index].enclosureLength != null &&
|
|
||||||
episodes![index].enclosureLength != 0)
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(
|
|
||||||
'${episodes![index].enclosureLength! ~/ 1000000}MB',
|
|
||||||
style: TextStyle(fontSize: width / 35),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.all(1),
|
|
||||||
),
|
),
|
||||||
if ((showFavorite || layout != Layout.three) && isLiked!)
|
|
||||||
Icon(
|
|
||||||
Icons.favorite,
|
|
||||||
color: Colors.red,
|
|
||||||
size: width / 35,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -416,106 +445,127 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
Color? color,
|
Color? color,
|
||||||
required bool isLiked,
|
required bool isLiked,
|
||||||
bool? isDownloaded,
|
bool? isDownloaded,
|
||||||
|
Color? cardColor,
|
||||||
|
required int isListened,
|
||||||
required bool boo}) {
|
required bool boo}) {
|
||||||
var width = context.width;
|
var width = context.width;
|
||||||
return Padding(
|
return Container(
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
decoration: BoxDecoration(
|
||||||
child: Row(
|
color: cardColor,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
mainAxisSize: MainAxisSize.min,
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
clipBehavior: Clip.hardEdge,
|
||||||
|
child: Stack(
|
||||||
|
alignment: AlignmentDirectional.bottomCenter,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
if (isListened > 0)
|
||||||
flex: 1,
|
Container(
|
||||||
child: Center(
|
height: 4,
|
||||||
child: _circleImage(context,
|
color: context.accentColor,
|
||||||
episode: episodes![index],
|
|
||||||
color: color,
|
|
||||||
boo: boo,
|
|
||||||
radius: context.width / 8),
|
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Expanded(
|
padding: const EdgeInsets.all(8.0),
|
||||||
flex: 4,
|
child: Row(
|
||||||
child: Column(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Row(
|
child: Center(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: _circleImage(context,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
episode: episodes![index],
|
||||||
children: <Widget>[
|
color: color,
|
||||||
Expanded(
|
boo: boo,
|
||||||
child: Text(episodes![index].feedTitle!,
|
radius: context.width / 8),
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold, color: color)),
|
|
||||||
),
|
|
||||||
_isNewIndicator(episodes![index]),
|
|
||||||
_downloadIndicater(context,
|
|
||||||
episode: episodes![index],
|
|
||||||
isDownloaded: isDownloaded),
|
|
||||||
_numberIndicater(context, index: index, color: color)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: Align(
|
child: Column(
|
||||||
alignment: Alignment.topLeft,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: _title(episodes![index]))),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Expanded(
|
children: [
|
||||||
flex: 1,
|
Expanded(
|
||||||
child: Row(
|
flex: 1,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
if (episodes![index].duration != 0)
|
children: <Widget>[
|
||||||
Align(
|
Expanded(
|
||||||
alignment: Alignment.center,
|
child: Text(episodes![index].feedTitle!,
|
||||||
child: Text(
|
maxLines: 1,
|
||||||
episodes![index].duration!.toTime,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(fontSize: width / 35),
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: color)),
|
||||||
),
|
),
|
||||||
),
|
_isNewIndicator(episodes![index]),
|
||||||
if (episodes![index].duration != 0 &&
|
_downloadIndicater(context,
|
||||||
episodes![index].enclosureLength != null &&
|
episode: episodes![index],
|
||||||
episodes![index].enclosureLength != 0 &&
|
isDownloaded: isDownloaded),
|
||||||
layout != Layout.three)
|
_numberIndicater(context,
|
||||||
Text(
|
index: index, color: color)
|
||||||
'|',
|
],
|
||||||
style: TextStyle(
|
),
|
||||||
fontSize: width / 35,
|
),
|
||||||
),
|
Expanded(
|
||||||
),
|
flex: 2,
|
||||||
if (episodes![index].enclosureLength != null &&
|
child: Align(
|
||||||
episodes![index].enclosureLength != 0)
|
alignment: Alignment.topLeft,
|
||||||
Align(
|
child: _title(episodes![index]))),
|
||||||
alignment: Alignment.center,
|
Expanded(
|
||||||
child: Text(
|
flex: 1,
|
||||||
'${episodes![index].enclosureLength! ~/ 1000000}MB',
|
child: Row(
|
||||||
style: TextStyle(fontSize: width / 35),
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
children: <Widget>[
|
||||||
SizedBox(width: 4),
|
if (episodes![index].duration != 0)
|
||||||
if (isLiked)
|
Align(
|
||||||
Icon(
|
alignment: Alignment.center,
|
||||||
Icons.favorite,
|
child: Text(
|
||||||
color: Colors.red,
|
episodes![index].duration!.toTime,
|
||||||
size: width / 35,
|
style: TextStyle(fontSize: width / 35),
|
||||||
),
|
),
|
||||||
Spacer(),
|
),
|
||||||
_pubDate(context,
|
if (episodes![index].duration != 0 &&
|
||||||
episode: episodes![index], color: color),
|
episodes![index].enclosureLength != null &&
|
||||||
]),
|
episodes![index].enclosureLength != 0 &&
|
||||||
)
|
layout != Layout.three)
|
||||||
|
Text(
|
||||||
|
'|',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: width / 35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (episodes![index].enclosureLength != null &&
|
||||||
|
episodes![index].enclosureLength != 0)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
'${episodes![index].enclosureLength! ~/ 1000000}MB',
|
||||||
|
style: TextStyle(fontSize: width / 35),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
if (isLiked)
|
||||||
|
Icon(
|
||||||
|
Icons.favorite,
|
||||||
|
color: Colors.red,
|
||||||
|
size: width / 35,
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
_pubDate(context,
|
||||||
|
episode: episodes![index], color: color),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 8)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -533,7 +583,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
final s = context.s;
|
final s = context.s;
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 10.0, bottom: 5.0, left: 15.0, right: 15.0),
|
top: 10.0, bottom: 5.0, left: 10.0, right: 10.0),
|
||||||
sliver: LiveSliverGrid.options(
|
sliver: LiveSliverGrid.options(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -549,8 +599,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
: layout == Layout.two
|
: layout == Layout.two
|
||||||
? 2
|
? 2
|
||||||
: 1,
|
: 1,
|
||||||
mainAxisSpacing: 6.0,
|
mainAxisSpacing: 10.0,
|
||||||
crossAxisSpacing: 6.0,
|
crossAxisSpacing: 10.0,
|
||||||
),
|
),
|
||||||
itemBuilder: (context, index, animation) {
|
itemBuilder: (context, index, animation) {
|
||||||
final c = episodes![index].backgroudColor(context);
|
final c = episodes![index].backgroudColor(context);
|
||||||
|
@ -576,28 +626,31 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
future: _initData(episodes![index]),
|
future: _initData(episodes![index]),
|
||||||
initialData: Tuple5(0, false, false, false, []),
|
initialData: Tuple5(0, false, false, false, []),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
var isListened = snapshot.data!.item1;
|
final isListened = snapshot.data!.item1;
|
||||||
var isLiked = snapshot.data!.item2;
|
final isLiked = snapshot.data!.item2;
|
||||||
var isDownloaded = snapshot.data!.item3;
|
final isDownloaded = snapshot.data!.item3;
|
||||||
var tapToOpen = snapshot.data!.item4;
|
final tapToOpen = snapshot.data!.item4;
|
||||||
var menuList = snapshot.data!.item5;
|
final menuList = snapshot.data!.item5;
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(5.0)),
|
// borderRadius: BorderRadius.all(
|
||||||
color: isListened > 0
|
// Radius.circular(15.0),
|
||||||
? context.brightness == Brightness.light
|
// ),
|
||||||
? Colors.grey[200]
|
// color: isListened > 0
|
||||||
: Color.fromRGBO(50, 50, 50, 1)
|
// ? context.brightness == Brightness.light
|
||||||
: context.background,
|
// ? Colors.grey[200]
|
||||||
boxShadow: [
|
// : Color.fromRGBO(50, 50, 50, 1)
|
||||||
BoxShadow(
|
// : context.priamryContainer,
|
||||||
color: context.brightness == Brightness.light
|
// ),
|
||||||
? context.primaryColor
|
// boxShadow: [
|
||||||
: Color.fromRGBO(40, 40, 40, 1),
|
// BoxShadow(
|
||||||
blurRadius: 0.5,
|
// color: context.brightness == Brightness.light
|
||||||
spreadRadius: 0.5,
|
// ? context.primaryColor
|
||||||
),
|
// : Color.fromRGBO(40, 40, 40, 1),
|
||||||
]),
|
// blurRadius: 0.5,
|
||||||
|
// spreadRadius: 0.5,
|
||||||
|
// ),
|
||||||
|
// ]),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: multiSelect!
|
child: multiSelect!
|
||||||
? Material(
|
? Material(
|
||||||
|
@ -616,7 +669,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
borderRadius: BorderRadius.circular(15.0),
|
||||||
|
color: episodes![index].cardColor(context),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: selectedList!
|
color: selectedList!
|
||||||
.contains(episodes![index])
|
.contains(episodes![index])
|
||||||
|
@ -632,6 +686,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
index: index,
|
index: index,
|
||||||
isLiked: isLiked,
|
isLiked: isLiked,
|
||||||
isDownloaded: isDownloaded,
|
isDownloaded: isDownloaded,
|
||||||
|
isListened: isListened,
|
||||||
color: c,
|
color: c,
|
||||||
boo: boo),
|
boo: boo),
|
||||||
),
|
),
|
||||||
|
@ -639,7 +694,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(5.0),
|
color: episodes![index].cardColor(context),
|
||||||
|
borderRadius: BorderRadius.circular(20.0),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: context.brightness == Brightness.light
|
color: context.brightness == Brightness.light
|
||||||
? context.primaryColor
|
? context.primaryColor
|
||||||
|
@ -652,7 +708,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
menuItemExtent: 45,
|
menuItemExtent: 45,
|
||||||
menuBoxDecoration: BoxDecoration(
|
menuBoxDecoration: BoxDecoration(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(15.0)),
|
borderRadius: BorderRadius.circular(20.0)),
|
||||||
duration: Duration(milliseconds: 100),
|
duration: Duration(milliseconds: 100),
|
||||||
tapMode: tapToOpen
|
tapMode: tapToOpen
|
||||||
? TapMode.onTap
|
? TapMode.onTap
|
||||||
|
@ -666,10 +722,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
menuOffset: 6,
|
menuOffset: 6,
|
||||||
menuItems: <FocusedMenuItem>[
|
menuItems: <FocusedMenuItem>[
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor:
|
backgroundColor: context.priamryContainer,
|
||||||
context.brightness == Brightness.light
|
|
||||||
? context.primaryColor
|
|
||||||
: context.dialogBackgroundColor,
|
|
||||||
title: Text(
|
title: Text(
|
||||||
data.item1 != episodes![index] ||
|
data.item1 != episodes![index] ||
|
||||||
!data.item4
|
!data.item4
|
||||||
|
@ -687,10 +740,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}),
|
}),
|
||||||
if (menuList.contains(1))
|
if (menuList.contains(1))
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor: context.brightness ==
|
backgroundColor:
|
||||||
Brightness.light
|
context.priamryContainer,
|
||||||
? context.primaryColor
|
|
||||||
: context.dialogBackgroundColor,
|
|
||||||
title: data.item2.contains(
|
title: data.item2.contains(
|
||||||
episodes![index].enclosureUrl)
|
episodes![index].enclosureUrl)
|
||||||
? Text(s.remove)
|
? Text(s.remove)
|
||||||
|
@ -719,10 +770,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}),
|
}),
|
||||||
if (menuList.contains(2))
|
if (menuList.contains(2))
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor: context.brightness ==
|
backgroundColor:
|
||||||
Brightness.light
|
context.priamryContainer,
|
||||||
? context.primaryColor
|
|
||||||
: context.dialogBackgroundColor,
|
|
||||||
title: isLiked
|
title: isLiked
|
||||||
? Text(s.unlike)
|
? Text(s.unlike)
|
||||||
: Text(s.like),
|
: Text(s.like),
|
||||||
|
@ -749,10 +798,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}),
|
}),
|
||||||
if (menuList.contains(3))
|
if (menuList.contains(3))
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor: context.brightness ==
|
backgroundColor:
|
||||||
Brightness.light
|
context.priamryContainer,
|
||||||
? context.primaryColor
|
|
||||||
: context.dialogBackgroundColor,
|
|
||||||
title: isListened > 0
|
title: isListened > 0
|
||||||
? Text(s.markNotListened,
|
? Text(s.markNotListened,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -792,10 +839,8 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}),
|
}),
|
||||||
if (menuList.contains(4))
|
if (menuList.contains(4))
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor: context.brightness ==
|
backgroundColor:
|
||||||
Brightness.light
|
context.priamryContainer,
|
||||||
? context.primaryColor
|
|
||||||
: context.dialogBackgroundColor,
|
|
||||||
title: isDownloaded
|
title: isDownloaded
|
||||||
? Text(s.downloaded,
|
? Text(s.downloaded,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -812,30 +857,33 @@ class EpisodeGrid extends StatelessWidget {
|
||||||
}),
|
}),
|
||||||
if (menuList.contains(5))
|
if (menuList.contains(5))
|
||||||
FocusedMenuItem(
|
FocusedMenuItem(
|
||||||
backgroundColor: context.brightness ==
|
backgroundColor: context.priamryContainer,
|
||||||
Brightness.light
|
title: Text(s.playNext),
|
||||||
? context.primaryColor
|
trailingIcon: Icon(
|
||||||
: context.dialogBackgroundColor,
|
LineIcons.lightningBolt,
|
||||||
title: Text(s.playNext),
|
color: Colors.amber,
|
||||||
trailingIcon: Icon(
|
),
|
||||||
LineIcons.lightningBolt,
|
onPressed: () {
|
||||||
color: Colors.amber,
|
audio.moveToTop(episodes![index]);
|
||||||
),
|
Fluttertoast.showToast(
|
||||||
onPressed: () {
|
msg: s.playNextDes,
|
||||||
audio.moveToTop(episodes![index]);
|
gravity: ToastGravity.BOTTOM,
|
||||||
Fluttertoast.showToast(
|
);
|
||||||
msg: s.playNextDes,
|
},
|
||||||
gravity: ToastGravity.BOTTOM,
|
),
|
||||||
);
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
onPressed: action,
|
onPressed: action,
|
||||||
child: _episodeCard(context,
|
child: _episodeCard(
|
||||||
index: index,
|
context,
|
||||||
isLiked: isLiked,
|
index: index,
|
||||||
isDownloaded: isDownloaded,
|
isLiked: isLiked,
|
||||||
color: c,
|
isListened: isListened,
|
||||||
boo: boo),
|
isDownloaded: isDownloaded,
|
||||||
|
cardColor:
|
||||||
|
episodes![index].cardColor(context),
|
||||||
|
color: c,
|
||||||
|
boo: boo,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue