mirror of
https://github.com/stonega/tsacdop
synced 2025-02-17 20:10:37 +01:00
Change filenames.
Update README.
This commit is contained in:
parent
afd89ea80c
commit
c5d6261c11
57
README.md
57
README.md
@ -36,6 +36,18 @@ More to come...
|
||||
| ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||
| <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893838840.png" art = "HomePage"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585894051734.png" art = "Groups"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893877702.png" art = "Podcast"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585896237809.png" art = "Episode"/> | <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/preview/1585893920721.png" art = "DarkMode"/> |
|
||||
|
||||
## Localization
|
||||
|
||||
Support languages
|
||||
|
||||
* English
|
||||
* Chinese Simplified (beta)
|
||||
|
||||
|
||||
Please [email](tsacdop.app@gmail.com) me you'd like to contribute to support more languages!
|
||||
|
||||
Credit to [Localizely](https://localizely.com/) for kind support to open source project.
|
||||
|
||||
## License
|
||||
|
||||
Tsacdop is licensed under the [GPL V3.0](https://github.com/stonega/tsacdop/blob/master/LICENSE) license.
|
||||
@ -52,17 +64,48 @@ final environment = {"apiKey":"APIKEY"};
|
||||
You can get own api key on [ListenNotes](https://www.listennotes.com/api/), basic plan is free to all, and replace "APIKEY" with it.
|
||||
If no api key added, the search function in the app won't work. But you can still add podcasts by serach rss link or import ompl file.
|
||||
|
||||
## Localization
|
||||
## Archetecture
|
||||
|
||||
Support languages
|
||||
### Plugins
|
||||
|
||||
* English
|
||||
* Chinese Simplified (beta)
|
||||
* Local storage
|
||||
- sqflite
|
||||
- share_preference
|
||||
* Audio
|
||||
- just_audio
|
||||
- audio_service
|
||||
* State management
|
||||
- provider
|
||||
* Download
|
||||
- flutter_downloader
|
||||
|
||||
|
||||
Please [email](tsacdop.app@gmail.com) me you'd to contribute to support more languages!
|
||||
### Directory Structure
|
||||
|
||||
Credit to [Localizely](https://localizely.com/) for kind support to open source project.
|
||||
```
|
||||
UI
|
||||
src
|
||||
├──home
|
||||
├──home.dart [Homepage]
|
||||
├──addpodcast.dart [Search Page]
|
||||
├──playlist.dart [Playlist Page]
|
||||
├──podcasts
|
||||
├──podcast_manage.dart [Group Page]
|
||||
├──podcast_detail.dart [Podcast Page]
|
||||
├──episodes
|
||||
├──episode_detail.dart [Episode Page]
|
||||
├──settings
|
||||
├──setting.dart [Setting Page]
|
||||
|
||||
STATES
|
||||
src
|
||||
├──state
|
||||
├──audio_state.dart [Audio State]
|
||||
├──download_state.dart [Episode Download]
|
||||
├──podcast_group.dart [Podcast Groups]
|
||||
├──refresh_podcast.dart [Episode Refresh]
|
||||
├──setting_state.dart [Setting]
|
||||
├──subscribe_podcast.dart [Podcast Subscribe]
|
||||
```
|
||||
|
||||
## Known Issue
|
||||
|
||||
|
@ -1 +1 @@
|
||||
export '../state/settingstate.dart';
|
||||
export '../state/setting_state.dart';
|
||||
|
@ -12,12 +12,12 @@ import 'package:tuple/tuple.dart';
|
||||
import 'package:flutter_linkify/flutter_linkify.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/custompaint.dart';
|
||||
import 'episodedownload.dart';
|
||||
import 'episode_download.dart';
|
||||
|
||||
class EpisodeDetail extends StatefulWidget {
|
||||
final EpisodeBrief episodeItem;
|
||||
@ -101,6 +101,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = context.s;
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
|
||||
@ -118,7 +119,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
elevation: 1,
|
||||
tooltip: 'Menu',
|
||||
tooltip: s.menu,
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 0,
|
||||
@ -139,7 +140,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
||||
),
|
||||
Text(
|
||||
'Mark Listened',
|
||||
s.markListened,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -152,7 +153,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
await _markListened(widget.episodeItem);
|
||||
if (mounted) setState(() {});
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Mark as listened',
|
||||
msg: s.markListened,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
break;
|
||||
@ -189,10 +190,9 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||
height: 30.0,
|
||||
child: Text(
|
||||
'Published ' +
|
||||
DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
widget.episodeItem.pubDate)),
|
||||
s.published(DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
widget.episodeItem.pubDate))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).accentColor)),
|
||||
),
|
||||
@ -226,9 +226,9 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
horizontal: 10.0),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
(widget.episodeItem.duration ~/ 60)
|
||||
.toString() +
|
||||
'min',
|
||||
s.minsCount(
|
||||
widget.episodeItem.duration ~/
|
||||
60),
|
||||
style: textstyle),
|
||||
)
|
||||
: Center(),
|
||||
@ -326,8 +326,7 @@ class _EpisodeDetailState extends State<EpisodeDetail> {
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.all(5.0)),
|
||||
Text(
|
||||
'Still no shownote received\n for this episode.',
|
||||
Text(s.noShownote,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: context.textColor
|
||||
@ -444,7 +443,7 @@ class _MenuBarState extends State<MenuBar> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
|
||||
|
||||
final s = context.s;
|
||||
return Container(
|
||||
height: 50.0,
|
||||
decoration: BoxDecoration(
|
||||
@ -518,7 +517,7 @@ class _MenuBarState extends State<MenuBar> {
|
||||
color: context.accentColor), () {
|
||||
audio.delFromPlaylist(widget.episodeItem);
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Removed from playlist',
|
||||
msg: s.toastRemovePlaylist,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
})
|
||||
@ -526,7 +525,7 @@ class _MenuBarState extends State<MenuBar> {
|
||||
Icon(Icons.playlist_add, color: Colors.grey[700]),
|
||||
() {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Added to playlist',
|
||||
msg: s.toastAddPlaylist,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
audio.addToPlaylist(widget.episodeItem);
|
||||
@ -637,7 +636,7 @@ class _MenuBarState extends State<MenuBar> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Text('Play',
|
||||
Text(s.play,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).accentColor,
|
||||
fontSize: 15,
|
@ -9,8 +9,8 @@ import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:connectivity/connectivity.dart';
|
||||
|
||||
import '../state/download_state.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../util/general_dialog.dart';
|
||||
|
@ -27,47 +27,53 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static m3(count) => "${Intl.plural(count, zero: 'Never', one: '${count} day', other: '${count} days')}";
|
||||
|
||||
static m4(time) => "From ${time}";
|
||||
static m4(count) => "${Intl.plural(count, zero: '', one: 'Episode', other: 'Episodes')}";
|
||||
|
||||
static m5(count) => "${Intl.plural(count, zero: 'Group', one: 'Group', other: 'Groups')}";
|
||||
static m5(time) => "From ${time}";
|
||||
|
||||
static m6(host) => "Hosted on ${host}";
|
||||
static m6(count) => "${Intl.plural(count, zero: 'Group', one: 'Group', other: 'Groups')}";
|
||||
|
||||
static m7(count) => "${Intl.plural(count, zero: '', one: '${count} hour ago', other: '${count} hours ago')}";
|
||||
static m7(host) => "Hosted on ${host}";
|
||||
|
||||
static m8(count) => "${Intl.plural(count, zero: '', one: '${count} hour', other: '${count} hours')}";
|
||||
static m8(count) => "${Intl.plural(count, zero: 'In an hour', one: '${count} hour ago', other: '${count} hours ago')}";
|
||||
|
||||
static m9(count) => "${Intl.plural(count, zero: '', one: '${count} minute ago', other: '${count} minutes ago')}";
|
||||
static m9(count) => "${Intl.plural(count, zero: '', one: '${count} hour', other: '${count} hours')}";
|
||||
|
||||
static m10(count) => "${Intl.plural(count, zero: '', one: '${count} min', other: '${count} mins')}";
|
||||
static m10(count) => "${Intl.plural(count, zero: '', one: '${count} minute ago', other: '${count} minutes ago')}";
|
||||
|
||||
static m11(title) => "Fetch data ${title}";
|
||||
static m11(count) => "${Intl.plural(count, zero: '', one: '${count} min', other: '${count} mins')}";
|
||||
|
||||
static m12(title) => "Subscribe failed, network error ${title}";
|
||||
static m12(title) => "Fetch data ${title}";
|
||||
|
||||
static m13(title) => "Subscribe ${title}";
|
||||
static m13(title) => "Subscribe failed, network error ${title}";
|
||||
|
||||
static m14(title) => "Subscribe failed, podcast existed ${title}";
|
||||
static m14(title) => "Subscribe ${title}";
|
||||
|
||||
static m15(title) => "Subscribe success ${title}";
|
||||
static m15(title) => "Subscribe failed, podcast existed ${title}";
|
||||
|
||||
static m16(title) => "Update ${title}";
|
||||
static m16(title) => "Subscribe success ${title}";
|
||||
|
||||
static m17(title) => "Update error ${title}";
|
||||
static m17(title) => "Update ${title}";
|
||||
|
||||
static m18(date) => "Removed at ${date}";
|
||||
static m18(title) => "Update error ${title}";
|
||||
|
||||
static m19(count) => "${Intl.plural(count, zero: '', one: '${count} second ago', other: '${count} seconds ago')}";
|
||||
static m19(count) => "${Intl.plural(count, zero: '', one: 'Podcast', other: 'Podcasts')}";
|
||||
|
||||
static m20(time) => "Last time ${time}";
|
||||
static m20(date) => "Published at ${date}";
|
||||
|
||||
static m21(time) => "${time} Left";
|
||||
static m21(date) => "Removed at ${date}";
|
||||
|
||||
static m22(time) => "To ${time}";
|
||||
static m22(count) => "${Intl.plural(count, zero: '', one: '${count} second ago', other: '${count} seconds ago')}";
|
||||
|
||||
static m23(count) => "${Intl.plural(count, zero: 'No update', one: 'Updated ${count} episode', other: 'Updated ${count} episodes')}";
|
||||
static m23(time) => "Last time ${time}";
|
||||
|
||||
static m24(version) => "Version : ${version}";
|
||||
static m24(time) => "${time} Left";
|
||||
|
||||
static m25(time) => "To ${time}";
|
||||
|
||||
static m26(count) => "${Intl.plural(count, zero: 'No update', one: 'Updated ${count} episode', other: 'Updated ${count} episodes')}";
|
||||
|
||||
static m27(version) => "Version : ${version}";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
@ -98,7 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloaded" : MessageLookupByLibrary.simpleMessage("Downloaded"),
|
||||
"editGroupName" : MessageLookupByLibrary.simpleMessage("Edit group name"),
|
||||
"endOfEpisode" : MessageLookupByLibrary.simpleMessage("End of Episode"),
|
||||
"episode" : MessageLookupByLibrary.simpleMessage("Episode"),
|
||||
"episode" : m4,
|
||||
"featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("Tap to edit group"),
|
||||
"featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("You can change group name or delete group here, but home group can not be edited or deleted"),
|
||||
"featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("Episode view"),
|
||||
@ -122,12 +128,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"feedbackPlay" : MessageLookupByLibrary.simpleMessage("Rate on Play"),
|
||||
"feedbackTelegram" : MessageLookupByLibrary.simpleMessage("Join group"),
|
||||
"fonts" : MessageLookupByLibrary.simpleMessage("Fonts"),
|
||||
"from" : m4,
|
||||
"from" : m5,
|
||||
"goodNight" : MessageLookupByLibrary.simpleMessage("Good Night"),
|
||||
"groupExisted" : MessageLookupByLibrary.simpleMessage("Group existed"),
|
||||
"groupFilter" : MessageLookupByLibrary.simpleMessage("Group filter"),
|
||||
"groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("Are you sure you want to delete this group? Podcasts will be moved to Home group."),
|
||||
"groups" : m5,
|
||||
"groups" : m6,
|
||||
"homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("See All"),
|
||||
"homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Playlist"),
|
||||
"homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Sort by"),
|
||||
@ -137,9 +143,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("Import OMPL"),
|
||||
"homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("Refresh all"),
|
||||
"homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("Settings"),
|
||||
"hostedOn" : m6,
|
||||
"hoursAgo" : m7,
|
||||
"hoursCount" : m8,
|
||||
"hostedOn" : m7,
|
||||
"hoursAgo" : m8,
|
||||
"hoursCount" : m9,
|
||||
"introFourthPage" : MessageLookupByLibrary.simpleMessage("Long press on episode card for quick actions."),
|
||||
"introSecondPage" : MessageLookupByLibrary.simpleMessage("Subscribe podcast via search or import OMPL file."),
|
||||
"introThirdPage" : MessageLookupByLibrary.simpleMessage("You can create new group for podcasts, swipe on podcast list to change group."),
|
||||
@ -160,8 +166,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("Mark All Listened"),
|
||||
"menuViewRSS" : MessageLookupByLibrary.simpleMessage("Visit RSS Feed"),
|
||||
"menuVisitSite" : MessageLookupByLibrary.simpleMessage("Visit Site"),
|
||||
"minsAgo" : m9,
|
||||
"minsCount" : m10,
|
||||
"minsAgo" : m10,
|
||||
"minsCount" : m11,
|
||||
"network" : MessageLookupByLibrary.simpleMessage("Network"),
|
||||
"newGroup" : MessageLookupByLibrary.simpleMessage("Create new group"),
|
||||
"newestFirst" : MessageLookupByLibrary.simpleMessage("Newest first"),
|
||||
@ -170,18 +176,19 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noEpisodeFavorite" : MessageLookupByLibrary.simpleMessage("No episode collected yet"),
|
||||
"noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("No episode received yet"),
|
||||
"noPodcastGroup" : MessageLookupByLibrary.simpleMessage("No podcast in this group"),
|
||||
"notificaitonFatch" : m11,
|
||||
"notificationNetworkError" : m12,
|
||||
"notificationSubscribe" : m13,
|
||||
"notificationSubscribeExisted" : m14,
|
||||
"notificationSuccess" : m15,
|
||||
"notificationUpdate" : m16,
|
||||
"notificationUpdateError" : m17,
|
||||
"noShownote" : MessageLookupByLibrary.simpleMessage("Still no show notes received \\nfor this episode."),
|
||||
"notificaitonFatch" : m12,
|
||||
"notificationNetworkError" : m13,
|
||||
"notificationSubscribe" : m14,
|
||||
"notificationSubscribeExisted" : m15,
|
||||
"notificationSuccess" : m16,
|
||||
"notificationUpdate" : m17,
|
||||
"notificationUpdateError" : m18,
|
||||
"oldestFirst" : MessageLookupByLibrary.simpleMessage("Oldest first"),
|
||||
"play" : MessageLookupByLibrary.simpleMessage("Play"),
|
||||
"playing" : MessageLookupByLibrary.simpleMessage("Playing"),
|
||||
"plugins" : MessageLookupByLibrary.simpleMessage("Plugins"),
|
||||
"podcast" : MessageLookupByLibrary.simpleMessage("Podcast"),
|
||||
"podcast" : m19,
|
||||
"podcastSubscribed" : MessageLookupByLibrary.simpleMessage("Podcast subscribed"),
|
||||
"popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("Download episode"),
|
||||
"popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("Add episode to playlist"),
|
||||
@ -189,15 +196,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("Mark episode as listened"),
|
||||
"popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("Play the episode"),
|
||||
"privacyPolicy" : MessageLookupByLibrary.simpleMessage("Privacy Policy"),
|
||||
"published" : m20,
|
||||
"recoverSubscribe" : MessageLookupByLibrary.simpleMessage("Recover subscribe"),
|
||||
"remove" : MessageLookupByLibrary.simpleMessage("Remove"),
|
||||
"removeConfirm" : MessageLookupByLibrary.simpleMessage("Remove confirm"),
|
||||
"removePodcastDes" : MessageLookupByLibrary.simpleMessage("Are you sure you want to unsubscribe?"),
|
||||
"removedAt" : m18,
|
||||
"removedAt" : m21,
|
||||
"schedule" : MessageLookupByLibrary.simpleMessage("Schedule"),
|
||||
"searchInvalidRss" : MessageLookupByLibrary.simpleMessage("Invalid RSS link"),
|
||||
"searchPodcast" : MessageLookupByLibrary.simpleMessage("Search podcast"),
|
||||
"secondsAgo" : m19,
|
||||
"secondsAgo" : m22,
|
||||
"settingStorage" : MessageLookupByLibrary.simpleMessage("Storage"),
|
||||
"settingsAccentColor" : MessageLookupByLibrary.simpleMessage("Accent color"),
|
||||
"settingsAccentColorDes" : MessageLookupByLibrary.simpleMessage("Include the ovelay color"),
|
||||
@ -225,6 +233,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("Listen date"),
|
||||
"settingsInfo" : MessageLookupByLibrary.simpleMessage("Info"),
|
||||
"settingsInterface" : MessageLookupByLibrary.simpleMessage("Interface"),
|
||||
"settingsLanguages" : MessageLookupByLibrary.simpleMessage("Languages"),
|
||||
"settingsLanguagesDes" : MessageLookupByLibrary.simpleMessage("Change language"),
|
||||
"settingsLayout" : MessageLookupByLibrary.simpleMessage("Layout"),
|
||||
"settingsLayoutDes" : MessageLookupByLibrary.simpleMessage("App layout"),
|
||||
"settingsLibraries" : MessageLookupByLibrary.simpleMessage("Libraries"),
|
||||
@ -258,9 +268,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"sleepTimer" : MessageLookupByLibrary.simpleMessage("Sleep timer"),
|
||||
"subscribe" : MessageLookupByLibrary.simpleMessage("Subscribe"),
|
||||
"systemDefault" : MessageLookupByLibrary.simpleMessage("System default"),
|
||||
"timeLastPlayed" : m20,
|
||||
"timeLeft" : m21,
|
||||
"to" : m22,
|
||||
"timeLastPlayed" : m23,
|
||||
"timeLeft" : m24,
|
||||
"to" : m25,
|
||||
"toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("Added to playlist"),
|
||||
"toastDiscovery" : MessageLookupByLibrary.simpleMessage("Discovery feature reopened, pleast restart the app"),
|
||||
"toastFileError" : MessageLookupByLibrary.simpleMessage("File error, subscribe failed"),
|
||||
@ -279,8 +289,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"unlike" : MessageLookupByLibrary.simpleMessage("Unlike"),
|
||||
"unliked" : MessageLookupByLibrary.simpleMessage("Episode removed from favorite"),
|
||||
"updateDate" : MessageLookupByLibrary.simpleMessage("Update date"),
|
||||
"updateEpisodesCount" : m23,
|
||||
"updateEpisodesCount" : m26,
|
||||
"updateFailed" : MessageLookupByLibrary.simpleMessage("Update failed, network error"),
|
||||
"version" : m24
|
||||
"version" : m27
|
||||
};
|
||||
}
|
||||
|
@ -27,47 +27,53 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static m3(count) => "${Intl.plural(count, zero: '从不', other: '${count}天')}";
|
||||
|
||||
static m4(time) => "自${time}";
|
||||
static m4(count) => "${Intl.plural(count, zero: '', other: '节目')}";
|
||||
|
||||
static m5(count) => "${Intl.plural(count, zero: '分组', other: '分组')}";
|
||||
static m5(time) => "自${time}";
|
||||
|
||||
static m6(host) => "平台 ${host}";
|
||||
static m6(count) => "${Intl.plural(count, zero: '分组', other: '分组')}";
|
||||
|
||||
static m7(count) => "${Intl.plural(count, zero: '', other: '${count}小时前')}";
|
||||
static m7(host) => "平台 ${host}";
|
||||
|
||||
static m8(count) => "${Intl.plural(count, zero: '', other: '${count} 小时')}";
|
||||
static m8(count) => "${Intl.plural(count, zero: '刚刚', other: '${count}小时前')}";
|
||||
|
||||
static m9(count) => "${Intl.plural(count, zero: '', other: '${count}分钟前')}";
|
||||
static m9(count) => "${Intl.plural(count, zero: '', other: '${count} 小时')}";
|
||||
|
||||
static m10(count) => "${Intl.plural(count, zero: '', other: '${count}分钟')}";
|
||||
static m10(count) => "${Intl.plural(count, zero: '', other: '${count}分钟前')}";
|
||||
|
||||
static m11(title) => "获取数据 ${title}";
|
||||
static m11(count) => "${Intl.plural(count, zero: '', other: '${count}分钟')}";
|
||||
|
||||
static m12(title) => "订阅失败,网络错误 ${title}";
|
||||
static m12(title) => "获取数据 ${title}";
|
||||
|
||||
static m13(title) => "订阅${title}";
|
||||
static m13(title) => "订阅失败,网络错误 ${title}";
|
||||
|
||||
static m14(title) => "订阅失败,播客已存在 ${title}";
|
||||
static m14(title) => "订阅${title}";
|
||||
|
||||
static m15(title) => "订阅成功 ${title}";
|
||||
static m15(title) => "订阅失败,播客已存在 ${title}";
|
||||
|
||||
static m16(title) => "更新 ${title}";
|
||||
static m16(title) => "订阅成功 ${title}";
|
||||
|
||||
static m17(title) => "更新失败 ${title}";
|
||||
static m17(title) => "更新 ${title}";
|
||||
|
||||
static m18(date) => "${date}移除";
|
||||
static m18(title) => "更新失败 ${title}";
|
||||
|
||||
static m19(count) => "${Intl.plural(count, zero: '', other: '${count}秒前')}";
|
||||
static m19(count) => "${Intl.plural(count, zero: '', other: '播客')}";
|
||||
|
||||
static m20(time) => "上次播放${time}";
|
||||
static m20(date) => "${date}上线";
|
||||
|
||||
static m21(time) => "剩余 ${time}";
|
||||
static m21(date) => "${date}移除";
|
||||
|
||||
static m22(time) => "到${time}";
|
||||
static m22(count) => "${Intl.plural(count, zero: '', other: '${count}秒前')}";
|
||||
|
||||
static m23(count) => "${Intl.plural(count, zero: '未有更新', other: '更新 ${count} 集节目')}";
|
||||
static m23(time) => "上次播放${time}";
|
||||
|
||||
static m24(version) => "版本:${version}";
|
||||
static m24(time) => "剩余 ${time}";
|
||||
|
||||
static m25(time) => "到${time}";
|
||||
|
||||
static m26(count) => "${Intl.plural(count, zero: '未有更新', other: '更新 ${count} 集节目')}";
|
||||
|
||||
static m27(version) => "版本:${version}";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
@ -98,7 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"downloaded" : MessageLookupByLibrary.simpleMessage("已下载"),
|
||||
"editGroupName" : MessageLookupByLibrary.simpleMessage("修改组名"),
|
||||
"endOfEpisode" : MessageLookupByLibrary.simpleMessage("节目结束"),
|
||||
"episode" : MessageLookupByLibrary.simpleMessage("节目"),
|
||||
"episode" : m4,
|
||||
"featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("点击修改分组"),
|
||||
"featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("您可以修改分组名或者删除分组,注意 Home 分组无法修改,也不能被删除。"),
|
||||
"featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("节目界面"),
|
||||
@ -122,12 +128,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"feedbackPlay" : MessageLookupByLibrary.simpleMessage("Play评价"),
|
||||
"feedbackTelegram" : MessageLookupByLibrary.simpleMessage("加入小组"),
|
||||
"fonts" : MessageLookupByLibrary.simpleMessage("字体"),
|
||||
"from" : m4,
|
||||
"from" : m5,
|
||||
"goodNight" : MessageLookupByLibrary.simpleMessage("晚安"),
|
||||
"groupExisted" : MessageLookupByLibrary.simpleMessage("组名已使用"),
|
||||
"groupFilter" : MessageLookupByLibrary.simpleMessage("分组"),
|
||||
"groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("您确认要移除该分组吗?播客将被移动到 Home 分组。"),
|
||||
"groups" : m5,
|
||||
"groups" : m6,
|
||||
"homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("查看全部"),
|
||||
"homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("播放列表"),
|
||||
"homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("排序"),
|
||||
@ -137,9 +143,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("导入OMPL"),
|
||||
"homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("全部刷新"),
|
||||
"homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("设置"),
|
||||
"hostedOn" : m6,
|
||||
"hoursAgo" : m7,
|
||||
"hoursCount" : m8,
|
||||
"hostedOn" : m7,
|
||||
"hoursAgo" : m8,
|
||||
"hoursCount" : m9,
|
||||
"introFourthPage" : MessageLookupByLibrary.simpleMessage("长按节目打开快捷菜单。"),
|
||||
"introSecondPage" : MessageLookupByLibrary.simpleMessage("您可以通过搜索订阅播客,也可以直接导入OMPL文件。"),
|
||||
"introThirdPage" : MessageLookupByLibrary.simpleMessage("您可以创建分组,上下滑动切换分组。"),
|
||||
@ -160,8 +166,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("标记所有已收听"),
|
||||
"menuViewRSS" : MessageLookupByLibrary.simpleMessage("查看 RSS"),
|
||||
"menuVisitSite" : MessageLookupByLibrary.simpleMessage("访问网站"),
|
||||
"minsAgo" : m9,
|
||||
"minsCount" : m10,
|
||||
"minsAgo" : m10,
|
||||
"minsCount" : m11,
|
||||
"network" : MessageLookupByLibrary.simpleMessage("网络"),
|
||||
"newGroup" : MessageLookupByLibrary.simpleMessage("创建分组"),
|
||||
"newestFirst" : MessageLookupByLibrary.simpleMessage("由新到旧"),
|
||||
@ -170,18 +176,19 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noEpisodeFavorite" : MessageLookupByLibrary.simpleMessage("暂无收藏节目"),
|
||||
"noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("暂无节目"),
|
||||
"noPodcastGroup" : MessageLookupByLibrary.simpleMessage("分组无播客"),
|
||||
"notificaitonFatch" : m11,
|
||||
"notificationNetworkError" : m12,
|
||||
"notificationSubscribe" : m13,
|
||||
"notificationSubscribeExisted" : m14,
|
||||
"notificationSuccess" : m15,
|
||||
"notificationUpdate" : m16,
|
||||
"notificationUpdateError" : m17,
|
||||
"noShownote" : MessageLookupByLibrary.simpleMessage("节目简介暂未收到。"),
|
||||
"notificaitonFatch" : m12,
|
||||
"notificationNetworkError" : m13,
|
||||
"notificationSubscribe" : m14,
|
||||
"notificationSubscribeExisted" : m15,
|
||||
"notificationSuccess" : m16,
|
||||
"notificationUpdate" : m17,
|
||||
"notificationUpdateError" : m18,
|
||||
"oldestFirst" : MessageLookupByLibrary.simpleMessage("由旧到新"),
|
||||
"play" : MessageLookupByLibrary.simpleMessage("播放"),
|
||||
"playing" : MessageLookupByLibrary.simpleMessage("正在播放"),
|
||||
"plugins" : MessageLookupByLibrary.simpleMessage("插件"),
|
||||
"podcast" : MessageLookupByLibrary.simpleMessage("播客"),
|
||||
"podcast" : m19,
|
||||
"podcastSubscribed" : MessageLookupByLibrary.simpleMessage("播客已订阅"),
|
||||
"popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("下载节目"),
|
||||
"popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("添加到播放列表"),
|
||||
@ -189,15 +196,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("设置为已收听"),
|
||||
"popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("播放节目"),
|
||||
"privacyPolicy" : MessageLookupByLibrary.simpleMessage("隐私条款"),
|
||||
"published" : m20,
|
||||
"recoverSubscribe" : MessageLookupByLibrary.simpleMessage("恢复订阅"),
|
||||
"remove" : MessageLookupByLibrary.simpleMessage("移除"),
|
||||
"removeConfirm" : MessageLookupByLibrary.simpleMessage("取消订阅"),
|
||||
"removePodcastDes" : MessageLookupByLibrary.simpleMessage("您确认要取消订阅吗?"),
|
||||
"removedAt" : m18,
|
||||
"removedAt" : m21,
|
||||
"schedule" : MessageLookupByLibrary.simpleMessage("定时"),
|
||||
"searchInvalidRss" : MessageLookupByLibrary.simpleMessage("RSS 链接错误"),
|
||||
"searchPodcast" : MessageLookupByLibrary.simpleMessage("搜索播客"),
|
||||
"secondsAgo" : m19,
|
||||
"secondsAgo" : m22,
|
||||
"settingStorage" : MessageLookupByLibrary.simpleMessage("储存空间"),
|
||||
"settingsAccentColor" : MessageLookupByLibrary.simpleMessage("次要颜色"),
|
||||
"settingsAccentColorDes" : MessageLookupByLibrary.simpleMessage("包括溢出颜色"),
|
||||
@ -225,6 +233,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("播放日期"),
|
||||
"settingsInfo" : MessageLookupByLibrary.simpleMessage("信息"),
|
||||
"settingsInterface" : MessageLookupByLibrary.simpleMessage("界面"),
|
||||
"settingsLanguages" : MessageLookupByLibrary.simpleMessage("语言"),
|
||||
"settingsLanguagesDes" : MessageLookupByLibrary.simpleMessage("设置语言"),
|
||||
"settingsLayout" : MessageLookupByLibrary.simpleMessage("布局"),
|
||||
"settingsLayoutDes" : MessageLookupByLibrary.simpleMessage("应用布局"),
|
||||
"settingsLibraries" : MessageLookupByLibrary.simpleMessage("开源"),
|
||||
@ -258,9 +268,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"sleepTimer" : MessageLookupByLibrary.simpleMessage("睡眠模式"),
|
||||
"subscribe" : MessageLookupByLibrary.simpleMessage("订阅"),
|
||||
"systemDefault" : MessageLookupByLibrary.simpleMessage("系统默认"),
|
||||
"timeLastPlayed" : m20,
|
||||
"timeLeft" : m21,
|
||||
"to" : m22,
|
||||
"timeLastPlayed" : m23,
|
||||
"timeLeft" : m24,
|
||||
"to" : m25,
|
||||
"toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("添加到播放列表"),
|
||||
"toastDiscovery" : MessageLookupByLibrary.simpleMessage("重启应用后可查看"),
|
||||
"toastFileError" : MessageLookupByLibrary.simpleMessage("文件错误,导入失败"),
|
||||
@ -279,8 +289,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"unlike" : MessageLookupByLibrary.simpleMessage("取消喜欢"),
|
||||
"unliked" : MessageLookupByLibrary.simpleMessage("从收藏移除"),
|
||||
"updateDate" : MessageLookupByLibrary.simpleMessage("更新日期"),
|
||||
"updateEpisodesCount" : m23,
|
||||
"updateEpisodesCount" : m26,
|
||||
"updateFailed" : MessageLookupByLibrary.simpleMessage("更新失败"),
|
||||
"version" : m24
|
||||
"version" : m27
|
||||
};
|
||||
}
|
||||
|
@ -315,13 +315,16 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Episode`
|
||||
String get episode {
|
||||
return Intl.message(
|
||||
'Episode',
|
||||
/// `{count, plural, zero{} one{Episode} other{Episodes}}`
|
||||
String episode(num count) {
|
||||
return Intl.plural(
|
||||
count,
|
||||
zero: '',
|
||||
one: 'Episode',
|
||||
other: 'Episodes',
|
||||
name: 'episode',
|
||||
desc: '',
|
||||
args: [],
|
||||
args: [count],
|
||||
);
|
||||
}
|
||||
|
||||
@ -718,11 +721,11 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `{count, plural, zero{} one{{count} hour ago} other{{count} hours ago}}`
|
||||
/// `{count, plural, zero{In an hour} one{{count} hour ago} other{{count} hours ago}}`
|
||||
String hoursAgo(num count) {
|
||||
return Intl.plural(
|
||||
count,
|
||||
zero: '',
|
||||
zero: 'In an hour',
|
||||
one: '$count hour ago',
|
||||
other: '$count hours ago',
|
||||
name: 'hoursAgo',
|
||||
@ -1050,6 +1053,16 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Still no show notes received \nfor this episode.`
|
||||
String get noShownote {
|
||||
return Intl.message(
|
||||
'Still no show notes received \nfor this episode.',
|
||||
name: 'noShownote',
|
||||
desc: 'Means this episode have no show notes.',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Fetch data {title}`
|
||||
String notificaitonFatch(Object title) {
|
||||
return Intl.message(
|
||||
@ -1160,13 +1173,16 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Podcast`
|
||||
String get podcast {
|
||||
return Intl.message(
|
||||
'Podcast',
|
||||
/// `{count, plural, zero{} one{Podcast} other{Podcasts}}`
|
||||
String podcast(num count) {
|
||||
return Intl.plural(
|
||||
count,
|
||||
zero: '',
|
||||
one: 'Podcast',
|
||||
other: 'Podcasts',
|
||||
name: 'podcast',
|
||||
desc: '',
|
||||
args: [],
|
||||
args: [count],
|
||||
);
|
||||
}
|
||||
|
||||
@ -1240,6 +1256,16 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Published at {date}`
|
||||
String published(Object date) {
|
||||
return Intl.message(
|
||||
'Published at $date',
|
||||
name: 'published',
|
||||
desc: '',
|
||||
args: [date],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Recover subscribe`
|
||||
String get recoverSubscribe {
|
||||
return Intl.message(
|
||||
@ -1593,6 +1619,26 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Languages`
|
||||
String get settingsLanguages {
|
||||
return Intl.message(
|
||||
'Languages',
|
||||
name: 'settingsLanguages',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Change language`
|
||||
String get settingsLanguagesDes {
|
||||
return Intl.message(
|
||||
'Change language',
|
||||
name: 'settingsLanguagesDes',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Layout`
|
||||
String get settingsLayout {
|
||||
return Intl.message(
|
||||
|
@ -9,7 +9,7 @@ import 'package:audio_service/audio_service.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
|
||||
import '../type/episodebrief.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
import '../util/pageroute.dart';
|
||||
@ -17,7 +17,7 @@ import '../util/colorize.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/custompaint.dart';
|
||||
import '../util/customslider.dart';
|
||||
import '../episodes/episodedetail.dart';
|
||||
import '../episodes/episode_detail.dart';
|
||||
import 'playlist.dart';
|
||||
import 'audiopanel.dart';
|
||||
|
||||
|
@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../state/download_state.dart';
|
||||
import '../episodes/episodedetail.dart';
|
||||
import '../episodes/episode_detail.dart';
|
||||
import '../util/pageroute.dart';
|
||||
|
||||
class DownloadList extends StatefulWidget {
|
||||
|
@ -10,7 +10,7 @@ import 'package:line_icons/line_icons.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:feature_discovery/feature_discovery.dart';
|
||||
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
|
@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:focused_menu/focused_menu.dart';
|
||||
import 'package:focused_menu/modals.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
@ -15,16 +16,16 @@ import '../state/podcast_group.dart';
|
||||
import '../state/subscribe_podcast.dart';
|
||||
import '../state/download_state.dart';
|
||||
import '../type/podcastlocal.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../util/custompaint.dart';
|
||||
import '../util/pageroute.dart';
|
||||
import '../util/colorize.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
import '../episodes/episodedetail.dart';
|
||||
import '../podcasts/podcastdetail.dart';
|
||||
import '../podcasts/podcastmanage.dart';
|
||||
import '../episodes/episode_detail.dart';
|
||||
import '../podcasts/podcast_detail.dart';
|
||||
import '../podcasts/podcast_manage.dart';
|
||||
|
||||
class ScrollPodcasts extends StatefulWidget {
|
||||
@override
|
||||
@ -478,6 +479,20 @@ class ShowEpisode extends StatelessWidget {
|
||||
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
String _dateToString(BuildContext context, {int pubDate}) {
|
||||
final s = context.s;
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true);
|
||||
var difference = DateTime.now().toUtc().difference(date);
|
||||
if (difference.inHours < 24) {
|
||||
return s.hoursAgo(difference.inHours);
|
||||
} else if (difference.inDays < 7) {
|
||||
return s.daysAgo(difference.inDays);
|
||||
} else {
|
||||
return DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true).toLocal());
|
||||
}
|
||||
}
|
||||
|
||||
Future<Tuple4<int, bool, bool, List<int>>> _initData(
|
||||
EpisodeBrief episode) async {
|
||||
int listened = await _isListened(episode);
|
||||
@ -993,8 +1008,9 @@ class ShowEpisode extends StatelessWidget {
|
||||
Container(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
episodes[index].dateToString(),
|
||||
//podcast[index].pubDate.substring(4, 16),
|
||||
_dateToString(context,
|
||||
pubDate: episodes[index]
|
||||
.pubDate),
|
||||
style: TextStyle(
|
||||
fontSize: _width / 35,
|
||||
color: _c,
|
||||
|
@ -8,7 +8,7 @@ import 'package:tuple/tuple.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/custompaint.dart';
|
||||
|
@ -9,7 +9,7 @@ import 'package:tsacdop/home/preview.dart';
|
||||
import 'package:wc_flutter_share/wc_flutter_share.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/customslider.dart';
|
||||
import '../util/pageroute.dart';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../home/home.dart';
|
||||
import '../util/pageroute.dart';
|
||||
import '../util/context_extension.dart';
|
||||
|
@ -64,7 +64,7 @@
|
||||
"@editGroupName": {},
|
||||
"endOfEpisode": "End of Episode",
|
||||
"@endOfEpisode": {},
|
||||
"episode": "Episode",
|
||||
"episode": "{count, plural, zero{} one{Episode} other{Episodes}}",
|
||||
"@episode": {},
|
||||
"featureDiscoveryEditGroup": "Tap to edit group",
|
||||
"@featureDiscoveryEditGroup": {},
|
||||
@ -152,7 +152,7 @@
|
||||
"host": {}
|
||||
}
|
||||
},
|
||||
"hoursAgo": "{count, plural, zero{} one{{count} hour ago} other{{count} hours ago}}",
|
||||
"hoursAgo": "{count, plural, zero{In an hour} one{{count} hour ago} other{{count} hours ago}}",
|
||||
"@hoursAgo": {},
|
||||
"hoursCount": "{count, plural, zero{} one{{count} hour} other{{count} hours}}",
|
||||
"@hoursCount": {},
|
||||
@ -218,6 +218,10 @@
|
||||
"@noEpisodeRecent": {},
|
||||
"noPodcastGroup": "No podcast in this group",
|
||||
"@noPodcastGroup": {},
|
||||
"noShownote": "Still no show notes received \\nfor this episode.",
|
||||
"@noShownote": {
|
||||
"description": "Means this episode have no show notes."
|
||||
},
|
||||
"notificaitonFatch": "Fetch data {title}",
|
||||
"@notificaitonFatch": {},
|
||||
"notificationNetworkError": "Subscribe failed, network error {title}",
|
||||
@ -264,7 +268,7 @@
|
||||
"@playing": {},
|
||||
"plugins": "Plugins",
|
||||
"@plugins": {},
|
||||
"podcast": "Podcast",
|
||||
"podcast": "{count, plural, zero{} one{Podcast} other{Podcasts}}",
|
||||
"@podcast": {},
|
||||
"podcastSubscribed": "Podcast subscribed",
|
||||
"@podcastSubscribed": {},
|
||||
@ -280,6 +284,12 @@
|
||||
"@popupMenuPlayDes": {},
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"@privacyPolicy": {},
|
||||
"published": "Published at {date}",
|
||||
"@published": {
|
||||
"placeholders": {
|
||||
"date": {}
|
||||
}
|
||||
},
|
||||
"recoverSubscribe": "Recover subscribe",
|
||||
"@recoverSubscribe": {},
|
||||
"remove": "Remove",
|
||||
@ -357,6 +367,10 @@
|
||||
"@settingsInfo": {},
|
||||
"settingsInterface": "Interface",
|
||||
"@settingsInterface": {},
|
||||
"settingsLanguages": "Languages",
|
||||
"@settingsLanguages": {},
|
||||
"settingsLanguagesDes": "Change language",
|
||||
"@settingsLanguagesDes": {},
|
||||
"settingsLayout": "Layout",
|
||||
"@settingsLayout": {},
|
||||
"settingsLayoutDes": "App layout",
|
||||
|
@ -64,7 +64,7 @@
|
||||
"@editGroupName": {},
|
||||
"endOfEpisode": "节目结束",
|
||||
"@endOfEpisode": {},
|
||||
"episode": "节目",
|
||||
"episode": "{count, plural, zero{} other{节目}}",
|
||||
"@episode": {},
|
||||
"featureDiscoveryEditGroup": "点击修改分组",
|
||||
"@featureDiscoveryEditGroup": {},
|
||||
@ -152,7 +152,7 @@
|
||||
"host": {}
|
||||
}
|
||||
},
|
||||
"hoursAgo": "{count, plural, zero{} other{{count}小时前}}",
|
||||
"hoursAgo": "{count, plural, zero{刚刚} other{{count}小时前}}",
|
||||
"@hoursAgo": {},
|
||||
"hoursCount": "{count, plural, zero{} other{{count} 小时}}",
|
||||
"@hoursCount": {},
|
||||
@ -218,6 +218,10 @@
|
||||
"@noEpisodeRecent": {},
|
||||
"noPodcastGroup": "分组无播客",
|
||||
"@noPodcastGroup": {},
|
||||
"noShownote": "节目简介暂未收到。",
|
||||
"@noShownote": {
|
||||
"description": "Means this episode have no show notes."
|
||||
},
|
||||
"notificaitonFatch": "获取数据 {title}",
|
||||
"@notificaitonFatch": {},
|
||||
"notificationNetworkError": "订阅失败,网络错误 {title}",
|
||||
@ -264,7 +268,7 @@
|
||||
"@playing": {},
|
||||
"plugins": "插件",
|
||||
"@plugins": {},
|
||||
"podcast": "播客",
|
||||
"podcast": "{count, plural, zero{} other{播客}}",
|
||||
"@podcast": {},
|
||||
"podcastSubscribed": "播客已订阅",
|
||||
"@podcastSubscribed": {},
|
||||
@ -280,6 +284,12 @@
|
||||
"@popupMenuPlayDes": {},
|
||||
"privacyPolicy": "隐私条款",
|
||||
"@privacyPolicy": {},
|
||||
"published": "{date}上线",
|
||||
"@published": {
|
||||
"placeholders": {
|
||||
"date": {}
|
||||
}
|
||||
},
|
||||
"recoverSubscribe": "恢复订阅",
|
||||
"@recoverSubscribe": {},
|
||||
"remove": "移除",
|
||||
@ -357,6 +367,10 @@
|
||||
"@settingsInfo": {},
|
||||
"settingsInterface": "界面",
|
||||
"@settingsInterface": {},
|
||||
"settingsLanguages": "语言",
|
||||
"@settingsLanguages": {},
|
||||
"settingsLanguagesDes": "设置语言",
|
||||
"@settingsLanguagesDes": {},
|
||||
"settingsLayout": "布局",
|
||||
"@settingsLayout": {},
|
||||
"settingsLayoutDes": "应用布局",
|
||||
|
@ -5,7 +5,7 @@ import 'package:intl/intl.dart';
|
||||
import 'package:flutter_downloader/flutter_downloader.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import '../type/podcastlocal.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../webfeed/webfeed.dart';
|
||||
import '../type/sub_history.dart';
|
||||
|
@ -8,8 +8,8 @@ import 'package:feature_discovery/feature_discovery.dart';
|
||||
|
||||
import 'generated/l10n.dart';
|
||||
import 'state/podcast_group.dart';
|
||||
import 'state/audiostate.dart';
|
||||
import 'state/settingstate.dart';
|
||||
import 'state/audio_state.dart';
|
||||
import 'state/setting_state.dart';
|
||||
import 'state/download_state.dart';
|
||||
import 'state/refresh_podcast.dart';
|
||||
import 'state/subscribe_podcast.dart';
|
||||
|
@ -25,7 +25,7 @@ import '../util/colorize.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/custompaint.dart';
|
||||
import '../util/general_dialog.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
|
||||
class PodcastDetail extends StatefulWidget {
|
||||
PodcastDetail({Key key, @required this.podcastLocal, this.hide = false})
|
@ -9,8 +9,8 @@ import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:feature_discovery/feature_discovery.dart';
|
||||
|
||||
import '../state/podcast_group.dart';
|
||||
import '../podcasts/podcastgroup.dart';
|
||||
import '../podcasts/podcastlist.dart';
|
||||
import 'podcastgroup.dart';
|
||||
import 'podcastlist.dart';
|
||||
import '../util/pageroute.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/general_dialog.dart';
|
||||
@ -292,7 +292,7 @@ class _PodcastManageState extends State<PodcastManage>
|
||||
pageBuilder: (context, index) =>
|
||||
DescribedFeatureOverlay(
|
||||
featureId: configurePodcast,
|
||||
tapTarget: Text(s.podcast),
|
||||
tapTarget: Text(s.podcast(1)),
|
||||
title: Text(s.featureDiscoveryGroupPodcast),
|
||||
overflowMode: OverflowMode.clipContent,
|
||||
onDismiss: () => Future.value(true),
|
@ -11,7 +11,7 @@ import 'package:provider/provider.dart';
|
||||
import '../state/podcast_group.dart';
|
||||
import '../type/podcastlocal.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../podcasts/podcastdetail.dart';
|
||||
import 'podcast_detail.dart';
|
||||
import '../util/pageroute.dart';
|
||||
import '../util/context_extension.dart';
|
||||
|
||||
@ -46,6 +46,7 @@ class _AboutPodcastState extends State<AboutPodcast> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var _groupList = Provider.of<GroupList>(context, listen: false);
|
||||
final s = context.s;
|
||||
return AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10.0))),
|
||||
@ -60,7 +61,7 @@ class _AboutPodcastState extends State<AboutPodcast> {
|
||||
},
|
||||
textColor: Colors.red,
|
||||
child: Text(
|
||||
'UNSUBSCRIBE',
|
||||
s.remove,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -109,7 +110,7 @@ class _PodcastListState extends State<PodcastList> {
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Podcasts'),
|
||||
title: Text(context.s.podcast(2)),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeArea(
|
||||
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@ -73,6 +74,21 @@ class _DownloadsManageState extends State<DownloadsManage> {
|
||||
_getStorageSize();
|
||||
}
|
||||
|
||||
String _downloadDateToString(BuildContext context,
|
||||
{int downloadDate, int pubDate}) {
|
||||
final s = context.s;
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(downloadDate);
|
||||
var diffrence = DateTime.now().toUtc().difference(date);
|
||||
if (diffrence.inHours < 24) {
|
||||
return s.hoursAgo(diffrence.inHours);
|
||||
} else if (diffrence.inDays < 7) {
|
||||
return s.daysAgo(diffrence.inDays);
|
||||
} else {
|
||||
return DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true).toLocal());
|
||||
}
|
||||
}
|
||||
|
||||
int sumSelected() {
|
||||
int sum = 0;
|
||||
if (_selectedList.length == 0) {
|
||||
@ -313,8 +329,14 @@ class _DownloadsManageState extends State<DownloadsManage> {
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Text(_episodes[index]
|
||||
.downloadDateToString()),
|
||||
Text(_downloadDateToString(
|
||||
context,
|
||||
downloadDate:
|
||||
_episodes[index]
|
||||
.downloadDate,
|
||||
pubDate:
|
||||
_episodes[index]
|
||||
.pubDate)),
|
||||
SizedBox(width: 20),
|
||||
_episodes[index]
|
||||
.enclosureLength !=
|
||||
|
@ -11,7 +11,7 @@ import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../webfeed/webfeed.dart';
|
||||
import '../type/searchpodcast.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../state/subscribe_podcast.dart';
|
||||
import '../type/sub_history.dart';
|
||||
|
||||
|
105
lib/settings/languages.dart
Normal file
105
lib/settings/languages.dart
Normal file
@ -0,0 +1,105 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../util/context_extension.dart';
|
||||
import '../generated/l10n.dart';
|
||||
|
||||
class LanguagesSetting extends StatefulWidget {
|
||||
const LanguagesSetting({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LanguagesSettingState createState() => _LanguagesSettingState();
|
||||
}
|
||||
|
||||
class _LanguagesSettingState extends State<LanguagesSetting> {
|
||||
_launchUrl(String url) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = context.s;
|
||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
|
||||
systemNavigationBarColor: Theme.of(context).primaryColor,
|
||||
systemNavigationBarIconBrightness:
|
||||
Theme.of(context).accentColorBrightness,
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.settingsLanguages),
|
||||
elevation: 0,
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(s.systemDefault),
|
||||
onTap: () async {
|
||||
await S.load(Locale(Intl.systemLocale));
|
||||
setState(() {});
|
||||
},
|
||||
trailing: Radio<Locale>(
|
||||
value: Locale(Intl.systemLocale),
|
||||
groupValue: Locale(Intl.getCurrentLocale()),
|
||||
onChanged: (Locale locale) async {
|
||||
await S.load(locale);
|
||||
setState(() {});
|
||||
}),
|
||||
),
|
||||
Divider(height: 2),
|
||||
ListTile(
|
||||
title: Text('English'),
|
||||
onTap: () async {
|
||||
await S.load(Locale('en'));
|
||||
setState(() {});
|
||||
},
|
||||
trailing: Radio<Locale>(
|
||||
value: Locale('en'),
|
||||
groupValue: Locale(Intl.getCurrentLocale()),
|
||||
onChanged: (Locale locale) async {
|
||||
await S.load(locale);
|
||||
setState(() {});
|
||||
}),
|
||||
),
|
||||
Divider(height: 2),
|
||||
ListTile(
|
||||
title: Text('简体中文'),
|
||||
onTap: () async {
|
||||
await S.load(Locale('zh_Hans'));
|
||||
setState(() {});
|
||||
},
|
||||
trailing: Radio<Locale>(
|
||||
value: Locale('zh_Hans'),
|
||||
groupValue: Locale(Intl.getCurrentLocale()),
|
||||
onChanged: (Locale locale) async {
|
||||
await S.load(locale);
|
||||
setState(() {});
|
||||
}),
|
||||
),
|
||||
Divider(height: 2),
|
||||
ListTile(
|
||||
onTap: () => _launchUrl(
|
||||
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project'),
|
||||
subtitle: Text(
|
||||
"If you'd like to contribute to support more languages, please contact me."),
|
||||
trailing: IconButton(
|
||||
icon: Icon(LineIcons.envelope_open_solid),
|
||||
onPressed: () => _launchUrl(
|
||||
'mailto:<tsacdop.app@gmail.com>?subject=Tsacdop localization project')),
|
||||
),
|
||||
],
|
||||
))),
|
||||
);
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:flutter_time_picker_spinner/flutter_time_picker_spinner.dart';
|
||||
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../home/audioplayer.dart';
|
||||
import '../util/general_dialog.dart';
|
||||
import '../util/context_extension.dart';
|
||||
|
@ -17,13 +17,14 @@ import '../intro_slider/app_intro.dart';
|
||||
import '../type/podcastlocal.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../home/home.dart';
|
||||
import '../podcasts/podcastmanage.dart';
|
||||
import '../podcasts/podcast_manage.dart';
|
||||
import 'theme.dart';
|
||||
import 'layouts.dart';
|
||||
import 'storage.dart';
|
||||
import 'history.dart';
|
||||
import 'syncing.dart';
|
||||
import 'libries.dart';
|
||||
import 'languages.dart';
|
||||
import 'play_setting.dart';
|
||||
|
||||
class Settings extends StatefulWidget {
|
||||
@ -217,6 +218,18 @@ class _SettingsState extends State<Settings>
|
||||
subtitle: Text(s.settingsHistoryDes),
|
||||
),
|
||||
Divider(height: 2),
|
||||
ListTile(
|
||||
onTap: () => Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => LanguagesSetting())),
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(horizontal: 25.0),
|
||||
leading: Icon(LineIcons.language_solid),
|
||||
title: Text(s.settingsLanguages),
|
||||
subtitle: Text(s.settingsLanguagesDes),
|
||||
),
|
||||
Divider(height: 2),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
_exportOmpl();
|
||||
|
@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
import '../settings/downloads_manage.dart';
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
import '../util/context_extension.dart';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../util/context_extension.dart';
|
||||
|
||||
class SyncingSetting extends StatelessWidget {
|
||||
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../state/settingstate.dart';
|
||||
import '../state/setting_state.dart';
|
||||
import '../util/context_extension.dart';
|
||||
import '../util/general_dialog.dart';
|
||||
|
||||
|
@ -39,7 +39,7 @@ class EpisodeBrief {
|
||||
this.downloadDate = 0})
|
||||
: assert(enclosureUrl != null);
|
||||
|
||||
String dateToString() {
|
||||
String ateToString() {
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true);
|
||||
var diffrence = DateTime.now().toUtc().difference(date);
|
||||
if (diffrence.inHours < 1) {
|
||||
@ -56,23 +56,6 @@ class EpisodeBrief {
|
||||
}
|
||||
}
|
||||
|
||||
String downloadDateToString() {
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(downloadDate);
|
||||
var diffrence = DateTime.now().toUtc().difference(date);
|
||||
if (diffrence.inHours < 1) {
|
||||
return '1 hour ago';
|
||||
} else if (diffrence.inHours < 24) {
|
||||
return '${diffrence.inHours} hours ago';
|
||||
} else if (diffrence.inHours == 24) {
|
||||
return '1 day ago';
|
||||
} else if (diffrence.inDays < 7) {
|
||||
return '${diffrence.inDays} days ago';
|
||||
} else {
|
||||
return DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true).toLocal());
|
||||
}
|
||||
}
|
||||
|
||||
MediaItem toMediaItem() {
|
||||
return MediaItem(
|
||||
id: mediaId,
|
||||
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:focused_menu/focused_menu.dart';
|
||||
import 'package:focused_menu/modals.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:line_icons/line_icons.dart';
|
||||
@ -12,10 +13,10 @@ import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:auto_animated/auto_animated.dart';
|
||||
import 'open_container.dart';
|
||||
|
||||
import '../state/audiostate.dart';
|
||||
import '../state/audio_state.dart';
|
||||
import '../state/download_state.dart';
|
||||
import '../type/episodebrief.dart';
|
||||
import '../episodes/episodedetail.dart';
|
||||
import '../episodes/episode_detail.dart';
|
||||
import '../local_storage/sqflite_localpodcast.dart';
|
||||
import '../local_storage/key_value_storage.dart';
|
||||
import 'colorize.dart';
|
||||
@ -45,6 +46,19 @@ class EpisodeGrid extends StatelessWidget {
|
||||
this.layout = Layout.three,
|
||||
this.reverse,
|
||||
}) : super(key: key);
|
||||
String _dateToString(BuildContext context, {int pubDate}) {
|
||||
final s = context.s;
|
||||
DateTime date = DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true);
|
||||
var difference = DateTime.now().toUtc().difference(date);
|
||||
if (difference.inHours < 24) {
|
||||
return s.hoursAgo(difference.inHours);
|
||||
} else if (difference.inDays < 7) {
|
||||
return s.daysAgo(difference.inDays);
|
||||
} else {
|
||||
return DateFormat.yMMMd().format(
|
||||
DateTime.fromMillisecondsSinceEpoch(pubDate, isUtc: true).toLocal());
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> _isListened(EpisodeBrief episode) async {
|
||||
DBHelper dbHelper = DBHelper();
|
||||
@ -210,7 +224,7 @@ class EpisodeGrid extends StatelessWidget {
|
||||
|
||||
Widget _pubDate(BuildContext context, {EpisodeBrief episode, Color color}) =>
|
||||
Text(
|
||||
episode.dateToString(),
|
||||
_dateToString(context, pubDate: episode.pubDate),
|
||||
style: TextStyle(
|
||||
fontSize: context.width / 35,
|
||||
color: color,
|
||||
|
Loading…
x
Reference in New Issue
Block a user