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

Add zh support

This commit is contained in:
stonegate 2020-07-04 22:42:56 +08:00
parent 7e365dbb87
commit 400e247134
16 changed files with 1323 additions and 280 deletions

View File

@ -4,40 +4,36 @@
<img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/text.png" art = "Tsacdop"/> <img src="https://raw.githubusercontent.com/stonega/tsacdop/master/android/app/src/main/res/mipmap-xhdpi/text.png" art = "Tsacdop"/>
</p> </p>
![CircleCI](https://img.shields.io/circleci/build/github/stonega/tsacdop?token=efe1331861e017144f2abb363acd95197e436dad) ![CircleCI](https://img.shields.io/circleci/build/github/stonega/tsacdop?token=efe1331861e017144f2abb363acd95197e436dad) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/stonega/tsacdop) [![GooglePlay](https://img.shields.io/badge/Google-PlayStore-%2323CCC6)](https://play.google.com/store/apps/details?id=com.stonegate.tsacdop)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/stonega/tsacdop) [![GooglePlay](https://img.shields.io/badge/Google-PlayStore-%2323CCC6)](https://play.google.com/store/apps/details?id=com.stonegate.tsacdop)
## About ## About
Enjoy podcasts with Tsacdop. Enjoy podcasts with Tsacdop.
Tsacdop is a podcast player developed with flutter, a clean, simply beautiful and friendly app, only support Android right now. Tsacdop is a podcast player developed with flutter, a clean, simply beautiful and friendly app, only support Android right now.
Credit to flutter team and all involved plugins, especially [webfeed](https://github.com/witochandra/webfeed) and [Just_Audio](https://pub.dev/packages/just_audio). Credit to flutter team and all involved plugins, especially [webfeed](https://github.com/witochandra/webfeed) and [Just_Audio](https://pub.dev/packages/just_audio).
The podcasts search engine is powered by [ListenNotes](https://listennotes.com). The podcasts search engine is powered by [ListenNotes](https://listennotes.com).
## Features ## Features
* Podcasts group management - Podcasts group management
* Playlist support - Playlist support
* Sleep timer / Speed setting - Sleep timer / Speed setting
* OMPL file export and import - OMPL file export and import
* Auto syncing in background - Auto syncing in background
* Listen and subscribe history record - Listen and subscribe history record
* Dark mode / Accent color - Dark mode / Accent color
* Download for offline playing - Download for offline playing
* Auto download new episodes / Auto delete outdated downloads - Auto download new episodes / Auto delete outdated downloads
More to come... More to come...
## Preview ## Preview
| HomePage | Group | Podcast | Episode | DarkMode | | HomePage | Group | Podcast | Episode | DarkMode |
|------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| <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"/> | | <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"/> |
## License ## License
@ -49,8 +45,8 @@ Tsacdop is licensed under the [GPL V3.0](https://github.com/stonega/tsacdop/blob
Tsacdop is using ListenNotes api 1.0 pro to search podcast, which is not free. So I can not expose the api key in the repo. Tsacdop is using ListenNotes api 1.0 pro to search podcast, which is not free. So I can not expose the api key in the repo.
If you want to build the app, you need to create a new file named .env.dart in lib folder. Add below code in .env.dart. If you want to build the app, you need to create a new file named .env.dart in lib folder. Add below code in .env.dart.
``` ```dart
final environment = {"apiKey":"APIKEY", "shareKey":"SHAREKEY"}; 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. You can get own api key on [ListenNotes](https://www.listennotes.com/api/), basic plan is free to all, and replace "APIKEY" with it.
@ -58,7 +54,7 @@ If no api key added, the search function in the app won't work. But you can stil
## Known Issue ## Known Issue
* Playlist unstable - Playlist unstable
## Getting Started ## Getting Started
@ -66,10 +62,8 @@ This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project: A few resources to get you started if this is your first Flutter project:
* [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
* [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials, [online documentation](https://flutter.dev/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference.
samples, guidance on mobile development, and a full API reference.

View File

@ -19,27 +19,85 @@ typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary { class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'en'; String get localeName => 'en';
static m0(groupName, count) => "${Intl.plural(count, zero: '', one: '${count} episode in ${groupName} added to playlist', other: '${count} episodes in ${groupName} added to playlist')}";
static m1(count) => "${Intl.plural(count, zero: '', one: '${count} episode added to playlist', other: '${count} episodes added to playlist')}";
static m2(host) => "Hosted on ${host}";
static m3(count) => "${Intl.plural(count, zero: '', one: '${count} hour', other: '${count} hours')}";
static m4(count) => "${Intl.plural(count, zero: '', one: '${count} min', other: '${count} mins')}";
static m5(title) => "Fetch data ${title}";
static m6(title) => "Subscribe failed, network error ${title}";
static m7(title) => "Subscribe ${title}";
static m8(title) => "Subscribe failed, podcast existed ${title}";
static m9(title) => "Subscribe success ${title}";
static m10(title) => "Update ${title}";
static m11(title) => "Update error ${title}";
static m12(time) => "Last time ${time}";
static m13(time) => "${time} Left";
static m14(count) => "${Intl.plural(count, zero: 'No Update', one: 'Updated ${count} Episode', other: 'Updated ${count} Episodes')}";
static m15(version) => "Version : ${version}";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function> { static _notInlinedMessages(_) => <String, Function> {
"add" : MessageLookupByLibrary.simpleMessage("Add"),
"addEpisodeGroup" : m0,
"addNewEpisodeAll" : m1,
"addNewEpisodeTooltip" : MessageLookupByLibrary.simpleMessage("Add new episodes to playlist"),
"addSomeGroups" : MessageLookupByLibrary.simpleMessage("Add some groups"),
"all" : MessageLookupByLibrary.simpleMessage("All"), "all" : MessageLookupByLibrary.simpleMessage("All"),
"cancel" : MessageLookupByLibrary.simpleMessage("Cancel"), "back" : MessageLookupByLibrary.simpleMessage("Back"),
"buffering" : MessageLookupByLibrary.simpleMessage("Buffering"),
"cancel" : MessageLookupByLibrary.simpleMessage("CANCEL"),
"changeLayout" : MessageLookupByLibrary.simpleMessage("Change layout"),
"changelog" : MessageLookupByLibrary.simpleMessage("Changelog"),
"chooseA" : MessageLookupByLibrary.simpleMessage("Choose a"), "chooseA" : MessageLookupByLibrary.simpleMessage("Choose a"),
"clear" : MessageLookupByLibrary.simpleMessage("Clear"),
"color" : MessageLookupByLibrary.simpleMessage("color"), "color" : MessageLookupByLibrary.simpleMessage("color"),
"confirm" : MessageLookupByLibrary.simpleMessage("Confirm"), "confirm" : MessageLookupByLibrary.simpleMessage("CONFIRM"),
"darkMode" : MessageLookupByLibrary.simpleMessage("Dark mode"), "darkMode" : MessageLookupByLibrary.simpleMessage("Dark mode"),
"delete" : MessageLookupByLibrary.simpleMessage("Delete"), "delete" : MessageLookupByLibrary.simpleMessage("Delete"),
"developer" : MessageLookupByLibrary.simpleMessage("Developer"),
"dismiss" : MessageLookupByLibrary.simpleMessage("Dismiss"),
"download" : MessageLookupByLibrary.simpleMessage("Download"), "download" : MessageLookupByLibrary.simpleMessage("Download"),
"downloaded" : MessageLookupByLibrary.simpleMessage("Downloaded"),
"editName" : MessageLookupByLibrary.simpleMessage("Edit name"), "editName" : MessageLookupByLibrary.simpleMessage("Edit name"),
"endOfEpisode" : MessageLookupByLibrary.simpleMessage("End of Episode"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("End of Episode"),
"featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("Episode view"),
"featureDiscoveryEpisodeDes" : MessageLookupByLibrary.simpleMessage("You can long tap to play episode or add episode to playlist."),
"featureDiscoveryEpisodeTitle" : MessageLookupByLibrary.simpleMessage("Long tap to play episode instantly"),
"featureDiscoveryOMPL" : MessageLookupByLibrary.simpleMessage("Tap to import OMPL"),
"featureDiscoveryOMPLDes" : MessageLookupByLibrary.simpleMessage("You can import OMPL file, open setting or refresh all podcast at once here."),
"featureDiscoveryPlaylist" : MessageLookupByLibrary.simpleMessage("Tap to open playlist"),
"featureDiscoveryPlaylistDes" : MessageLookupByLibrary.simpleMessage("You can add episode to playlist by yourself. Episode will be auto removed from playlist when played."),
"featureDiscoveryPodcast" : MessageLookupByLibrary.simpleMessage("Podcast view"),
"featureDiscoveryPodcastDes" : MessageLookupByLibrary.simpleMessage("You can tap See All to add groups or manage podcasts."),
"featureDiscoveryPodcastTitle" : MessageLookupByLibrary.simpleMessage("Scroll vertically to switch groups"),
"featureDiscoverySearch" : MessageLookupByLibrary.simpleMessage("Tap to search podcast"),
"featureDiscoverySearchDes" : MessageLookupByLibrary.simpleMessage("You can search podcast title , key word or RSS link to subscribe new podcast."),
"feedbackEmail" : MessageLookupByLibrary.simpleMessage("Write to me"), "feedbackEmail" : MessageLookupByLibrary.simpleMessage("Write to me"),
"feedbackGithub" : MessageLookupByLibrary.simpleMessage("Submit issue"), "feedbackGithub" : MessageLookupByLibrary.simpleMessage("Submit issue"),
"feedbackPlay" : MessageLookupByLibrary.simpleMessage("Rate on Play"), "feedbackPlay" : MessageLookupByLibrary.simpleMessage("Rate on Play"),
"feedbackTelegram" : MessageLookupByLibrary.simpleMessage("Join group"), "feedbackTelegram" : MessageLookupByLibrary.simpleMessage("Join group"),
"from" : MessageLookupByLibrary.simpleMessage("From"), "from" : MessageLookupByLibrary.simpleMessage("From"),
"goodNight" : MessageLookupByLibrary.simpleMessage("Good Night"),
"groupFilter" : MessageLookupByLibrary.simpleMessage("Group filter"),
"groups" : MessageLookupByLibrary.simpleMessage("Groups"), "groups" : MessageLookupByLibrary.simpleMessage("Groups"),
"homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("See All"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("See All"),
"homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Playlist"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Playlist"),
"homeSubMenuDownloaded" : MessageLookupByLibrary.simpleMessage("Downloaded"),
"homeSubMenuLikeData" : MessageLookupByLibrary.simpleMessage("Like Date"), "homeSubMenuLikeData" : MessageLookupByLibrary.simpleMessage("Like Date"),
"homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Sort by"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Sort by"),
"homeSubMenuUpdateDate" : MessageLookupByLibrary.simpleMessage("Update Date"), "homeSubMenuUpdateDate" : MessageLookupByLibrary.simpleMessage("Update Date"),
@ -49,29 +107,52 @@ class MessageLookup extends MessageLookupByLibrary {
"homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("Import OMPL"), "homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("Import OMPL"),
"homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("Refresh all"), "homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("Refresh all"),
"homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("Settings"), "homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("Settings"),
"hostedOn" : m2,
"hoursCount" : m3,
"later" : MessageLookupByLibrary.simpleMessage("Later"), "later" : MessageLookupByLibrary.simpleMessage("Later"),
"lightMode" : MessageLookupByLibrary.simpleMessage("Light mode"), "lightMode" : MessageLookupByLibrary.simpleMessage("Light mode"),
"like" : MessageLookupByLibrary.simpleMessage("Like"), "like" : MessageLookupByLibrary.simpleMessage("Like"),
"likeDate" : MessageLookupByLibrary.simpleMessage("Like date"),
"liked" : MessageLookupByLibrary.simpleMessage("Liked"), "liked" : MessageLookupByLibrary.simpleMessage("Liked"),
"listen" : MessageLookupByLibrary.simpleMessage("Listen"), "listen" : MessageLookupByLibrary.simpleMessage("Listen"),
"listened" : MessageLookupByLibrary.simpleMessage("Listened"), "listened" : MessageLookupByLibrary.simpleMessage("Listened"),
"loadMore" : MessageLookupByLibrary.simpleMessage("Load more"),
"markConfirm" : MessageLookupByLibrary.simpleMessage("Mark confirm"),
"markConfirmContent" : MessageLookupByLibrary.simpleMessage("Confirm mark all episodes listened?"),
"markListened" : MessageLookupByLibrary.simpleMessage("Mark listened"), "markListened" : MessageLookupByLibrary.simpleMessage("Mark listened"),
"menu" : MessageLookupByLibrary.simpleMessage("Menu"), "menu" : MessageLookupByLibrary.simpleMessage("Menu"),
"menuAllPodcasts" : MessageLookupByLibrary.simpleMessage("All podcasts"), "menuAllPodcasts" : MessageLookupByLibrary.simpleMessage("All podcasts"),
"menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("Mark All Listened"), "menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("Mark All Listened"),
"menuMarkListened" : MessageLookupByLibrary.simpleMessage("Mark Listened"),
"menuViewRSS" : MessageLookupByLibrary.simpleMessage("Visit RSS Feed"), "menuViewRSS" : MessageLookupByLibrary.simpleMessage("Visit RSS Feed"),
"menuVisitSite" : MessageLookupByLibrary.simpleMessage("Visit Site"), "menuVisitSite" : MessageLookupByLibrary.simpleMessage("Visit Site"),
"minsCount" : m4,
"network" : MessageLookupByLibrary.simpleMessage("Network"), "network" : MessageLookupByLibrary.simpleMessage("Network"),
"newGroup" : MessageLookupByLibrary.simpleMessage("Create new group"), "newGroup" : MessageLookupByLibrary.simpleMessage("Create new group"),
"newestFirst" : MessageLookupByLibrary.simpleMessage("Newest first"),
"noEpisodeDownload" : MessageLookupByLibrary.simpleMessage("No episode downloaded yet"),
"noEpisodeFavorite" : MessageLookupByLibrary.simpleMessage("No episode collected yet"),
"noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("No episode received yet"),
"noPodcastGroup" : MessageLookupByLibrary.simpleMessage("No podcast in this group"),
"notificaitonFatch" : m5,
"notificationNetworkError" : m6,
"notificationSubscribe" : m7,
"notificationSubscribeExisted" : m8,
"notificationSuccess" : m9,
"notificationUpdate" : m10,
"notificationUpdateError" : m11,
"oldestFirst" : MessageLookupByLibrary.simpleMessage("Oldest first"),
"play" : MessageLookupByLibrary.simpleMessage("Play"), "play" : MessageLookupByLibrary.simpleMessage("Play"),
"playing" : MessageLookupByLibrary.simpleMessage("Playing"),
"podcastSubscribed" : MessageLookupByLibrary.simpleMessage("Podcast subscribed"),
"popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("Download episode"), "popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("Download episode"),
"popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("Add episode to playlist"), "popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("Add episode to playlist"),
"popupMenuLikeDes" : MessageLookupByLibrary.simpleMessage("Add episode to favorite"), "popupMenuLikeDes" : MessageLookupByLibrary.simpleMessage("Add episode to favorite"),
"popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("Mark episode as listened"), "popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("Mark episode as listened"),
"popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("Play the episode"), "popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("Play the episode"),
"privacyPolicy" : MessageLookupByLibrary.simpleMessage("Privacy Policy"),
"remove" : MessageLookupByLibrary.simpleMessage("Remove"), "remove" : MessageLookupByLibrary.simpleMessage("Remove"),
"schedule" : MessageLookupByLibrary.simpleMessage("Schedule"), "schedule" : MessageLookupByLibrary.simpleMessage("Schedule"),
"searchInvalidRss" : MessageLookupByLibrary.simpleMessage("Invalid RSS link"),
"searchPodcast" : MessageLookupByLibrary.simpleMessage("Search podcast"), "searchPodcast" : MessageLookupByLibrary.simpleMessage("Search podcast"),
"settingStorage" : MessageLookupByLibrary.simpleMessage("Storage"), "settingStorage" : MessageLookupByLibrary.simpleMessage("Storage"),
"settingsAccentColor" : MessageLookupByLibrary.simpleMessage("Accent color"), "settingsAccentColor" : MessageLookupByLibrary.simpleMessage("Accent color"),
@ -128,9 +209,12 @@ class MessageLookup extends MessageLookupByLibrary {
"settingsTheme" : MessageLookupByLibrary.simpleMessage("Theme"), "settingsTheme" : MessageLookupByLibrary.simpleMessage("Theme"),
"settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("Update interval"), "settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("Update interval"),
"settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("Default 24 hours"), "settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("Default 24 hours"),
"size" : MessageLookupByLibrary.simpleMessage("Size"),
"sleepTimer" : MessageLookupByLibrary.simpleMessage("Sleep timer"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("Sleep timer"),
"subscribe" : MessageLookupByLibrary.simpleMessage("Subscribe"), "subscribe" : MessageLookupByLibrary.simpleMessage("Subscribe"),
"systemDefault" : MessageLookupByLibrary.simpleMessage("System default"), "systemDefault" : MessageLookupByLibrary.simpleMessage("System default"),
"timeLastPlayed" : m12,
"timeLeft" : m13,
"to" : MessageLookupByLibrary.simpleMessage("To"), "to" : MessageLookupByLibrary.simpleMessage("To"),
"toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("Added to playlist"), "toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("Added to playlist"),
"toastDescovery" : MessageLookupByLibrary.simpleMessage("Discovery feature reopened, pleast restart the app"), "toastDescovery" : MessageLookupByLibrary.simpleMessage("Discovery feature reopened, pleast restart the app"),
@ -138,7 +222,12 @@ class MessageLookup extends MessageLookupByLibrary {
"toastFileNotVilid" : MessageLookupByLibrary.simpleMessage("File not vilid"), "toastFileNotVilid" : MessageLookupByLibrary.simpleMessage("File not vilid"),
"toastReadFile" : MessageLookupByLibrary.simpleMessage("Read file successfully"), "toastReadFile" : MessageLookupByLibrary.simpleMessage("Read file successfully"),
"toastRemovePlaylist" : MessageLookupByLibrary.simpleMessage("Removed from playlist"), "toastRemovePlaylist" : MessageLookupByLibrary.simpleMessage("Removed from playlist"),
"understood" : MessageLookupByLibrary.simpleMessage("Understood"),
"unlike" : MessageLookupByLibrary.simpleMessage("Unlike"), "unlike" : MessageLookupByLibrary.simpleMessage("Unlike"),
"unliked" : MessageLookupByLibrary.simpleMessage("Unliked") "unliked" : MessageLookupByLibrary.simpleMessage("Removed from favorite"),
"updateDate" : MessageLookupByLibrary.simpleMessage("Update date"),
"updateEpisodesCount" : m14,
"updateFailed" : MessageLookupByLibrary.simpleMessage("Update failed, network error"),
"version" : m15
}; };
} }

View File

@ -19,27 +19,85 @@ typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
class MessageLookup extends MessageLookupByLibrary { class MessageLookup extends MessageLookupByLibrary {
String get localeName => 'zh_Hans'; String get localeName => 'zh_Hans';
static m0(groupName, count) => "{count, plural, zero{} other{{group Name}分组${count}集节目添加到播放列表}}";
static m1(count) => "${Intl.plural(count, zero: '', other: '${count}集节目添加到播放列表')}";
static m2(host) => "平台 ${host}";
static m3(count) => "${Intl.plural(count, zero: '', other: '${count} 小时')}";
static m4(count) => "${Intl.plural(count, zero: '', other: '${count}分钟')}";
static m5(title) => "获取数据 ${title}";
static m6(title) => "订阅失败,网络错误 ${title}";
static m7(title) => "订阅${title}";
static m8(title) => "订阅失败,播客已存在 ${title}";
static m9(title) => "订阅成功 ${title}";
static m10(title) => "更新 ${title}";
static m11(title) => "更新失败 ${title}";
static m12(time) => "上次播放${time}";
static m13(time) => "剩余 ${time}";
static m14(count) => "${Intl.plural(count, zero: '未有更新', other: '更新 ${count} 集节目')}";
static m15(version) => "版本:${version}";
final messages = _notInlinedMessages(_notInlinedMessages); final messages = _notInlinedMessages(_notInlinedMessages);
static _notInlinedMessages(_) => <String, Function> { static _notInlinedMessages(_) => <String, Function> {
"add" : MessageLookupByLibrary.simpleMessage("订阅"),
"addEpisodeGroup" : m0,
"addNewEpisodeAll" : m1,
"addNewEpisodeTooltip" : MessageLookupByLibrary.simpleMessage("添加更新节目到播放列表"),
"addSomeGroups" : MessageLookupByLibrary.simpleMessage("请添加分组"),
"all" : MessageLookupByLibrary.simpleMessage("全部"), "all" : MessageLookupByLibrary.simpleMessage("全部"),
"back" : MessageLookupByLibrary.simpleMessage("返回"),
"buffering" : MessageLookupByLibrary.simpleMessage("缓冲"),
"cancel" : MessageLookupByLibrary.simpleMessage("取消"), "cancel" : MessageLookupByLibrary.simpleMessage("取消"),
"changeLayout" : MessageLookupByLibrary.simpleMessage("修改布局"),
"changelog" : MessageLookupByLibrary.simpleMessage("更新日志"),
"chooseA" : MessageLookupByLibrary.simpleMessage("选择"), "chooseA" : MessageLookupByLibrary.simpleMessage("选择"),
"clear" : MessageLookupByLibrary.simpleMessage("清除"),
"color" : MessageLookupByLibrary.simpleMessage("颜色"), "color" : MessageLookupByLibrary.simpleMessage("颜色"),
"confirm" : MessageLookupByLibrary.simpleMessage("确认"), "confirm" : MessageLookupByLibrary.simpleMessage("确认"),
"darkMode" : MessageLookupByLibrary.simpleMessage("夜晚模式"), "darkMode" : MessageLookupByLibrary.simpleMessage("夜晚模式"),
"delete" : MessageLookupByLibrary.simpleMessage("删除"), "delete" : MessageLookupByLibrary.simpleMessage("删除"),
"developer" : MessageLookupByLibrary.simpleMessage("关于我"),
"dismiss" : MessageLookupByLibrary.simpleMessage("忽略"),
"download" : MessageLookupByLibrary.simpleMessage("下载"), "download" : MessageLookupByLibrary.simpleMessage("下载"),
"downloaded" : MessageLookupByLibrary.simpleMessage("已下载"),
"editName" : MessageLookupByLibrary.simpleMessage("修改组名"), "editName" : MessageLookupByLibrary.simpleMessage("修改组名"),
"endOfEpisode" : MessageLookupByLibrary.simpleMessage("节目结束"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("节目结束"),
"featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("节目界面"),
"featureDiscoveryEpisodeDes" : MessageLookupByLibrary.simpleMessage("您可以长按播放节目或者添加节目到播放列表。"),
"featureDiscoveryEpisodeTitle" : MessageLookupByLibrary.simpleMessage("您可以长按快速播放节目"),
"featureDiscoveryOMPL" : MessageLookupByLibrary.simpleMessage("点击导入 OMPL"),
"featureDiscoveryOMPLDes" : MessageLookupByLibrary.simpleMessage("在这里您可以导入OMPL文件打开设置页面或者刷新所有播客。"),
"featureDiscoveryPlaylist" : MessageLookupByLibrary.simpleMessage("点击打开播放列表"),
"featureDiscoveryPlaylistDes" : MessageLookupByLibrary.simpleMessage("您可以添加节目到播放列表,节目在播放后将会从播放列表自动移除。"),
"featureDiscoveryPodcast" : MessageLookupByLibrary.simpleMessage("播客界面"),
"featureDiscoveryPodcastDes" : MessageLookupByLibrary.simpleMessage("您可以点击“查看所有”新增或管理分组。"),
"featureDiscoveryPodcastTitle" : MessageLookupByLibrary.simpleMessage("您可以通过上下滑动切换分组"),
"featureDiscoverySearch" : MessageLookupByLibrary.simpleMessage("点击搜索播客"),
"featureDiscoverySearchDes" : MessageLookupByLibrary.simpleMessage("您可以通过搜索播客名称、关键字或者RSS链接订阅播客。"),
"feedbackEmail" : MessageLookupByLibrary.simpleMessage("发送邮件"), "feedbackEmail" : MessageLookupByLibrary.simpleMessage("发送邮件"),
"feedbackGithub" : MessageLookupByLibrary.simpleMessage("提交Issue"), "feedbackGithub" : MessageLookupByLibrary.simpleMessage("提交Issue"),
"feedbackPlay" : MessageLookupByLibrary.simpleMessage("Play评价"), "feedbackPlay" : MessageLookupByLibrary.simpleMessage("Play评价"),
"feedbackTelegram" : MessageLookupByLibrary.simpleMessage("加入小组"), "feedbackTelegram" : MessageLookupByLibrary.simpleMessage("加入小组"),
"from" : MessageLookupByLibrary.simpleMessage(""), "from" : MessageLookupByLibrary.simpleMessage(""),
"goodNight" : MessageLookupByLibrary.simpleMessage("晚安"),
"groupFilter" : MessageLookupByLibrary.simpleMessage("分组"),
"groups" : MessageLookupByLibrary.simpleMessage("分组"), "groups" : MessageLookupByLibrary.simpleMessage("分组"),
"homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("查看全部"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("查看全部"),
"homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("播放列表"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("播放列表"),
"homeSubMenuDownloaded" : MessageLookupByLibrary.simpleMessage("已下载"),
"homeSubMenuLikeData" : MessageLookupByLibrary.simpleMessage("添加日期"), "homeSubMenuLikeData" : MessageLookupByLibrary.simpleMessage("添加日期"),
"homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("排序"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("排序"),
"homeSubMenuUpdateDate" : MessageLookupByLibrary.simpleMessage("更新日期"), "homeSubMenuUpdateDate" : MessageLookupByLibrary.simpleMessage("更新日期"),
@ -49,29 +107,52 @@ class MessageLookup extends MessageLookupByLibrary {
"homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("导入OMPL"), "homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("导入OMPL"),
"homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("全部刷新"), "homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("全部刷新"),
"homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("设置"), "homeToprightMenuSettings" : MessageLookupByLibrary.simpleMessage("设置"),
"hostedOn" : m2,
"hoursCount" : m3,
"later" : MessageLookupByLibrary.simpleMessage("稍后"), "later" : MessageLookupByLibrary.simpleMessage("稍后"),
"lightMode" : MessageLookupByLibrary.simpleMessage("明亮模式"), "lightMode" : MessageLookupByLibrary.simpleMessage("明亮模式"),
"like" : MessageLookupByLibrary.simpleMessage("喜欢"), "like" : MessageLookupByLibrary.simpleMessage("喜欢"),
"likeDate" : MessageLookupByLibrary.simpleMessage("收藏日期"),
"liked" : MessageLookupByLibrary.simpleMessage("已收藏"), "liked" : MessageLookupByLibrary.simpleMessage("已收藏"),
"listen" : MessageLookupByLibrary.simpleMessage("收听"), "listen" : MessageLookupByLibrary.simpleMessage("收听"),
"listened" : MessageLookupByLibrary.simpleMessage("已收听"), "listened" : MessageLookupByLibrary.simpleMessage("已收听"),
"loadMore" : MessageLookupByLibrary.simpleMessage("加载更多"),
"markConfirm" : MessageLookupByLibrary.simpleMessage("确认标记"),
"markConfirmContent" : MessageLookupByLibrary.simpleMessage("是否确认标记全部节目为已收听?"),
"markListened" : MessageLookupByLibrary.simpleMessage("标记已收听"), "markListened" : MessageLookupByLibrary.simpleMessage("标记已收听"),
"menu" : MessageLookupByLibrary.simpleMessage("菜单"), "menu" : MessageLookupByLibrary.simpleMessage("菜单"),
"menuAllPodcasts" : MessageLookupByLibrary.simpleMessage("所有订阅"), "menuAllPodcasts" : MessageLookupByLibrary.simpleMessage("所有订阅"),
"menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("标记所有已收听"), "menuMarkAllListened" : MessageLookupByLibrary.simpleMessage("标记所有已收听"),
"menuMarkListened" : MessageLookupByLibrary.simpleMessage("标记已收听"),
"menuViewRSS" : MessageLookupByLibrary.simpleMessage("查看 RSS"), "menuViewRSS" : MessageLookupByLibrary.simpleMessage("查看 RSS"),
"menuVisitSite" : MessageLookupByLibrary.simpleMessage("访问网站"), "menuVisitSite" : MessageLookupByLibrary.simpleMessage("访问网站"),
"minsCount" : m4,
"network" : MessageLookupByLibrary.simpleMessage("网络"), "network" : MessageLookupByLibrary.simpleMessage("网络"),
"newGroup" : MessageLookupByLibrary.simpleMessage("创建分组"), "newGroup" : MessageLookupByLibrary.simpleMessage("创建分组"),
"newestFirst" : MessageLookupByLibrary.simpleMessage("由新到旧"),
"noEpisodeDownload" : MessageLookupByLibrary.simpleMessage("暂无下载节目"),
"noEpisodeFavorite" : MessageLookupByLibrary.simpleMessage("暂无收藏节目"),
"noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("暂无节目"),
"noPodcastGroup" : MessageLookupByLibrary.simpleMessage("分组无播客"),
"notificaitonFatch" : m5,
"notificationNetworkError" : m6,
"notificationSubscribe" : m7,
"notificationSubscribeExisted" : m8,
"notificationSuccess" : m9,
"notificationUpdate" : m10,
"notificationUpdateError" : m11,
"oldestFirst" : MessageLookupByLibrary.simpleMessage("由旧到新"),
"play" : MessageLookupByLibrary.simpleMessage("播放"), "play" : MessageLookupByLibrary.simpleMessage("播放"),
"playing" : MessageLookupByLibrary.simpleMessage("正在播放"),
"podcastSubscribed" : MessageLookupByLibrary.simpleMessage("播客已订阅"),
"popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("下载节目"), "popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("下载节目"),
"popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("添加到播放列表"), "popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("添加到播放列表"),
"popupMenuLikeDes" : MessageLookupByLibrary.simpleMessage("添加到收藏"), "popupMenuLikeDes" : MessageLookupByLibrary.simpleMessage("添加到收藏"),
"popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("设置为已收听"), "popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("设置为已收听"),
"popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("播放节目"), "popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("播放节目"),
"privacyPolicy" : MessageLookupByLibrary.simpleMessage("隐私条款"),
"remove" : MessageLookupByLibrary.simpleMessage("移除"), "remove" : MessageLookupByLibrary.simpleMessage("移除"),
"schedule" : MessageLookupByLibrary.simpleMessage("定时"), "schedule" : MessageLookupByLibrary.simpleMessage("定时"),
"searchInvalidRss" : MessageLookupByLibrary.simpleMessage("RSS 链接错误"),
"searchPodcast" : MessageLookupByLibrary.simpleMessage("搜索播客"), "searchPodcast" : MessageLookupByLibrary.simpleMessage("搜索播客"),
"settingStorage" : MessageLookupByLibrary.simpleMessage("储存空间"), "settingStorage" : MessageLookupByLibrary.simpleMessage("储存空间"),
"settingsAccentColor" : MessageLookupByLibrary.simpleMessage("次要颜色"), "settingsAccentColor" : MessageLookupByLibrary.simpleMessage("次要颜色"),
@ -128,9 +209,12 @@ class MessageLookup extends MessageLookupByLibrary {
"settingsTheme" : MessageLookupByLibrary.simpleMessage("主题"), "settingsTheme" : MessageLookupByLibrary.simpleMessage("主题"),
"settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("更新频率"), "settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("更新频率"),
"settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("默认 24 小时"), "settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("默认 24 小时"),
"size" : MessageLookupByLibrary.simpleMessage("大小"),
"sleepTimer" : MessageLookupByLibrary.simpleMessage("睡眠模式"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("睡眠模式"),
"subscribe" : MessageLookupByLibrary.simpleMessage("订阅"), "subscribe" : MessageLookupByLibrary.simpleMessage("订阅"),
"systemDefault" : MessageLookupByLibrary.simpleMessage("系统默认"), "systemDefault" : MessageLookupByLibrary.simpleMessage("系统默认"),
"timeLastPlayed" : m12,
"timeLeft" : m13,
"to" : MessageLookupByLibrary.simpleMessage(""), "to" : MessageLookupByLibrary.simpleMessage(""),
"toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("添加到播放列表"), "toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("添加到播放列表"),
"toastDescovery" : MessageLookupByLibrary.simpleMessage("重启应用后可查看"), "toastDescovery" : MessageLookupByLibrary.simpleMessage("重启应用后可查看"),
@ -138,7 +222,12 @@ class MessageLookup extends MessageLookupByLibrary {
"toastFileNotVilid" : MessageLookupByLibrary.simpleMessage("文件错误"), "toastFileNotVilid" : MessageLookupByLibrary.simpleMessage("文件错误"),
"toastReadFile" : MessageLookupByLibrary.simpleMessage("读取文件成功"), "toastReadFile" : MessageLookupByLibrary.simpleMessage("读取文件成功"),
"toastRemovePlaylist" : MessageLookupByLibrary.simpleMessage("从播放列表移除"), "toastRemovePlaylist" : MessageLookupByLibrary.simpleMessage("从播放列表移除"),
"understood" : MessageLookupByLibrary.simpleMessage("了解"),
"unlike" : MessageLookupByLibrary.simpleMessage("取消喜欢"), "unlike" : MessageLookupByLibrary.simpleMessage("取消喜欢"),
"unliked" : MessageLookupByLibrary.simpleMessage("从收藏移除") "unliked" : MessageLookupByLibrary.simpleMessage("从收藏移除"),
"updateDate" : MessageLookupByLibrary.simpleMessage("更新日期"),
"updateEpisodesCount" : m14,
"updateFailed" : MessageLookupByLibrary.simpleMessage("更新失败"),
"version" : m15
}; };
} }

View File

@ -33,6 +33,62 @@ class S {
return Localizations.of<S>(context, S); return Localizations.of<S>(context, S);
} }
/// `Add`
String get add {
return Intl.message(
'Add',
name: 'add',
desc: 'Subscribe new podcast',
args: [],
);
}
/// `{count, plural, zero{} one{{count} episode in {groupName} added to playlist} other{{count} episodes in {groupName} added to playlist}}`
String addEpisodeGroup(Object groupName, num count) {
return Intl.plural(
count,
zero: '',
one: '$count episode in $groupName added to playlist',
other: '$count episodes in $groupName added to playlist',
name: 'addEpisodeGroup',
desc: '',
args: [groupName, count],
);
}
/// `{count, plural, zero{} one{{count} episode added to playlist} other{{count} episodes added to playlist}}`
String addNewEpisodeAll(num count) {
return Intl.plural(
count,
zero: '',
one: '$count episode added to playlist',
other: '$count episodes added to playlist',
name: 'addNewEpisodeAll',
desc: '',
args: [count],
);
}
/// `Add new episodes to playlist`
String get addNewEpisodeTooltip {
return Intl.message(
'Add new episodes to playlist',
name: 'addNewEpisodeTooltip',
desc: '',
args: [],
);
}
/// `Add some groups`
String get addSomeGroups {
return Intl.message(
'Add some groups',
name: 'addSomeGroups',
desc: 'Please add new groups',
args: [],
);
}
/// `All` /// `All`
String get all { String get all {
return Intl.message( return Intl.message(
@ -43,16 +99,56 @@ class S {
); );
} }
/// `Cancel` /// `Back`
String get back {
return Intl.message(
'Back',
name: 'back',
desc: '',
args: [],
);
}
/// `Buffering`
String get buffering {
return Intl.message(
'Buffering',
name: 'buffering',
desc: '',
args: [],
);
}
/// `CANCEL`
String get cancel { String get cancel {
return Intl.message( return Intl.message(
'Cancel', 'CANCEL',
name: 'cancel', name: 'cancel',
desc: '', desc: '',
args: [], args: [],
); );
} }
/// `Change layout`
String get changeLayout {
return Intl.message(
'Change layout',
name: 'changeLayout',
desc: '',
args: [],
);
}
/// `Changelog`
String get changelog {
return Intl.message(
'Changelog',
name: 'changelog',
desc: '',
args: [],
);
}
/// `Choose a` /// `Choose a`
String get chooseA { String get chooseA {
return Intl.message( return Intl.message(
@ -63,6 +159,16 @@ class S {
); );
} }
/// `Clear`
String get clear {
return Intl.message(
'Clear',
name: 'clear',
desc: '',
args: [],
);
}
/// `color` /// `color`
String get color { String get color {
return Intl.message( return Intl.message(
@ -73,10 +179,10 @@ class S {
); );
} }
/// `Confirm` /// `CONFIRM`
String get confirm { String get confirm {
return Intl.message( return Intl.message(
'Confirm', 'CONFIRM',
name: 'confirm', name: 'confirm',
desc: '', desc: '',
args: [], args: [],
@ -103,6 +209,26 @@ class S {
); );
} }
/// `Developer`
String get developer {
return Intl.message(
'Developer',
name: 'developer',
desc: '',
args: [],
);
}
/// `Dismiss`
String get dismiss {
return Intl.message(
'Dismiss',
name: 'dismiss',
desc: '',
args: [],
);
}
/// `Download` /// `Download`
String get download { String get download {
return Intl.message( return Intl.message(
@ -113,6 +239,16 @@ class S {
); );
} }
/// `Downloaded`
String get downloaded {
return Intl.message(
'Downloaded',
name: 'downloaded',
desc: '',
args: [],
);
}
/// `Edit name` /// `Edit name`
String get editName { String get editName {
return Intl.message( return Intl.message(
@ -133,6 +269,126 @@ class S {
); );
} }
/// `Episode view`
String get featureDiscoveryEpisode {
return Intl.message(
'Episode view',
name: 'featureDiscoveryEpisode',
desc: '',
args: [],
);
}
/// `You can long tap to play episode or add episode to playlist.`
String get featureDiscoveryEpisodeDes {
return Intl.message(
'You can long tap to play episode or add episode to playlist.',
name: 'featureDiscoveryEpisodeDes',
desc: '',
args: [],
);
}
/// `Long tap to play episode instantly`
String get featureDiscoveryEpisodeTitle {
return Intl.message(
'Long tap to play episode instantly',
name: 'featureDiscoveryEpisodeTitle',
desc: '',
args: [],
);
}
/// `Tap to import OMPL`
String get featureDiscoveryOMPL {
return Intl.message(
'Tap to import OMPL',
name: 'featureDiscoveryOMPL',
desc: '',
args: [],
);
}
/// `You can import OMPL file, open setting or refresh all podcast at once here.`
String get featureDiscoveryOMPLDes {
return Intl.message(
'You can import OMPL file, open setting or refresh all podcast at once here.',
name: 'featureDiscoveryOMPLDes',
desc: '',
args: [],
);
}
/// `Tap to open playlist`
String get featureDiscoveryPlaylist {
return Intl.message(
'Tap to open playlist',
name: 'featureDiscoveryPlaylist',
desc: '',
args: [],
);
}
/// `You can add episode to playlist by yourself. Episode will be auto removed from playlist when played.`
String get featureDiscoveryPlaylistDes {
return Intl.message(
'You can add episode to playlist by yourself. Episode will be auto removed from playlist when played.',
name: 'featureDiscoveryPlaylistDes',
desc: '',
args: [],
);
}
/// `Podcast view`
String get featureDiscoveryPodcast {
return Intl.message(
'Podcast view',
name: 'featureDiscoveryPodcast',
desc: '',
args: [],
);
}
/// `You can tap See All to add groups or manage podcasts.`
String get featureDiscoveryPodcastDes {
return Intl.message(
'You can tap See All to add groups or manage podcasts.',
name: 'featureDiscoveryPodcastDes',
desc: '',
args: [],
);
}
/// `Scroll vertically to switch groups`
String get featureDiscoveryPodcastTitle {
return Intl.message(
'Scroll vertically to switch groups',
name: 'featureDiscoveryPodcastTitle',
desc: '',
args: [],
);
}
/// `Tap to search podcast`
String get featureDiscoverySearch {
return Intl.message(
'Tap to search podcast',
name: 'featureDiscoverySearch',
desc: '',
args: [],
);
}
/// `You can search podcast title , key word or RSS link to subscribe new podcast.`
String get featureDiscoverySearchDes {
return Intl.message(
'You can search podcast title , key word or RSS link to subscribe new podcast.',
name: 'featureDiscoverySearchDes',
desc: '',
args: [],
);
}
/// `Write to me` /// `Write to me`
String get feedbackEmail { String get feedbackEmail {
return Intl.message( return Intl.message(
@ -183,6 +439,26 @@ class S {
); );
} }
/// `Good Night`
String get goodNight {
return Intl.message(
'Good Night',
name: 'goodNight',
desc: '',
args: [],
);
}
/// `Group filter`
String get groupFilter {
return Intl.message(
'Group filter',
name: 'groupFilter',
desc: '',
args: [],
);
}
/// `Groups` /// `Groups`
String get groups { String get groups {
return Intl.message( return Intl.message(
@ -213,16 +489,6 @@ class S {
); );
} }
/// `Downloaded`
String get homeSubMenuDownloaded {
return Intl.message(
'Downloaded',
name: 'homeSubMenuDownloaded',
desc: '',
args: [],
);
}
/// `Like Date` /// `Like Date`
String get homeSubMenuLikeData { String get homeSubMenuLikeData {
return Intl.message( return Intl.message(
@ -313,6 +579,29 @@ class S {
); );
} }
/// `Hosted on {host}`
String hostedOn(Object host) {
return Intl.message(
'Hosted on $host',
name: 'hostedOn',
desc: '',
args: [host],
);
}
/// `{count, plural, zero{} one{{count} hour} other{{count} hours}}`
String hoursCount(num count) {
return Intl.plural(
count,
zero: '',
one: '$count hour',
other: '$count hours',
name: 'hoursCount',
desc: '',
args: [count],
);
}
/// `Later` /// `Later`
String get later { String get later {
return Intl.message( return Intl.message(
@ -353,6 +642,16 @@ class S {
); );
} }
/// `Like date`
String get likeDate {
return Intl.message(
'Like date',
name: 'likeDate',
desc: '',
args: [],
);
}
/// `Listen` /// `Listen`
String get listen { String get listen {
return Intl.message( return Intl.message(
@ -373,6 +672,36 @@ class S {
); );
} }
/// `Load more`
String get loadMore {
return Intl.message(
'Load more',
name: 'loadMore',
desc: '',
args: [],
);
}
/// `Mark confirm`
String get markConfirm {
return Intl.message(
'Mark confirm',
name: 'markConfirm',
desc: '',
args: [],
);
}
/// `Confirm mark all episodes listened?`
String get markConfirmContent {
return Intl.message(
'Confirm mark all episodes listened?',
name: 'markConfirmContent',
desc: '',
args: [],
);
}
/// `Mark listened` /// `Mark listened`
String get markListened { String get markListened {
return Intl.message( return Intl.message(
@ -413,16 +742,6 @@ class S {
); );
} }
/// `Mark Listened`
String get menuMarkListened {
return Intl.message(
'Mark Listened',
name: 'menuMarkListened',
desc: '',
args: [],
);
}
/// `Visit RSS Feed` /// `Visit RSS Feed`
String get menuViewRSS { String get menuViewRSS {
return Intl.message( return Intl.message(
@ -443,6 +762,19 @@ class S {
); );
} }
/// `{count, plural, zero{} one{{count} min} other{{count} mins}}`
String minsCount(num count) {
return Intl.plural(
count,
zero: '',
one: '$count min',
other: '$count mins',
name: 'minsCount',
desc: '',
args: [count],
);
}
/// `Network` /// `Network`
String get network { String get network {
return Intl.message( return Intl.message(
@ -453,6 +785,16 @@ class S {
); );
} }
/// `Newest first`
String get newestFirst {
return Intl.message(
'Newest first',
name: 'newestFirst',
desc: '',
args: [],
);
}
/// `Create new group` /// `Create new group`
String get newGroup { String get newGroup {
return Intl.message( return Intl.message(
@ -463,6 +805,126 @@ class S {
); );
} }
/// `No episode downloaded yet`
String get noEpisodeDownload {
return Intl.message(
'No episode downloaded yet',
name: 'noEpisodeDownload',
desc: '',
args: [],
);
}
/// `No episode collected yet`
String get noEpisodeFavorite {
return Intl.message(
'No episode collected yet',
name: 'noEpisodeFavorite',
desc: '',
args: [],
);
}
/// `No episode received yet`
String get noEpisodeRecent {
return Intl.message(
'No episode received yet',
name: 'noEpisodeRecent',
desc: '',
args: [],
);
}
/// `No podcast in this group`
String get noPodcastGroup {
return Intl.message(
'No podcast in this group',
name: 'noPodcastGroup',
desc: '',
args: [],
);
}
/// `Fetch data {title}`
String notificaitonFatch(Object title) {
return Intl.message(
'Fetch data $title',
name: 'notificaitonFatch',
desc: '',
args: [title],
);
}
/// `Subscribe failed, network error {title}`
String notificationNetworkError(Object title) {
return Intl.message(
'Subscribe failed, network error $title',
name: 'notificationNetworkError',
desc: '',
args: [title],
);
}
/// `Subscribe {title}`
String notificationSubscribe(Object title) {
return Intl.message(
'Subscribe $title',
name: 'notificationSubscribe',
desc: '',
args: [title],
);
}
/// `Subscribe failed, podcast existed {title}`
String notificationSubscribeExisted(Object title) {
return Intl.message(
'Subscribe failed, podcast existed $title',
name: 'notificationSubscribeExisted',
desc: '',
args: [title],
);
}
/// `Subscribe success {title}`
String notificationSuccess(Object title) {
return Intl.message(
'Subscribe success $title',
name: 'notificationSuccess',
desc: '',
args: [title],
);
}
/// `Update {title}`
String notificationUpdate(Object title) {
return Intl.message(
'Update $title',
name: 'notificationUpdate',
desc: '',
args: [title],
);
}
/// `Update error {title}`
String notificationUpdateError(Object title) {
return Intl.message(
'Update error $title',
name: 'notificationUpdateError',
desc: '',
args: [title],
);
}
/// `Oldest first`
String get oldestFirst {
return Intl.message(
'Oldest first',
name: 'oldestFirst',
desc: '',
args: [],
);
}
/// `Play` /// `Play`
String get play { String get play {
return Intl.message( return Intl.message(
@ -473,6 +935,26 @@ class S {
); );
} }
/// `Playing`
String get playing {
return Intl.message(
'Playing',
name: 'playing',
desc: '',
args: [],
);
}
/// `Podcast subscribed`
String get podcastSubscribed {
return Intl.message(
'Podcast subscribed',
name: 'podcastSubscribed',
desc: '',
args: [],
);
}
/// `Download episode` /// `Download episode`
String get popupMenuDownloadDes { String get popupMenuDownloadDes {
return Intl.message( return Intl.message(
@ -523,6 +1005,16 @@ class S {
); );
} }
/// `Privacy Policy`
String get privacyPolicy {
return Intl.message(
'Privacy Policy',
name: 'privacyPolicy',
desc: '',
args: [],
);
}
/// `Remove` /// `Remove`
String get remove { String get remove {
return Intl.message( return Intl.message(
@ -543,6 +1035,16 @@ class S {
); );
} }
/// `Invalid RSS link`
String get searchInvalidRss {
return Intl.message(
'Invalid RSS link',
name: 'searchInvalidRss',
desc: '',
args: [],
);
}
/// `Search podcast` /// `Search podcast`
String get searchPodcast { String get searchPodcast {
return Intl.message( return Intl.message(
@ -1103,6 +1605,16 @@ class S {
); );
} }
/// `Size`
String get size {
return Intl.message(
'Size',
name: 'size',
desc: '',
args: [],
);
}
/// `Sleep timer` /// `Sleep timer`
String get sleepTimer { String get sleepTimer {
return Intl.message( return Intl.message(
@ -1133,6 +1645,26 @@ class S {
); );
} }
/// `Last time {time}`
String timeLastPlayed(Object time) {
return Intl.message(
'Last time $time',
name: 'timeLastPlayed',
desc: '',
args: [time],
);
}
/// `{time} Left`
String timeLeft(Object time) {
return Intl.message(
'$time Left',
name: 'timeLeft',
desc: '',
args: [time],
);
}
/// `To` /// `To`
String get to { String get to {
return Intl.message( return Intl.message(
@ -1203,6 +1735,16 @@ class S {
); );
} }
/// `Understood`
String get understood {
return Intl.message(
'Understood',
name: 'understood',
desc: '',
args: [],
);
}
/// `Unlike` /// `Unlike`
String get unlike { String get unlike {
return Intl.message( return Intl.message(
@ -1213,15 +1755,58 @@ class S {
); );
} }
/// `Unliked` /// `Removed from favorite`
String get unliked { String get unliked {
return Intl.message( return Intl.message(
'Unliked', 'Removed from favorite',
name: 'unliked', name: 'unliked',
desc: '', desc: '',
args: [], args: [],
); );
} }
/// `Update date`
String get updateDate {
return Intl.message(
'Update date',
name: 'updateDate',
desc: '',
args: [],
);
}
/// `{count, plural, zero{No Update} one{Updated {count} Episode} other{Updated {count} Episodes}}`
String updateEpisodesCount(num count) {
return Intl.plural(
count,
zero: 'No Update',
one: 'Updated $count Episode',
other: 'Updated $count Episodes',
name: 'updateEpisodesCount',
desc: '',
args: [count],
);
}
/// `Update failed, network error`
String get updateFailed {
return Intl.message(
'Update failed, network error',
name: 'updateFailed',
desc: '',
args: [],
);
}
/// `Version : {version}`
String version(Object version) {
return Intl.message(
'Version : $version',
name: 'version',
desc: '',
args: [version],
);
}
} }
class AppLocalizationDelegate extends LocalizationsDelegate<S> { class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@ -63,6 +63,7 @@ class AboutApp extends StatelessWidget {
); );
} }
final s = context.s;
return AnnotatedRegion<SystemUiOverlayStyle>( return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle( value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness, statusBarIconBrightness: Theme.of(context).accentColorBrightness,
@ -73,7 +74,7 @@ class AboutApp extends StatelessWidget {
child: Scaffold( child: Scaffold(
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
appBar: AppBar( appBar: AppBar(
title: Text('About'), title: Text(s.homeToprightMenuAbout),
), ),
body: SafeArea( body: SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
@ -95,7 +96,7 @@ class AboutApp extends StatelessWidget {
image: AssetImage('assets/logo.png'), image: AssetImage('assets/logo.png'),
height: 80, height: 80,
), ),
Text('Version: $version'), Text(s.version(version)),
], ],
), ),
), ),
@ -113,7 +114,7 @@ class AboutApp extends StatelessWidget {
FlatButton( FlatButton(
onPressed: () => _launchUrl( onPressed: () => _launchUrl(
'https://tsacdop.stonegate.me/#/privacy'), 'https://tsacdop.stonegate.me/#/privacy'),
child: Text('Privacy Policy', child: Text(s.privacyPolicy,
style: TextStyle(color: context.accentColor)), style: TextStyle(color: context.accentColor)),
), ),
Container( Container(
@ -127,7 +128,7 @@ class AboutApp extends StatelessWidget {
FlatButton( FlatButton(
onPressed: () => _launchUrl( onPressed: () => _launchUrl(
'https://tsacdop.stonegate.me/#/changelog'), 'https://tsacdop.stonegate.me/#/changelog'),
child: Text('Changelog', child: Text(s.changelog,
style: TextStyle(color: context.accentColor)), style: TextStyle(color: context.accentColor)),
), ),
], ],
@ -152,7 +153,7 @@ class AboutApp extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Developer', s.developer,
style: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),

View File

@ -25,21 +25,6 @@ class MyHomePageDelegate extends SearchDelegate<int> {
searchFieldLabel: searchFieldLabel, searchFieldLabel: searchFieldLabel,
); );
//static Future<List> getList(String searchText) async {
// String apiKey = environment['apiKey'];
// String url =
// "https://listennotes.p.rapidapi.com/api/v1/search?only_in=title%2Cdescription&q=" +
// "$searchText&type=podcast";
// Response response = await Dio().get(url,
// options: Options(headers: {
// 'X-RapidAPI-Key': "$apiKey",
// 'Accept': "application/json"
// }));
// Map searchResultMap = jsonDecode(response.toString());
// var searchResult = SearchPodcast.fromJson(searchResultMap);
// return searchResult.results;
//}
static Future getRss(String url) async { static Future getRss(String url) async {
try { try {
BaseOptions options = new BaseOptions( BaseOptions options = new BaseOptions(
@ -60,10 +45,10 @@ class MyHomePageDelegate extends SearchDelegate<int> {
} }
RegExp rssExp = RegExp(r'^(https?):\/\/(.*)'); RegExp rssExp = RegExp(r'^(https?):\/\/(.*)');
Widget invalidRss() => Container( Widget invalidRss(BuildContext context) => Container(
height: 50, height: 50,
alignment: Alignment.center, alignment: Alignment.center,
child: Text('Invalid rss link'), child: Text(context.s.searchInvalidRss),
); );
@override @override
@ -72,7 +57,7 @@ class MyHomePageDelegate extends SearchDelegate<int> {
@override @override
Widget buildLeading(BuildContext context) { Widget buildLeading(BuildContext context) {
return IconButton( return IconButton(
tooltip: 'Back', tooltip: context.s.back,
icon: AnimatedIcon( icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow, icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation, progress: transitionAnimation,
@ -145,7 +130,7 @@ class MyHomePageDelegate extends SearchDelegate<int> {
Center() Center()
else else
IconButton( IconButton(
tooltip: 'Clear', tooltip: context.s.clear,
icon: const Icon(Icons.clear), icon: const Icon(Icons.clear),
onPressed: () { onPressed: () {
query = ''; query = '';
@ -174,7 +159,7 @@ class MyHomePageDelegate extends SearchDelegate<int> {
future: getRss(rssExp.stringMatch(query)), future: getRss(rssExp.stringMatch(query)),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) if (snapshot.hasError)
return invalidRss(); return invalidRss(context);
else if (snapshot.hasData) else if (snapshot.hasData)
return SearchResult( return SearchResult(
onlinePodcast: snapshot.data, onlinePodcast: snapshot.data,
@ -297,7 +282,7 @@ class _SearchListState extends State<SearchList> {
child: CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2, strokeWidth: 2,
)) ))
: Text('Load more'), : Text(context.s.loadMore),
onPressed: () => _loading onPressed: () => _loading
? null ? null
: setState(() { : setState(() {
@ -362,7 +347,7 @@ class _SearchResultState extends State<SearchResult>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var subscribeWorker = Provider.of<SubscribeWorker>(context, listen: false); var subscribeWorker = Provider.of<SubscribeWorker>(context, listen: false);
final s = context.s;
savePodcast(OnlinePodcast podcast) { savePodcast(OnlinePodcast podcast) {
SubscribeItem item = SubscribeItem item =
SubscribeItem(podcast.rss, podcast.title, imgUrl: podcast.image); SubscribeItem(podcast.rss, podcast.title, imgUrl: podcast.image);
@ -437,14 +422,14 @@ class _SearchResultState extends State<SearchResult>
? OutlineButton( ? OutlineButton(
highlightedBorderColor: context.accentColor, highlightedBorderColor: context.accentColor,
splashColor: context.accentColor.withOpacity(0.8), splashColor: context.accentColor.withOpacity(0.8),
child: Text('Subscribe', child: Text(s.subscribe,
style: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor)), color: Theme.of(context).accentColor)),
onPressed: () { onPressed: () {
savePodcast(widget.onlinePodcast); savePodcast(widget.onlinePodcast);
setState(() => _issubscribe = true); setState(() => _issubscribe = true);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Podcast subscribed', msg: s.podcastSubscribed,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
}) })
@ -452,7 +437,7 @@ class _SearchResultState extends State<SearchResult>
color: context.accentColor.withOpacity(0.8), color: context.accentColor.withOpacity(0.8),
highlightedBorderColor: Colors.grey[500], highlightedBorderColor: Colors.grey[500],
disabledTextColor: Colors.grey[500], disabledTextColor: Colors.grey[500],
child: Text('Subscribe'), child: Text(s.subscribe),
disabledBorderColor: Colors.grey[500], disabledBorderColor: Colors.grey[500],
onPressed: () {}), onPressed: () {}),
), ),

View File

@ -77,7 +77,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
// color: context.primaryColorDark, // color: context.primaryColorDark,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
'Playlist', context.s.homeMenuPlaylist,
style: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -389,6 +389,7 @@ class _PlayerWidgetState extends State<PlayerWidget> {
Widget _miniPanel(double width, BuildContext context) { Widget _miniPanel(double width, BuildContext context) {
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
final s = context.s;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
@ -459,13 +460,13 @@ class _PlayerWidgetState extends State<PlayerWidget> {
BasicPlaybackState.skippingToNext || BasicPlaybackState.skippingToNext ||
data.item1 == BasicPlaybackState.stopped data.item1 == BasicPlaybackState.stopped
? Text( ? Text(
'Buffering...', s.buffering,
style: TextStyle( style: TextStyle(
color: Theme.of(context).accentColor), color: Theme.of(context).accentColor),
) )
: Text( : Text(
(_stringForSeconds(data.item2) ?? '') + s.timeLeft(
' Left', _stringForSeconds(data.item2) ?? ''),
maxLines: 2, maxLines: 2,
), ),
); );
@ -582,6 +583,7 @@ class _LastPositionState extends State<LastPosition> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final s = context.s;
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
return Selector<AudioPlayerNotifier, EpisodeBrief>( return Selector<AudioPlayerNotifier, EpisodeBrief>(
selector: (_, audio) => audio.episode, selector: (_, audio) => audio.episode,
@ -605,7 +607,7 @@ class _LastPositionState extends State<LastPosition> {
.color), .color),
borderRadius: borderRadius:
BorderRadius.all(Radius.circular(10.0))), BorderRadius.all(Radius.circular(10.0))),
child: Text('Played before')) child: Text(s.listened))
: snapshot.data.seconds < 10 : snapshot.data.seconds < 10
? Center() ? Center()
: Material( : Material(
@ -628,8 +630,9 @@ class _LastPositionState extends State<LastPosition> {
.color), .color),
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(10.0))), Radius.circular(10.0))),
child: Text('Last time ' + child: Text(s.timeLastPlayed(
_stringForSeconds(snapshot.data.seconds)), _stringForSeconds(
snapshot.data.seconds))),
), ),
), ),
) )
@ -851,6 +854,7 @@ class SleepModeState extends State<SleepMode>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final s = context.s;
final ColorTween _colorTween = final ColorTween _colorTween =
ColorTween(begin: context.primaryColor, end: Colors.black); ColorTween(begin: context.primaryColor, end: Colors.black);
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
@ -976,7 +980,7 @@ class SleepModeState extends State<SleepMode>
width: 120, width: 120,
child: Center( child: Center(
child: Text( child: Text(
'End of episode', s.endOfEpisode,
style: TextStyle( style: TextStyle(
// fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
// fontSize: 20, // fontSize: 20,
@ -1059,7 +1063,7 @@ class SleepModeState extends State<SleepMode>
width: 200, width: 200,
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
child: Text('Good Night', child: Text(s.goodNight,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 20, fontSize: 20,
@ -1072,7 +1076,7 @@ class SleepModeState extends State<SleepMode>
width: 200, width: 200,
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
child: Text('Sleep Timer', child: Text(s.sleepTimer,
style: style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
), ),
@ -1223,7 +1227,7 @@ class _ControlPanelState extends State<ControlPanel>
data.audioState == data.audioState ==
BasicPlaybackState BasicPlaybackState
.skippingToNext .skippingToNext
? 'Buffring...' ? context.s.buffering
: '', : '',
style: TextStyle( style: TextStyle(
color: Theme.of(context) color: Theme.of(context)

View File

@ -42,10 +42,6 @@ class Home extends StatefulWidget {
} }
class _HomeState extends State<Home> with SingleTickerProviderStateMixin { class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
final MyHomePageDelegate _delegate = MyHomePageDelegate(
searchFieldLabel: 'Search podcast',
);
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TabController _controller; TabController _controller;
Decoration _getIndicator(BuildContext context) { Decoration _getIndicator(BuildContext context) {
@ -140,8 +136,8 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
featureId: addFeature, featureId: addFeature,
tapTarget: tapTarget:
Icon(Icons.add_circle_outline), Icon(Icons.add_circle_outline),
title: const Text( title:
'Tap to search podcast'), Text(s.featureDiscoverySearch),
backgroundColor: Colors.cyan[600], backgroundColor: Colors.cyan[600],
overflowMode: feature1OverflowMode, overflowMode: feature1OverflowMode,
onDismiss: () { onDismiss: () {
@ -151,13 +147,13 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
const Text( Text(s
'You can search podcast title , key word or RSS link to subscribe new podcast.'), .featureDiscoverySearchDes),
FlatButton( FlatButton(
color: Colors.cyan[500], color: Colors.cyan[500],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Understood', child: Text(s.understood,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -173,7 +169,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
color: Colors.cyan[500], color: Colors.cyan[500],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Dismiss', child: Text(s.dismiss,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -187,13 +183,15 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
], ],
), ),
child: IconButton( child: IconButton(
tooltip: 'Add', tooltip: s.add,
icon: const Icon( icon: const Icon(
Icons.add_circle_outline), Icons.add_circle_outline),
onPressed: () async { onPressed: () async {
await showSearch<int>( await showSearch<int>(
context: context, context: context,
delegate: _delegate, delegate: MyHomePageDelegate(
searchFieldLabel:
s.searchPodcast),
); );
}, },
), ),
@ -213,19 +211,19 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
backgroundColor: Colors.cyan[500], backgroundColor: Colors.cyan[500],
onDismiss: () => onDismiss: () =>
Future.value(true), Future.value(true),
title: const Text( title:
'Tap to import OMPL'), Text(s.featureDiscoveryOMPL),
description: Column( description: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.end, CrossAxisAlignment.end,
children: <Widget>[ children: <Widget>[
const Text( Text(s
'You can import OMPL file, open setting or refresh all podcast at once here.'), .featureDiscoveryOMPLDes),
FlatButton( FlatButton(
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Understood', child: Text(s.understood,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -241,7 +239,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Dismiss', child: Text(s.dismiss,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -270,27 +268,26 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
featureId: groupsFeature, featureId: groupsFeature,
tapTarget: Center( tapTarget: Center(
child: Text( child: Text(
'Podcast View', s.featureDiscoveryPodcast,
textAlign: TextAlign.center, textAlign: TextAlign.center,
)), )),
backgroundColor: Colors.cyan[500], backgroundColor: Colors.cyan[500],
enablePulsingAnimation: false, enablePulsingAnimation: false,
onDismiss: () => Future.value(true), onDismiss: () => Future.value(true),
title: const Text( title:
'Scroll vertically to switch groups'), Text(s.featureDiscoveryPodcastTitle),
description: Column( description: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
const Text( Text(s.featureDiscoveryPodcastDes),
'You can tap See All to add groups or manage podcasts.'),
Row( Row(
children: [ children: [
FlatButton( FlatButton(
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Understood', child: Text(s.understood,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -309,7 +306,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Dismiss', child: Text(s.dismiss,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -365,26 +362,25 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
Key('tab0'), Key('tab0'),
DescribedFeatureOverlay( DescribedFeatureOverlay(
featureId: podcastFeature, featureId: podcastFeature,
tapTarget: Text('Episode View', tapTarget: Text(s.featureDiscoveryEpisode,
textAlign: TextAlign.center), textAlign: TextAlign.center),
backgroundColor: Colors.cyan[500], backgroundColor: Colors.cyan[500],
enablePulsingAnimation: false, enablePulsingAnimation: false,
onDismiss: () => Future.value(true), onDismiss: () => Future.value(true),
title: const Text( title:
'Long tap to play episode instantly'), Text(s.featureDiscoveryEpisodeTitle),
description: Column( description: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
const Text( Text(s.featureDiscoveryEpisodeDes),
'You can long tap to play episode or add episode to playlist.'),
Row( Row(
children: [ children: [
FlatButton( FlatButton(
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Understood', child: Text(s.understood,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -403,7 +399,7 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
color: Colors.cyan[600], color: Colors.cyan[600],
padding: padding:
const EdgeInsets.all(0), const EdgeInsets.all(0),
child: Text('Dismiss', child: Text(s.dismiss,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -457,6 +453,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
@override @override
Widget build( Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) { BuildContext context, double shrinkOffset, bool overlapsContent) {
final s = context.s;
return Container( return Container(
color: Theme.of(context).scaffoldBackgroundColor, color: Theme.of(context).scaffoldBackgroundColor,
child: Column( child: Column(
@ -471,17 +468,16 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
featureId: playlistFeature, featureId: playlistFeature,
tapTarget: Icon(Icons.playlist_play), tapTarget: Icon(Icons.playlist_play),
backgroundColor: Colors.cyan[500], backgroundColor: Colors.cyan[500],
title: const Text('Tap to open playlist'), title: Text(s.featureDiscoveryPlaylist),
onDismiss: () => Future.value(true), onDismiss: () => Future.value(true),
description: Column( description: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
const Text( Text(s.featureDiscoveryPlaylistDes),
'You can add episode to playlist by yourself. Episode will be auto removed from playlist when played.'),
FlatButton( FlatButton(
color: Colors.cyan[600], color: Colors.cyan[600],
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: Text('Understood', child: Text(s.understood,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -492,7 +488,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
FlatButton( FlatButton(
color: Colors.cyan[600], color: Colors.cyan[600],
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: Text('Dismiss', child: Text(s.dismiss,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.button .button
@ -554,7 +550,7 @@ class PlaylistButtonState extends State<PlaylistButton> {
borderRadius: BorderRadius.all(Radius.circular(10))), borderRadius: BorderRadius.all(Radius.circular(10))),
elevation: 1, elevation: 1,
icon: Icon(Icons.playlist_play), icon: Icon(Icons.playlist_play),
tooltip: "Menu", tooltip: s.menu,
itemBuilder: (context) => [ itemBuilder: (context) => [
MyPopupMenuItem( MyPopupMenuItem(
height: 50, height: 50,
@ -749,7 +745,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 10)), padding: EdgeInsets.symmetric(vertical: 10)),
Text( Text(
'No episode received yet', s.noEpisodeRecent,
style: TextStyle(color: Colors.grey[500]), style: TextStyle(color: Colors.grey[500]),
) )
], ],
@ -792,7 +788,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
Radius.circular( Radius.circular(
10))), 10))),
elevation: 1, elevation: 1,
tooltip: 'Groups fliter', tooltip: s.groupFilter,
child: Container( child: Container(
padding: padding:
EdgeInsets.symmetric( EdgeInsets.symmetric(
@ -863,8 +859,8 @@ class _RecentUpdateState extends State<_RecentUpdate>
color: Colors color: Colors
.transparent, .transparent,
child: IconButton( child: IconButton(
tooltip: tooltip: s
'Add new episodes to playlist', .addNewEpisodeTooltip,
icon: icon:
// Icon(Icons.playlist_add), // Icon(Icons.playlist_add),
SizedBox( SizedBox(
@ -886,8 +882,13 @@ class _RecentUpdateState extends State<_RecentUpdate>
.showToast( .showToast(
msg: _groupName == msg: _groupName ==
'All' 'All'
? '${snapshot.data} episode added to playlist' ? s.addNewEpisodeAll(
: '${snapshot.data} episode in $_groupName added to playlist', snapshot
.data)
: s.addEpisodeGroup(
_groupName,
snapshot
.data),
gravity: gravity:
ToastGravity ToastGravity
.BOTTOM, .BOTTOM,
@ -898,8 +899,8 @@ class _RecentUpdateState extends State<_RecentUpdate>
color: Colors color: Colors
.transparent, .transparent,
child: IconButton( child: IconButton(
tooltip: tooltip: s
'Add new episodes to playlist', .addNewEpisodeTooltip,
icon: icon:
// Icon(Icons.playlist_add), // Icon(Icons.playlist_add),
SizedBox( SizedBox(
@ -923,7 +924,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
Material( Material(
color: Colors.transparent, color: Colors.transparent,
child: IconButton( child: IconButton(
tooltip: 'Change layout', tooltip: s.changeLayout,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () { onPressed: () {
if (_layout == Layout.three) if (_layout == Layout.three)
@ -1073,7 +1074,7 @@ class _MyFavoriteState extends State<_MyFavorite>
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 10)), padding: EdgeInsets.symmetric(vertical: 10)),
Text( Text(
'No episode collected yet', s.noEpisodeFavorite,
style: TextStyle(color: Colors.grey[500]), style: TextStyle(color: Colors.grey[500]),
) )
], ],
@ -1103,7 +1104,7 @@ class _MyFavoriteState extends State<_MyFavorite>
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(10))), Radius.circular(10))),
elevation: 1, elevation: 1,
tooltip: 'Sort By', tooltip: s.homeSubMenuSortBy,
child: Container( child: Container(
height: 50, height: 50,
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
@ -1131,11 +1132,11 @@ class _MyFavoriteState extends State<_MyFavorite>
itemBuilder: (context) => [ itemBuilder: (context) => [
PopupMenuItem( PopupMenuItem(
value: 0, value: 0,
child: Text('Update Date'), child: Text(s.updateDate),
), ),
PopupMenuItem( PopupMenuItem(
value: 1, value: 1,
child: Text('Like Date'), child: Text(s.likeDate),
) )
], ],
onSelected: (value) { onSelected: (value) {
@ -1278,7 +1279,7 @@ class _MyDownloadState extends State<_MyDownload>
children: <Widget>[ children: <Widget>[
Container( Container(
padding: EdgeInsets.symmetric(horizontal: 20), padding: EdgeInsets.symmetric(horizontal: 20),
child: Text(s.homeSubMenuDownloaded)), child: Text(s.downloaded)),
Spacer(), Spacer(),
Material( Material(
color: Colors.transparent, color: Colors.transparent,
@ -1349,7 +1350,7 @@ class _MyDownloadState extends State<_MyDownload>
size: 80, color: Colors.grey[500]), size: 80, color: Colors.grey[500]),
Padding(padding: EdgeInsets.symmetric(vertical: 10)), Padding(padding: EdgeInsets.symmetric(vertical: 10)),
Text( Text(
'No episode downloaded yet', s.noEpisodeDownload,
style: TextStyle(color: Colors.grey[500]), style: TextStyle(color: Colors.grey[500]),
) )
], ],

View File

@ -56,6 +56,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width; double _width = MediaQuery.of(context).size.width;
final s = context.s;
return Consumer<GroupList>(builder: (_, groupList, __) { return Consumer<GroupList>(builder: (_, groupList, __) {
var groups = groupList.groups; var groups = groupList.groups;
bool isLoading = groupList.isLoading; bool isLoading = groupList.isLoading;
@ -75,7 +76,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
if (event.primaryVelocity > 200) { if (event.primaryVelocity > 200) {
if (groups.length == 1) { if (groups.length == 1) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Add some groups', msg: s.addSomeGroups,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -89,7 +90,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
} else if (event.primaryVelocity < -200) { } else if (event.primaryVelocity < -200) {
if (groups.length == 1) { if (groups.length == 1) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Add some groups', msg: s.addSomeGroups,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -136,7 +137,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
height: 30, height: 30,
padding: EdgeInsets.all(5.0), padding: EdgeInsets.all(5.0),
child: Text( child: Text(
'See All', s.homeGroupsSeeAll,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.bodyText1 .bodyText1
@ -189,7 +190,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
TextSpan(text: ' to subscribe podcasts') TextSpan(text: ' to subscribe podcasts')
], ],
)) ))
: Text('No podcast in this group', : Text(s.noPodcastGroup,
style: TextStyle( style: TextStyle(
color: context.textTheme.bodyText2.color color: context.textTheme.bodyText2.color
.withOpacity(0.5)))), .withOpacity(0.5)))),
@ -208,7 +209,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
if (event.primaryVelocity > 200) { if (event.primaryVelocity > 200) {
if (groups.length == 1) { if (groups.length == 1) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Add some groups', msg: s.addSomeGroups,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -222,7 +223,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
} else if (event.primaryVelocity < -200) { } else if (event.primaryVelocity < -200) {
if (groups.length == 1) { if (groups.length == 1) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Add some groups', msg: s.addSomeGroups,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -268,7 +269,7 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
height: 30, height: 30,
padding: EdgeInsets.all(5.0), padding: EdgeInsets.all(5.0),
child: Text( child: Text(
'See All', s.homeGroupsSeeAll,
style: Theme.of(context) style: Theme.of(context)
.textTheme .textTheme
.bodyText1 .bodyText1
@ -441,7 +442,7 @@ class PodcastPreview extends StatelessWidget {
selector: (_, audio) => audio.playerRunning, selector: (_, audio) => audio.playerRunning,
builder: (_, playerRunning, __) => IconButton( builder: (_, playerRunning, __) => IconButton(
icon: Icon(Icons.arrow_forward), icon: Icon(Icons.arrow_forward),
tooltip: 'See All', tooltip: context.s.homeGroupsSeeAll,
onPressed: () { onPressed: () {
Navigator.push( Navigator.push(
context, context,
@ -471,19 +472,19 @@ class PodcastPreview extends StatelessWidget {
class ShowEpisode extends StatelessWidget { class ShowEpisode extends StatelessWidget {
final List<EpisodeBrief> episodes; final List<EpisodeBrief> episodes;
final PodcastLocal podcastLocal; final PodcastLocal podcastLocal;
List<int> _menuList = [];
ShowEpisode({Key key, this.episodes, this.podcastLocal}) : super(key: key); ShowEpisode({Key key, this.episodes, this.podcastLocal}) : super(key: key);
String _stringForSeconds(double seconds) { String _stringForSeconds(double seconds) {
if (seconds == null) return null; if (seconds == null) return null;
return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}'; return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
} }
Future<Tuple3<int, bool, bool>> _initData(EpisodeBrief episode) async { Future<Tuple4<int, bool, bool, List<int>>> _initData(
EpisodeBrief episode) async {
int listened = await _isListened(episode); int listened = await _isListened(episode);
bool liked = await _isLiked(episode); bool liked = await _isLiked(episode);
bool downloaded = await _isDownloaded(episode); bool downloaded = await _isDownloaded(episode);
_menuList = await _getEpisodeMenu(); List<int> menuList = await _getEpisodeMenu();
return Tuple3(listened, liked, downloaded); return Tuple4(listened, liked, downloaded, menuList);
} }
Future<int> _isListened(EpisodeBrief episode) async { Future<int> _isListened(EpisodeBrief episode) async {
@ -697,9 +698,9 @@ class ShowEpisode extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double _width = context.width; double _width = context.width;
final s = context.s;
var downloader = Provider.of<DownloadState>(context, listen: false); var downloader = Provider.of<DownloadState>(context, listen: false);
var audio = Provider.of<AudioPlayerNotifier>(context, listen: false); var audio = Provider.of<AudioPlayerNotifier>(context, listen: false);
Offset offset;
return CustomScrollView( return CustomScrollView(
physics: NeverScrollableScrollPhysics(), physics: NeverScrollableScrollPhysics(),
primary: false, primary: false,
@ -727,14 +728,15 @@ class ShowEpisode extends StatelessWidget {
.toList(), .toList(),
), ),
builder: (_, data, __) => FutureBuilder< builder: (_, data, __) => FutureBuilder<
Tuple3<int, bool, bool>>( Tuple4<int, bool, bool, List<int>>>(
future: _initData(episodes[index]), future: _initData(episodes[index]),
initialData: Tuple3(0, false, false), initialData: Tuple4(0, false, false, []),
builder: builder:
(BuildContext context, AsyncSnapshot snapshot) { (BuildContext context, AsyncSnapshot snapshot) {
int isListened = snapshot.data.item1; int isListened = snapshot.data.item1;
bool isLiked = snapshot.data.item2; bool isLiked = snapshot.data.item2;
bool isDownloaded = snapshot.data.item3; bool isDownloaded = snapshot.data.item3;
List<int> menuList = snapshot.data.item4;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: borderRadius:
@ -742,24 +744,7 @@ class ShowEpisode extends StatelessWidget {
color: Theme.of(context).scaffoldBackgroundColor, color: Theme.of(context).scaffoldBackgroundColor,
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: child: FocusedMenuHolder(
// InkWell(
// borderRadius:
// BorderRadius.all(Radius.circular(5.0)),
// onTapDown: (details) => offset = Offset(
// details.globalPosition.dx,
// details.globalPosition.dy),
// onLongPress: () => _showPopupMenu(
// offset,
// episodes[index],
// context,
// data.item1 == episodes[index],
// data.item2.contains(
// episodes[index].enclosureUrl)),
// onTap: () {
//
// },
FocusedMenuHolder(
blurSize: 0.0, blurSize: 0.0,
menuItemExtent: 45, menuItemExtent: 45,
menuBoxDecoration: BoxDecoration( menuBoxDecoration: BoxDecoration(
@ -782,8 +767,8 @@ class ShowEpisode extends StatelessWidget {
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: Text(data.item1 != episodes[index] title: Text(data.item1 != episodes[index]
? "Play" ? s.play
: "Playing"), : s.playing),
trailingIcon: Icon( trailingIcon: Icon(
LineIcons.play_circle_solid, LineIcons.play_circle_solid,
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
@ -792,7 +777,7 @@ class ShowEpisode extends StatelessWidget {
if (data.item1 != episodes[index]) if (data.item1 != episodes[index])
audio.episodeLoad(episodes[index]); audio.episodeLoad(episodes[index]);
}), }),
_menuList.contains(1) menuList.contains(1)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: context.brightness == backgroundColor: context.brightness ==
Brightness.light Brightness.light
@ -800,8 +785,8 @@ class ShowEpisode extends StatelessWidget {
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: data.item2.contains( title: data.item2.contains(
episodes[index].enclosureUrl) episodes[index].enclosureUrl)
? Text("Remove") ? Text(s.remove)
: Text("Later"), : Text(s.later),
trailingIcon: Icon( trailingIcon: Icon(
LineIcons.clock_solid, LineIcons.clock_solid,
color: Colors.cyan, color: Colors.cyan,
@ -812,28 +797,28 @@ class ShowEpisode extends StatelessWidget {
audio audio
.addToPlaylist(episodes[index]); .addToPlaylist(episodes[index]);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Added to playlist', msg: s.toastAddPlaylist,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
audio.delFromPlaylist( audio.delFromPlaylist(
episodes[index]); episodes[index]);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Removed from playlist', msg: s.toastRemovePlaylist,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} }
}) })
: null, : null,
_menuList.contains(2) menuList.contains(2)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: context.brightness == backgroundColor: context.brightness ==
Brightness.light Brightness.light
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: isLiked title: isLiked
? Text("Unlike") ? Text(s.unlike)
: Text("Like"), : Text(s.like),
trailingIcon: Icon(LineIcons.heart, trailingIcon: Icon(LineIcons.heart,
color: Colors.red, size: 21), color: Colors.red, size: 21),
onPressed: () async { onPressed: () async {
@ -842,7 +827,7 @@ class ShowEpisode extends StatelessWidget {
episodes[index].enclosureUrl); episodes[index].enclosureUrl);
audio.setEpisodeState = true; audio.setEpisodeState = true;
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Unliked', msg: s.unliked,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -850,25 +835,25 @@ class ShowEpisode extends StatelessWidget {
episodes[index].enclosureUrl); episodes[index].enclosureUrl);
audio.setEpisodeState = true; audio.setEpisodeState = true;
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Liked', msg: s.liked,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} }
}) })
: null, : null,
_menuList.contains(3) menuList.contains(3)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: context.brightness == backgroundColor: context.brightness ==
Brightness.light Brightness.light
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: isListened > 0 title: isListened > 0
? Text('Listened', ? Text(s.listened,
style: TextStyle( style: TextStyle(
color: context.textColor color: context.textColor
.withOpacity(0.5))) .withOpacity(0.5)))
: Text( : Text(
'Mark Listened', s.markListened,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -886,24 +871,24 @@ class ShowEpisode extends StatelessWidget {
episodes[index]); episodes[index]);
audio.setEpisodeState = true; audio.setEpisodeState = true;
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Mark listened', msg: s.markListened,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} }
}) })
: null, : null,
_menuList.contains(4) menuList.contains(4)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: context.brightness == backgroundColor: context.brightness ==
Brightness.light Brightness.light
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: isDownloaded title: isDownloaded
? Text('Downloaded', ? Text(s.downloaded,
style: TextStyle( style: TextStyle(
color: context.textColor color: context.textColor
.withOpacity(0.5))) .withOpacity(0.5)))
: Text('Download'), : Text(s.download),
trailingIcon: Icon( trailingIcon: Icon(
LineIcons.download_solid, LineIcons.download_solid,
color: Colors.green), color: Colors.green),

View File

@ -56,6 +56,7 @@ class Import extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final s = context.s;
GroupList groupList = Provider.of<GroupList>(context, listen: false); GroupList groupList = Provider.of<GroupList>(context, listen: false);
return Column( return Column(
children: <Widget>[ children: <Widget>[
@ -64,20 +65,21 @@ class Import extends StatelessWidget {
SubscribeItem item = subscribeWorker.currentSubscribeItem; SubscribeItem item = subscribeWorker.currentSubscribeItem;
switch (item.subscribeState) { switch (item.subscribeState) {
case SubscribeState.start: case SubscribeState.start:
return importColumn("Subscribe ${item.title}", context); return importColumn(
s.notificationSubscribe(item.title), context);
case SubscribeState.subscribe: case SubscribeState.subscribe:
return importColumn("Fetch data ${item.title}", context); return importColumn(s.notificaitonFatch(item.title), context);
case SubscribeState.fetch: case SubscribeState.fetch:
groupList.subscribeNewPodcast(item.id); groupList.subscribeNewPodcast(item.id);
// groupList.updatePodcast(item.id); // groupList.updatePodcast(item.id);
return importColumn("Subscribe success ${item.title}", context); return importColumn(s.notificationSuccess(item.title), context);
case SubscribeState.exist: case SubscribeState.exist:
//groupList.subscribeNewPodcast(item.id); //groupList.subscribeNewPodcast(item.id);
return importColumn( return importColumn(
"Subscribe failed, podcast existed ${item.title}", context); s.notificationSubscribeExisted(item.title), context);
case SubscribeState.error: case SubscribeState.error:
return importColumn( return importColumn(
"Subscribe failed, network error ${item.title}", context); s.notificationNetworkError(item.title), context);
default: default:
return Center(); return Center();
} }
@ -92,9 +94,10 @@ class Import extends StatelessWidget {
} }
switch (item.refreshState) { switch (item.refreshState) {
case RefreshState.fetch: case RefreshState.fetch:
return importColumn("Update ${item.title}", context); return importColumn(s.notificationUpdate(item.title), context);
case RefreshState.error: case RefreshState.error:
return importColumn("Update error ${item.title}", context); return importColumn(
s.notificationUpdateError(item.title), context);
default: default:
return Center(); return Center();
} }

View File

@ -1,25 +1,83 @@
{ {
"@@locale": "en", "@@locale": "en",
"add": "Add",
"@add": {
"description": "Subscribe new podcast"
},
"addEpisodeGroup": "{count, plural, zero{} one{{count} episode in {groupName} added to playlist} other{{count} episodes in {groupName} added to playlist}}",
"@addEpisodeGroup": {
"placeholders": {
"groupName": {}
}
},
"addNewEpisodeAll": "{count, plural, zero{} one{{count} episode added to playlist} other{{count} episodes added to playlist}}",
"@addNewEpisodeAll": {},
"addNewEpisodeTooltip": "Add new episodes to playlist",
"@addNewEpisodeTooltip": {},
"addSomeGroups": "Add some groups",
"@addSomeGroups": {
"description": "Please add new groups"
},
"all": "All", "all": "All",
"@all": {}, "@all": {},
"cancel": "Cancel", "back": "Back",
"@back": {},
"buffering": "Buffering",
"@buffering": {},
"cancel": "CANCEL",
"@cancel": {}, "@cancel": {},
"changeLayout": "Change layout",
"@changeLayout": {},
"changelog": "Changelog",
"@changelog": {},
"chooseA": "Choose a", "chooseA": "Choose a",
"@chooseA": {}, "@chooseA": {},
"clear": "Clear",
"@clear": {},
"color": "color", "color": "color",
"@color": {}, "@color": {},
"confirm": "Confirm", "confirm": "CONFIRM",
"@confirm": {}, "@confirm": {},
"darkMode": "Dark mode", "darkMode": "Dark mode",
"@darkMode": {}, "@darkMode": {},
"delete": "Delete", "delete": "Delete",
"@delete": {}, "@delete": {},
"developer": "Developer",
"@developer": {},
"dismiss": "Dismiss",
"@dismiss": {},
"download": "Download", "download": "Download",
"@download": {}, "@download": {},
"downloaded": "Downloaded",
"@downloaded": {},
"editName": "Edit name", "editName": "Edit name",
"@editName": {}, "@editName": {},
"endOfEpisode": "End of Episode", "endOfEpisode": "End of Episode",
"@endOfEpisode": {}, "@endOfEpisode": {},
"featureDiscoveryEpisode": "Episode view",
"@featureDiscoveryEpisode": {},
"featureDiscoveryEpisodeDes": "You can long tap to play episode or add episode to playlist.",
"@featureDiscoveryEpisodeDes": {},
"featureDiscoveryEpisodeTitle": "Long tap to play episode instantly",
"@featureDiscoveryEpisodeTitle": {},
"featureDiscoveryOMPL": "Tap to import OMPL",
"@featureDiscoveryOMPL": {},
"featureDiscoveryOMPLDes": "You can import OMPL file, open setting or refresh all podcast at once here.",
"@featureDiscoveryOMPLDes": {},
"featureDiscoveryPlaylist": "Tap to open playlist",
"@featureDiscoveryPlaylist": {},
"featureDiscoveryPlaylistDes": "You can add episode to playlist by yourself. Episode will be auto removed from playlist when played.",
"@featureDiscoveryPlaylistDes": {},
"featureDiscoveryPodcast": "Podcast view",
"@featureDiscoveryPodcast": {},
"featureDiscoveryPodcastDes": "You can tap See All to add groups or manage podcasts.",
"@featureDiscoveryPodcastDes": {},
"featureDiscoveryPodcastTitle": "Scroll vertically to switch groups",
"@featureDiscoveryPodcastTitle": {},
"featureDiscoverySearch": "Tap to search podcast",
"@featureDiscoverySearch": {},
"featureDiscoverySearchDes": "You can search podcast title , key word or RSS link to subscribe new podcast.",
"@featureDiscoverySearchDes": {},
"feedbackEmail": "Write to me", "feedbackEmail": "Write to me",
"@feedbackEmail": {}, "@feedbackEmail": {},
"feedbackGithub": "Submit issue", "feedbackGithub": "Submit issue",
@ -30,14 +88,16 @@
"@feedbackTelegram": {}, "@feedbackTelegram": {},
"from": "From", "from": "From",
"@from": {}, "@from": {},
"goodNight": "Good Night",
"@goodNight": {},
"groupFilter": "Group filter",
"@groupFilter": {},
"groups": "Groups", "groups": "Groups",
"@groups": {}, "@groups": {},
"homeGroupsSeeAll": "See All", "homeGroupsSeeAll": "See All",
"@homeGroupsSeeAll": {}, "@homeGroupsSeeAll": {},
"homeMenuPlaylist": "Playlist", "homeMenuPlaylist": "Playlist",
"@homeMenuPlaylist": {}, "@homeMenuPlaylist": {},
"homeSubMenuDownloaded": "Downloaded",
"@homeSubMenuDownloaded": {},
"homeSubMenuLikeData": "Like Date", "homeSubMenuLikeData": "Like Date",
"@homeSubMenuLikeData": {}, "@homeSubMenuLikeData": {},
"homeSubMenuSortBy": "Sort by", "homeSubMenuSortBy": "Sort by",
@ -56,6 +116,14 @@
"@homeToprightMenuRefreshAll": {}, "@homeToprightMenuRefreshAll": {},
"homeToprightMenuSettings": "Settings", "homeToprightMenuSettings": "Settings",
"@homeToprightMenuSettings": {}, "@homeToprightMenuSettings": {},
"hostedOn": "Hosted on {host}",
"@hostedOn": {
"placeholders": {
"host": {}
}
},
"hoursCount": "{count, plural, zero{} one{{count} hour} other{{count} hours}}",
"@hoursCount": {},
"later": "Later", "later": "Later",
"@later": {}, "@later": {},
"lightMode": "Light mode", "lightMode": "Light mode",
@ -64,10 +132,18 @@
"@like": {}, "@like": {},
"liked": "Liked", "liked": "Liked",
"@liked": {}, "@liked": {},
"likeDate": "Like date",
"@likeDate": {},
"listen": "Listen", "listen": "Listen",
"@listen": {}, "@listen": {},
"listened": "Listened", "listened": "Listened",
"@listened": {}, "@listened": {},
"loadMore": "Load more",
"@loadMore": {},
"markConfirm": "Mark confirm",
"@markConfirm": {},
"markConfirmContent": "Confirm mark all episodes listened?",
"@markConfirmContent": {},
"markListened": "Mark listened", "markListened": "Mark listened",
"@markListened": {}, "@markListened": {},
"menu": "Menu", "menu": "Menu",
@ -76,18 +152,72 @@
"@menuAllPodcasts": {}, "@menuAllPodcasts": {},
"menuMarkAllListened": "Mark All Listened", "menuMarkAllListened": "Mark All Listened",
"@menuMarkAllListened": {}, "@menuMarkAllListened": {},
"menuMarkListened": "Mark Listened",
"@menuMarkListened": {},
"menuViewRSS": "Visit RSS Feed", "menuViewRSS": "Visit RSS Feed",
"@menuViewRSS": {}, "@menuViewRSS": {},
"menuVisitSite": "Visit Site", "menuVisitSite": "Visit Site",
"@menuVisitSite": {}, "@menuVisitSite": {},
"minsCount": "{count, plural, zero{} one{{count} min} other{{count} mins}}",
"@minsCount": {},
"network": "Network", "network": "Network",
"@network": {}, "@network": {},
"newestFirst": "Newest first",
"@newestFirst": {},
"newGroup": "Create new group", "newGroup": "Create new group",
"@newGroup": {}, "@newGroup": {},
"noEpisodeDownload": "No episode downloaded yet",
"@noEpisodeDownload": {},
"noEpisodeFavorite": "No episode collected yet",
"@noEpisodeFavorite": {},
"noEpisodeRecent": "No episode received yet",
"@noEpisodeRecent": {},
"noPodcastGroup": "No podcast in this group",
"@noPodcastGroup": {},
"notificaitonFatch": "Fetch data {title}",
"@notificaitonFatch": {},
"notificationNetworkError": "Subscribe failed, network error {title}",
"@notificationNetworkError": {
"placeholders": {
"title": {}
}
},
"notificationSubscribe": "Subscribe {title}",
"@notificationSubscribe": {
"placeholders": {
"title": {}
}
},
"notificationSubscribeExisted": "Subscribe failed, podcast existed {title}",
"@notificationSubscribeExisted": {
"placeholders": {
"title": {}
}
},
"notificationSuccess": "Subscribe success {title}",
"@notificationSuccess": {
"placeholders": {
"title": {}
}
},
"notificationUpdate": "Update {title}",
"@notificationUpdate": {
"placeholders": {
"title": {}
}
},
"notificationUpdateError": "Update error {title}",
"@notificationUpdateError": {
"placeholders": {
"title": {}
}
},
"oldestFirst": "Oldest first",
"@oldestFirst": {},
"play": "Play", "play": "Play",
"@play": {}, "@play": {},
"playing": "Playing",
"@playing": {},
"podcastSubscribed": "Podcast subscribed",
"@podcastSubscribed": {},
"popupMenuDownloadDes": "Download episode", "popupMenuDownloadDes": "Download episode",
"@popupMenuDownloadDes": {}, "@popupMenuDownloadDes": {},
"popupMenuLaterDes": "Add episode to playlist", "popupMenuLaterDes": "Add episode to playlist",
@ -98,10 +228,14 @@
"@popupMenuMarkDes": {}, "@popupMenuMarkDes": {},
"popupMenuPlayDes": "Play the episode", "popupMenuPlayDes": "Play the episode",
"@popupMenuPlayDes": {}, "@popupMenuPlayDes": {},
"privacyPolicy": "Privacy Policy",
"@privacyPolicy": {},
"remove": "Remove", "remove": "Remove",
"@remove": {}, "@remove": {},
"schedule": "Schedule", "schedule": "Schedule",
"@schedule": {}, "@schedule": {},
"searchInvalidRss": "Invalid RSS link",
"@searchInvalidRss": {},
"searchPodcast": "Search podcast", "searchPodcast": "Search podcast",
"@searchPodcast": {}, "@searchPodcast": {},
"settingsAccentColor": "Accent color", "settingsAccentColor": "Accent color",
@ -214,12 +348,26 @@
"@settingsUpdateInterval": {}, "@settingsUpdateInterval": {},
"settingsUpdateIntervalDes": "Default 24 hours", "settingsUpdateIntervalDes": "Default 24 hours",
"@settingsUpdateIntervalDes": {}, "@settingsUpdateIntervalDes": {},
"size": "Size",
"@size": {},
"sleepTimer": "Sleep timer", "sleepTimer": "Sleep timer",
"@sleepTimer": {}, "@sleepTimer": {},
"subscribe": "Subscribe", "subscribe": "Subscribe",
"@subscribe": {}, "@subscribe": {},
"systemDefault": "System default", "systemDefault": "System default",
"@systemDefault": {}, "@systemDefault": {},
"timeLastPlayed": "Last time {time}",
"@timeLastPlayed": {
"placeholders": {
"time": {}
}
},
"timeLeft": "{time} Left",
"@timeLeft": {
"placeholders": {
"time": {}
}
},
"to": "To", "to": "To",
"@to": {}, "@to": {},
"toastAddPlaylist": "Added to playlist", "toastAddPlaylist": "Added to playlist",
@ -234,8 +382,22 @@
"@toastReadFile": {}, "@toastReadFile": {},
"toastRemovePlaylist": "Removed from playlist", "toastRemovePlaylist": "Removed from playlist",
"@toastRemovePlaylist": {}, "@toastRemovePlaylist": {},
"understood": "Understood",
"@understood": {},
"unlike": "Unlike", "unlike": "Unlike",
"@unlike": {}, "@unlike": {},
"unliked": "Unliked", "unliked": "Removed from favorite",
"@unliked": {} "@unliked": {},
"updateDate": "Update date",
"@updateDate": {},
"updateEpisodesCount": "{count, plural, zero{No Update} one{Updated {count} Episode} other{Updated {count} Episodes}}",
"@updateEpisodesCount": {},
"updateFailed": "Update failed, network error",
"@updateFailed": {},
"version": "Version : {version}",
"@version": {
"placeholders": {
"version": {}
}
}
} }

View File

@ -1,11 +1,39 @@
{ {
"@@locale": "zh-Hans", "@@locale": "zh-Hans",
"add": "订阅",
"@add": {
"description": "Subscribe new podcast"
},
"addEpisodeGroup": "{count, plural, zero{} other{{group Name}分组{count}集节目添加到播放列表}}",
"@addEpisodeGroup": {
"placeholders": {
"groupName": {}
}
},
"addNewEpisodeAll": "{count, plural, zero{} other{{count}集节目添加到播放列表}}",
"@addNewEpisodeAll": {},
"addNewEpisodeTooltip": "添加更新节目到播放列表",
"@addNewEpisodeTooltip": {},
"addSomeGroups": "请添加分组",
"@addSomeGroups": {
"description": "Please add new groups"
},
"all": "全部", "all": "全部",
"@all": {}, "@all": {},
"back": "返回",
"@back": {},
"buffering": "缓冲",
"@buffering": {},
"cancel": "取消", "cancel": "取消",
"@cancel": {}, "@cancel": {},
"changeLayout": "修改布局",
"@changeLayout": {},
"changelog": "更新日志",
"@changelog": {},
"chooseA": "选择", "chooseA": "选择",
"@chooseA": {}, "@chooseA": {},
"clear": "清除",
"@clear": {},
"color": "颜色", "color": "颜色",
"@color": {}, "@color": {},
"confirm": "确认", "confirm": "确认",
@ -14,12 +42,42 @@
"@darkMode": {}, "@darkMode": {},
"delete": "删除", "delete": "删除",
"@delete": {}, "@delete": {},
"developer": "关于我",
"@developer": {},
"dismiss": "忽略",
"@dismiss": {},
"download": "下载", "download": "下载",
"@download": {}, "@download": {},
"downloaded": "已下载",
"@downloaded": {},
"editName": "修改组名", "editName": "修改组名",
"@editName": {}, "@editName": {},
"endOfEpisode": "节目结束", "endOfEpisode": "节目结束",
"@endOfEpisode": {}, "@endOfEpisode": {},
"featureDiscoveryEpisode": "节目界面",
"@featureDiscoveryEpisode": {},
"featureDiscoveryEpisodeDes": "您可以长按播放节目或者添加节目到播放列表。",
"@featureDiscoveryEpisodeDes": {},
"featureDiscoveryEpisodeTitle": "您可以长按快速播放节目",
"@featureDiscoveryEpisodeTitle": {},
"featureDiscoveryOMPL": "点击导入 OMPL",
"@featureDiscoveryOMPL": {},
"featureDiscoveryOMPLDes": "在这里您可以导入OMPL文件打开设置页面或者刷新所有播客。",
"@featureDiscoveryOMPLDes": {},
"featureDiscoveryPlaylist": "点击打开播放列表",
"@featureDiscoveryPlaylist": {},
"featureDiscoveryPlaylistDes": "您可以添加节目到播放列表,节目在播放后将会从播放列表自动移除。",
"@featureDiscoveryPlaylistDes": {},
"featureDiscoveryPodcast": "播客界面",
"@featureDiscoveryPodcast": {},
"featureDiscoveryPodcastDes": "您可以点击“查看所有”新增或管理分组。",
"@featureDiscoveryPodcastDes": {},
"featureDiscoveryPodcastTitle": "您可以通过上下滑动切换分组",
"@featureDiscoveryPodcastTitle": {},
"featureDiscoverySearch": "点击搜索播客",
"@featureDiscoverySearch": {},
"featureDiscoverySearchDes": "您可以通过搜索播客名称、关键字或者RSS链接订阅播客。",
"@featureDiscoverySearchDes": {},
"feedbackEmail": "发送邮件", "feedbackEmail": "发送邮件",
"@feedbackEmail": {}, "@feedbackEmail": {},
"feedbackGithub": "提交Issue", "feedbackGithub": "提交Issue",
@ -30,14 +88,16 @@
"@feedbackTelegram": {}, "@feedbackTelegram": {},
"from": "自", "from": "自",
"@from": {}, "@from": {},
"goodNight": "晚安",
"@goodNight": {},
"groupFilter": "分组",
"@groupFilter": {},
"groups": "分组", "groups": "分组",
"@groups": {}, "@groups": {},
"homeGroupsSeeAll": "查看全部", "homeGroupsSeeAll": "查看全部",
"@homeGroupsSeeAll": {}, "@homeGroupsSeeAll": {},
"homeMenuPlaylist": "播放列表", "homeMenuPlaylist": "播放列表",
"@homeMenuPlaylist": {}, "@homeMenuPlaylist": {},
"homeSubMenuDownloaded": "已下载",
"@homeSubMenuDownloaded": {},
"homeSubMenuLikeData": "添加日期", "homeSubMenuLikeData": "添加日期",
"@homeSubMenuLikeData": {}, "@homeSubMenuLikeData": {},
"homeSubMenuSortBy": "排序", "homeSubMenuSortBy": "排序",
@ -56,6 +116,14 @@
"@homeToprightMenuRefreshAll": {}, "@homeToprightMenuRefreshAll": {},
"homeToprightMenuSettings": "设置", "homeToprightMenuSettings": "设置",
"@homeToprightMenuSettings": {}, "@homeToprightMenuSettings": {},
"hostedOn": "平台 {host}",
"@hostedOn": {
"placeholders": {
"host": {}
}
},
"hoursCount": "{count, plural, zero{} other{{count} 小时}}",
"@hoursCount": {},
"later": "稍后", "later": "稍后",
"@later": {}, "@later": {},
"lightMode": "明亮模式", "lightMode": "明亮模式",
@ -64,10 +132,18 @@
"@like": {}, "@like": {},
"liked": "已收藏", "liked": "已收藏",
"@liked": {}, "@liked": {},
"likeDate": "收藏日期",
"@likeDate": {},
"listen": "收听", "listen": "收听",
"@listen": {}, "@listen": {},
"listened": "已收听", "listened": "已收听",
"@listened": {}, "@listened": {},
"loadMore": "加载更多",
"@loadMore": {},
"markConfirm": "确认标记",
"@markConfirm": {},
"markConfirmContent": "是否确认标记全部节目为已收听?",
"@markConfirmContent": {},
"markListened": "标记已收听", "markListened": "标记已收听",
"@markListened": {}, "@markListened": {},
"menu": "菜单", "menu": "菜单",
@ -76,18 +152,72 @@
"@menuAllPodcasts": {}, "@menuAllPodcasts": {},
"menuMarkAllListened": "标记所有已收听", "menuMarkAllListened": "标记所有已收听",
"@menuMarkAllListened": {}, "@menuMarkAllListened": {},
"menuMarkListened": "标记已收听",
"@menuMarkListened": {},
"menuViewRSS": "查看 RSS", "menuViewRSS": "查看 RSS",
"@menuViewRSS": {}, "@menuViewRSS": {},
"menuVisitSite": "访问网站", "menuVisitSite": "访问网站",
"@menuVisitSite": {}, "@menuVisitSite": {},
"minsCount": "{count, plural, zero{} other{{count}分钟}}",
"@minsCount": {},
"network": "网络", "network": "网络",
"@network": {}, "@network": {},
"newestFirst": "由新到旧",
"@newestFirst": {},
"newGroup": "创建分组", "newGroup": "创建分组",
"@newGroup": {}, "@newGroup": {},
"noEpisodeDownload": "暂无下载节目",
"@noEpisodeDownload": {},
"noEpisodeFavorite": "暂无收藏节目",
"@noEpisodeFavorite": {},
"noEpisodeRecent": "暂无节目",
"@noEpisodeRecent": {},
"noPodcastGroup": "分组无播客",
"@noPodcastGroup": {},
"notificaitonFatch": "获取数据 {title}",
"@notificaitonFatch": {},
"notificationNetworkError": "订阅失败,网络错误 {title}",
"@notificationNetworkError": {
"placeholders": {
"title": {}
}
},
"notificationSubscribe": "订阅{title}",
"@notificationSubscribe": {
"placeholders": {
"title": {}
}
},
"notificationSubscribeExisted": "订阅失败,播客已存在 {title}",
"@notificationSubscribeExisted": {
"placeholders": {
"title": {}
}
},
"notificationSuccess": "订阅成功 {title}",
"@notificationSuccess": {
"placeholders": {
"title": {}
}
},
"notificationUpdate": "更新 {title}",
"@notificationUpdate": {
"placeholders": {
"title": {}
}
},
"notificationUpdateError": "更新失败 {title}",
"@notificationUpdateError": {
"placeholders": {
"title": {}
}
},
"oldestFirst": "由旧到新",
"@oldestFirst": {},
"play": "播放", "play": "播放",
"@play": {}, "@play": {},
"playing": "正在播放",
"@playing": {},
"podcastSubscribed": "播客已订阅",
"@podcastSubscribed": {},
"popupMenuDownloadDes": "下载节目", "popupMenuDownloadDes": "下载节目",
"@popupMenuDownloadDes": {}, "@popupMenuDownloadDes": {},
"popupMenuLaterDes": "添加到播放列表", "popupMenuLaterDes": "添加到播放列表",
@ -98,10 +228,14 @@
"@popupMenuMarkDes": {}, "@popupMenuMarkDes": {},
"popupMenuPlayDes": "播放节目", "popupMenuPlayDes": "播放节目",
"@popupMenuPlayDes": {}, "@popupMenuPlayDes": {},
"privacyPolicy": "隐私条款",
"@privacyPolicy": {},
"remove": "移除", "remove": "移除",
"@remove": {}, "@remove": {},
"schedule": "定时", "schedule": "定时",
"@schedule": {}, "@schedule": {},
"searchInvalidRss": "RSS 链接错误",
"@searchInvalidRss": {},
"searchPodcast": "搜索播客", "searchPodcast": "搜索播客",
"@searchPodcast": {}, "@searchPodcast": {},
"settingsAccentColor": "次要颜色", "settingsAccentColor": "次要颜色",
@ -214,12 +348,26 @@
"@settingsUpdateInterval": {}, "@settingsUpdateInterval": {},
"settingsUpdateIntervalDes": "默认 24 小时", "settingsUpdateIntervalDes": "默认 24 小时",
"@settingsUpdateIntervalDes": {}, "@settingsUpdateIntervalDes": {},
"size": "大小",
"@size": {},
"sleepTimer": "睡眠模式", "sleepTimer": "睡眠模式",
"@sleepTimer": {}, "@sleepTimer": {},
"subscribe": "订阅", "subscribe": "订阅",
"@subscribe": {}, "@subscribe": {},
"systemDefault": "系统默认", "systemDefault": "系统默认",
"@systemDefault": {}, "@systemDefault": {},
"timeLastPlayed": "上次播放{time}",
"@timeLastPlayed": {
"placeholders": {
"time": {}
}
},
"timeLeft": "剩余 {time}",
"@timeLeft": {
"placeholders": {
"time": {}
}
},
"to": "到", "to": "到",
"@to": {}, "@to": {},
"toastAddPlaylist": "添加到播放列表", "toastAddPlaylist": "添加到播放列表",
@ -234,8 +382,22 @@
"@toastReadFile": {}, "@toastReadFile": {},
"toastRemovePlaylist": "从播放列表移除", "toastRemovePlaylist": "从播放列表移除",
"@toastRemovePlaylist": {}, "@toastRemovePlaylist": {},
"understood": "了解",
"@understood": {},
"unlike": "取消喜欢", "unlike": "取消喜欢",
"@unlike": {}, "@unlike": {},
"unliked": "从收藏移除", "unliked": "从收藏移除",
"@unliked": {} "@unliked": {},
"updateDate": "更新日期",
"@updateDate": {},
"updateEpisodesCount": "{count, plural, zero{未有更新} other{更新 {count} 集节目}}",
"@updateEpisodesCount": {},
"updateFailed": "更新失败",
"@updateFailed": {},
"version": "版本:{version}",
"@version": {
"placeholders": {
"version": {}
}
}
} }

View File

@ -44,7 +44,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
int _episodeCount; int _episodeCount;
Layout _layout; Layout _layout;
bool _scroll; bool _scroll;
Future _updateRssItem(PodcastLocal podcastLocal) async { Future _updateRssItem(BuildContext context, PodcastLocal podcastLocal) async {
var dbHelper = DBHelper(); var dbHelper = DBHelper();
final result = await dbHelper.updatePodcastRss(podcastLocal); final result = await dbHelper.updatePodcastRss(podcastLocal);
if (result == 0) { if (result == 0) {
@ -54,7 +54,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
); );
} else if (result > 0) { } else if (result > 0) {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Updated $result Episodes', msg: context.s.updateEpisodesCount(result),
gravity: ToastGravity.TOP, gravity: ToastGravity.TOP,
); );
@ -85,7 +85,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
} }
} else { } else {
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Update failed, network error', msg: context.s.updateFailed,
gravity: ToastGravity.TOP, gravity: ToastGravity.TOP,
); );
} }
@ -226,15 +226,15 @@ class _PodcastDetailState extends State<PodcastDetail> {
_confirmMarkListened(BuildContext context) => generalDialog( _confirmMarkListened(BuildContext context) => generalDialog(
context, context,
title: Text('Mark confirm'), title: Text(context.s.markConfirm),
content: Text('Confirm mark all episodes listened?'), content: Text(context.s.markConfirmContent),
actions: <Widget>[ actions: <Widget>[
FlatButton( FlatButton(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text( child: Text(
'CANCEL', context.s.cancel,
style: TextStyle(color: Colors.grey[600]), style: TextStyle(color: Colors.grey[600]),
), ),
), ),
@ -244,7 +244,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
await _markListened(widget.podcastLocal.id); await _markListened(widget.podcastLocal.id);
}, },
child: Text( child: Text(
'CONFIRM', context.s.confirm,
style: TextStyle(color: context.accentColor), style: TextStyle(color: context.accentColor),
), ),
) )
@ -293,7 +293,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
key: _refreshIndicatorKey, key: _refreshIndicatorKey,
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
onRefresh: () async { onRefresh: () async {
await _updateRssItem(widget.podcastLocal); await _updateRssItem(context, widget.podcastLocal);
// audio.addNewEpisode(widget.podcastLocal.id); // audio.addNewEpisode(widget.podcastLocal.id);
}, },
child: Stack( child: Stack(
@ -346,7 +346,7 @@ class _PodcastDetailState extends State<PodcastDetail> {
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
Radius.circular(10))), Radius.circular(10))),
elevation: 2, elevation: 2,
tooltip: 'Menu', tooltip: s.menu,
itemBuilder: (context) => [ itemBuilder: (context) => [
widget.podcastLocal.link != null widget.podcastLocal.link != null
? PopupMenuItem( ? PopupMenuItem(
@ -494,10 +494,9 @@ class _PodcastDetailState extends State<PodcastDetail> {
widget.podcastLocal.provider widget.podcastLocal.provider
.isNotEmpty .isNotEmpty
? Text( ? Text(
'Hosted on ' + s.hostedOn(widget
widget .podcastLocal
.podcastLocal .provider),
.provider,
maxLines: 1, maxLines: 1,
style: TextStyle( style: TextStyle(
color: Colors color: Colors
@ -588,12 +587,12 @@ class _PodcastDetailState extends State<PodcastDetail> {
PopupMenuItem( PopupMenuItem(
value: 0, value: 0,
child: child:
Text('Newest first'), Text(s.newestFirst),
), ),
PopupMenuItem( PopupMenuItem(
value: 1, value: 1,
child: child:
Text('Oldest first'), Text(s.oldestFirst),
) )
], ],
onSelected: (value) { onSelected: (value) {

View File

@ -91,7 +91,7 @@ class ThemeSetting extends StatelessWidget {
Navigator.of(context).pop(); Navigator.of(context).pop();
}), }),
RadioListTile( RadioListTile(
title: Text('Dark mode'), title: Text(s.darkMode),
value: ThemeMode.dark, value: ThemeMode.dark,
groupValue: settings.theme, groupValue: settings.theme,
onChanged: (value) { onChanged: (value) {
@ -99,7 +99,7 @@ class ThemeSetting extends StatelessWidget {
Navigator.of(context).pop(); Navigator.of(context).pop();
}), }),
RadioListTile( RadioListTile(
title: Text('Light mode'), title: Text(s.lightMode),
value: ThemeMode.light, value: ThemeMode.light,
groupValue: settings.theme, groupValue: settings.theme,
onChanged: (value) { onChanged: (value) {
@ -140,9 +140,9 @@ class ThemeSetting extends StatelessWidget {
ListTile( ListTile(
onTap: () => generalDialog( onTap: () => generalDialog(
context, context,
title: Text.rich(TextSpan(text: 'Choose a ', children: [ title: Text.rich(TextSpan(text: s.chooseA, children: [
TextSpan( TextSpan(
text: 'color', text: s.color,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: context.accentColor)) color: context.accentColor))

View File

@ -205,7 +205,7 @@ Future<void> subIsolateEntryPoint(SendPort sendPort) async {
print(e); print(e);
} }
} }
int count = await dbHelper.savePodcastRss(p, uuid); await dbHelper.savePodcastRss(p, uuid);
sendPort.send([item.title, item.url, 3, uuid]); sendPort.send([item.title, item.url, 3, uuid]);

View File

@ -46,20 +46,18 @@ class EpisodeGrid extends StatelessWidget {
this.reverse, this.reverse,
}) : super(key: key); }) : super(key: key);
List<int> _menuList = [];
Future<int> _isListened(EpisodeBrief episode) async { Future<int> _isListened(EpisodeBrief episode) async {
DBHelper dbHelper = DBHelper(); DBHelper dbHelper = DBHelper();
_menuList = await _getEpisodeMenu();
return await dbHelper.isListened(episode.enclosureUrl); return await dbHelper.isListened(episode.enclosureUrl);
} }
Future<Tuple3<int, bool, bool>> _initData(EpisodeBrief episode) async { Future<Tuple4<int, bool, bool, List<int>>> _initData(
EpisodeBrief episode) async {
int listened = await _isListened(episode); int listened = await _isListened(episode);
bool liked = await _isLiked(episode); bool liked = await _isLiked(episode);
bool downloaded = await _isDownloaded(episode); bool downloaded = await _isDownloaded(episode);
_menuList = await _getEpisodeMenu(); List<int> menuList = await _getEpisodeMenu();
return Tuple3(listened, liked, downloaded); return Tuple4(listened, liked, downloaded, menuList);
} }
Future<bool> _isLiked(EpisodeBrief episode) async { Future<bool> _isLiked(EpisodeBrief episode) async {
@ -431,13 +429,14 @@ class EpisodeGrid extends StatelessWidget {
builder: (_, data, __) => OpenContainerWrapper( builder: (_, data, __) => OpenContainerWrapper(
episode: episodes[index], episode: episodes[index],
closedBuilder: (context, action, boo) => FutureBuilder< closedBuilder: (context, action, boo) => FutureBuilder<
Tuple3<int, bool, bool>>( Tuple4<int, bool, bool, List<int>>>(
future: _initData(episodes[index]), future: _initData(episodes[index]),
initialData: Tuple3(0, false, false), initialData: Tuple4(0, false, false, []),
builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (BuildContext context, AsyncSnapshot snapshot) {
int isListened = snapshot.data.item1; int isListened = snapshot.data.item1;
bool isLiked = snapshot.data.item2; bool isLiked = snapshot.data.item2;
bool isDownloaded = snapshot.data.item3; bool isDownloaded = snapshot.data.item3;
List<int> menuList = snapshot.data.item4;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: borderRadius:
@ -457,21 +456,6 @@ class EpisodeGrid extends StatelessWidget {
), ),
]), ]),
alignment: Alignment.center, alignment: Alignment.center,
// InkWell(
// borderRadius:
// BorderRadius.all(Radius.circular(5.0)),
// onTapDown: (details) => _offset = Offset(
// details.globalPosition.dx,
// details.globalPosition.dy),
// onLongPress: () => _showPopupMenu(
// _offset,
// episodes[index],
// context,
// isPlaying: data.item1 == episodes[index],
// isInPlaylist: data.item2
// .contains(episodes[index].enclosureUrl),
// ),
// onTap: action,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: borderRadius:
@ -507,7 +491,7 @@ class EpisodeGrid extends StatelessWidget {
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: Text(data.item1 != episodes[index] title: Text(data.item1 != episodes[index]
? s.play ? s.play
: "Playing"), : s.playing),
trailingIcon: Icon( trailingIcon: Icon(
LineIcons.play_circle_solid, LineIcons.play_circle_solid,
color: Theme.of(context).accentColor, color: Theme.of(context).accentColor,
@ -516,7 +500,7 @@ class EpisodeGrid extends StatelessWidget {
if (data.item1 != episodes[index]) if (data.item1 != episodes[index])
audio.episodeLoad(episodes[index]); audio.episodeLoad(episodes[index]);
}), }),
_menuList.contains(1) menuList.contains(1)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: backgroundColor:
context.brightness == Brightness.light context.brightness == Brightness.light
@ -524,7 +508,7 @@ class EpisodeGrid extends StatelessWidget {
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: data.item2.contains( title: data.item2.contains(
episodes[index].enclosureUrl) episodes[index].enclosureUrl)
? Text("Remove") ? Text(s.remove)
: Text(s.later), : Text(s.later),
trailingIcon: Icon( trailingIcon: Icon(
LineIcons.clock_solid, LineIcons.clock_solid,
@ -535,20 +519,20 @@ class EpisodeGrid extends StatelessWidget {
episodes[index].enclosureUrl)) { episodes[index].enclosureUrl)) {
audio.addToPlaylist(episodes[index]); audio.addToPlaylist(episodes[index]);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Added to playlist', msg: s.toastAddPlaylist,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
audio audio
.delFromPlaylist(episodes[index]); .delFromPlaylist(episodes[index]);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Removed from playlist', msg: s.toastRemovePlaylist,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} }
}) })
: null, : null,
_menuList.contains(2) menuList.contains(2)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: backgroundColor:
context.brightness == Brightness.light context.brightness == Brightness.light
@ -565,7 +549,7 @@ class EpisodeGrid extends StatelessWidget {
episodes[index].enclosureUrl); episodes[index].enclosureUrl);
audio.setEpisodeState = true; audio.setEpisodeState = true;
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Unliked', msg: s.unliked,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} else { } else {
@ -573,20 +557,20 @@ class EpisodeGrid extends StatelessWidget {
episodes[index].enclosureUrl); episodes[index].enclosureUrl);
audio.setEpisodeState = true; audio.setEpisodeState = true;
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Liked', msg: s.liked,
gravity: ToastGravity.BOTTOM, gravity: ToastGravity.BOTTOM,
); );
} }
}) })
: null, : null,
_menuList.contains(3) menuList.contains(3)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: backgroundColor:
context.brightness == Brightness.light context.brightness == Brightness.light
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: isListened > 0 title: isListened > 0
? Text('Listened', ? Text(s.listened,
style: TextStyle( style: TextStyle(
color: context.textColor color: context.textColor
.withOpacity(0.5))) .withOpacity(0.5)))
@ -614,14 +598,14 @@ class EpisodeGrid extends StatelessWidget {
} }
}) })
: null, : null,
_menuList.contains(4) menuList.contains(4)
? FocusedMenuItem( ? FocusedMenuItem(
backgroundColor: backgroundColor:
context.brightness == Brightness.light context.brightness == Brightness.light
? context.primaryColor ? context.primaryColor
: context.scaffoldBackgroundColor, : context.scaffoldBackgroundColor,
title: isDownloaded title: isDownloaded
? Text(s.homeSubMenuDownloaded, ? Text(s.downloaded,
style: TextStyle( style: TextStyle(
color: context.textColor color: context.textColor
.withOpacity(0.5))) .withOpacity(0.5)))