diff --git a/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_18.png b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_18.png new file mode 100644 index 0000000..c441952 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_18.png differ diff --git a/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_24.png b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_24.png new file mode 100644 index 0000000..cc656ac Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_24.png differ diff --git a/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_36.png b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_36.png new file mode 100644 index 0000000..ce73fbe Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_36.png differ diff --git a/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_48.png b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_48.png new file mode 100644 index 0000000..8c26c20 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/baseline_fast_rewind_white_48.png differ diff --git a/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_18.png b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_18.png new file mode 100644 index 0000000..2ec4a0b Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_18.png differ diff --git a/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_24.png b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_24.png new file mode 100644 index 0000000..7e28f28 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_24.png differ diff --git a/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_36.png b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_36.png new file mode 100644 index 0000000..cc656ac Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_36.png differ diff --git a/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_48.png b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_48.png new file mode 100644 index 0000000..710b3c8 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/baseline_fast_rewind_white_48.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_18.png b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_18.png new file mode 100644 index 0000000..cc656ac Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_18.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_24.png b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_24.png new file mode 100644 index 0000000..710b3c8 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_24.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_36.png b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_36.png new file mode 100644 index 0000000..8c26c20 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_36.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_48.png b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_48.png new file mode 100644 index 0000000..c1765b4 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/baseline_fast_rewind_white_48.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_18.png b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_18.png new file mode 100644 index 0000000..ce73fbe Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_18.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_24.png b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_24.png new file mode 100644 index 0000000..8c26c20 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_24.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_36.png b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_36.png new file mode 100644 index 0000000..504036d Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_36.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_48.png b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_48.png new file mode 100644 index 0000000..b3d3e2a Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/baseline_fast_rewind_white_48.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_18.png b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_18.png new file mode 100644 index 0000000..8c26c20 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_18.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_24.png b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_24.png new file mode 100644 index 0000000..c1765b4 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_24.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_36.png b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_36.png new file mode 100644 index 0000000..b3d3e2a Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_36.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_48.png b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_48.png new file mode 100644 index 0000000..c0d059a Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/baseline_fast_rewind_white_48.png differ diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 3eb792e..c4382ac 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -110,6 +110,8 @@ class MessageLookup extends MessageLookupByLibrary { "editGroupName" : MessageLookupByLibrary.simpleMessage("Edit group name"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("End of Episode"), "episode" : m4, + "fastForward" : MessageLookupByLibrary.simpleMessage("Fast forward"), + "fastRewind" : MessageLookupByLibrary.simpleMessage("Fast rewind"), "featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("Tap to edit group"), "featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("You can change group name or delete it here, but the home group can not be edited or deleted"), "featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("Episode view"), @@ -140,6 +142,7 @@ class MessageLookup extends MessageLookupByLibrary { "groupFilter" : MessageLookupByLibrary.simpleMessage("Group filter"), "groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("Are you sure you want to delete this group? Podcasts will be moved to the Home group."), "groups" : m6, + "hideListenedSetting" : MessageLookupByLibrary.simpleMessage("Hide listened"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("See All"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Playlist"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Sort by"), @@ -186,12 +189,14 @@ class MessageLookup extends MessageLookupByLibrary { "noShownote" : MessageLookupByLibrary.simpleMessage("No show notes available for this episode."), "notificaitonFatch" : m12, "notificationNetworkError" : m13, + "notificationSetting" : MessageLookupByLibrary.simpleMessage("Notification panel"), "notificationSubscribe" : m14, "notificationSubscribeExisted" : m15, "notificationSuccess" : m16, "notificationUpdate" : m17, "notificationUpdateError" : m18, "oldestFirst" : MessageLookupByLibrary.simpleMessage("Oldest first"), + "pause" : MessageLookupByLibrary.simpleMessage("Pause"), "play" : MessageLookupByLibrary.simpleMessage("Play"), "playback" : MessageLookupByLibrary.simpleMessage("Playback control"), "player" : MessageLookupByLibrary.simpleMessage("Player"), @@ -300,7 +305,9 @@ class MessageLookup extends MessageLookupByLibrary { "size" : MessageLookupByLibrary.simpleMessage("Size"), "skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Skip seconds at start"), "skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"), + "skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("Sleep timer"), + "stop" : MessageLookupByLibrary.simpleMessage("Stop"), "subscribe" : MessageLookupByLibrary.simpleMessage("Subscribe"), "subscribeExportDes" : MessageLookupByLibrary.simpleMessage("Export OMPL file of all podcasts"), "systemDefault" : MessageLookupByLibrary.simpleMessage("System default"), diff --git a/lib/generated/intl/messages_es.dart b/lib/generated/intl/messages_es.dart index 40cea77..95a8f5a 100644 --- a/lib/generated/intl/messages_es.dart +++ b/lib/generated/intl/messages_es.dart @@ -110,6 +110,8 @@ class MessageLookup extends MessageLookupByLibrary { "editGroupName" : MessageLookupByLibrary.simpleMessage("Editar nombre del grupo"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("Fin del episodio"), "episode" : m4, + "fastForward" : MessageLookupByLibrary.simpleMessage("Fast forward"), + "fastRewind" : MessageLookupByLibrary.simpleMessage("Fast rewind"), "featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("Toca para editar grupo"), "featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("Puedes cambiar el nombre del grupo o eliminar el grupo aquí, el grupo Home no puede ser editado ni borrado"), "featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("Vista de episodios"), @@ -140,6 +142,7 @@ class MessageLookup extends MessageLookupByLibrary { "groupFilter" : MessageLookupByLibrary.simpleMessage("Filtro de grupo"), "groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("¿Estas seguro de que quieres remover este grupo? Los podcasts serán movidos al grupo Home"), "groups" : m6, + "hideListenedSetting" : MessageLookupByLibrary.simpleMessage("Hide listened"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("Ver todo"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Lista de reproducción"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Ordenar por"), @@ -186,12 +189,14 @@ class MessageLookup extends MessageLookupByLibrary { "noShownote" : MessageLookupByLibrary.simpleMessage("Aun no hay notas disponibles para este episodio"), "notificaitonFatch" : m12, "notificationNetworkError" : m13, + "notificationSetting" : MessageLookupByLibrary.simpleMessage("Notification panel"), "notificationSubscribe" : m14, "notificationSubscribeExisted" : m15, "notificationSuccess" : m16, "notificationUpdate" : m17, "notificationUpdateError" : m18, "oldestFirst" : MessageLookupByLibrary.simpleMessage("Mas antiguos primero"), + "pause" : MessageLookupByLibrary.simpleMessage("Pause"), "play" : MessageLookupByLibrary.simpleMessage("Reproducir"), "playback" : MessageLookupByLibrary.simpleMessage("Control de reproducción"), "player" : MessageLookupByLibrary.simpleMessage("Reproductor"), @@ -300,7 +305,9 @@ class MessageLookup extends MessageLookupByLibrary { "size" : MessageLookupByLibrary.simpleMessage("Tamaño"), "skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Saltar segundos al inicio"), "skipSilence" : MessageLookupByLibrary.simpleMessage("Saltar silencios"), + "skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("Temporizador de sueño"), + "stop" : MessageLookupByLibrary.simpleMessage("Stop"), "subscribe" : MessageLookupByLibrary.simpleMessage("Suscribir"), "subscribeExportDes" : MessageLookupByLibrary.simpleMessage("Exportar OPML de todos los podcasts"), "systemDefault" : MessageLookupByLibrary.simpleMessage("Acorde al sistema"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 1f8f9b7..bea2fa1 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -47,7 +47,7 @@ class MessageLookup extends MessageLookupByLibrary { static m13(title) => "Échec de l’abonnement, erreur réseau ${title} "; - static m14(title) => "S\'abonner"; + static m14(title) => "Abonnement en cours"; static m15(title) => "Échec de l’abonnement, le podcast existe déjà ${title}"; @@ -85,9 +85,9 @@ class MessageLookup extends MessageLookupByLibrary { "addNewEpisodeTooltip" : MessageLookupByLibrary.simpleMessage("Ajouter de nouveaux épisodes à la playlist."), "addSomeGroups" : MessageLookupByLibrary.simpleMessage("Ajouter des groupes"), "all" : MessageLookupByLibrary.simpleMessage("Tout"), - "autoDownload" : MessageLookupByLibrary.simpleMessage("Téléchargements auto"), + "autoDownload" : MessageLookupByLibrary.simpleMessage("Automatisation"), "back" : MessageLookupByLibrary.simpleMessage("Retour"), - "boostVolume" : MessageLookupByLibrary.simpleMessage("Boost volume"), + "boostVolume" : MessageLookupByLibrary.simpleMessage("Booster le volume"), "buffering" : MessageLookupByLibrary.simpleMessage("Buffering"), "cancel" : MessageLookupByLibrary.simpleMessage("ANNULER"), "cellularConfirm" : MessageLookupByLibrary.simpleMessage("Avertissement utilisation des données mobiles"), @@ -103,31 +103,33 @@ class MessageLookup extends MessageLookupByLibrary { "daysCount" : m3, "delete" : MessageLookupByLibrary.simpleMessage("Effacer"), "developer" : MessageLookupByLibrary.simpleMessage("Développeur"), - "dismiss" : MessageLookupByLibrary.simpleMessage("Rejeter"), + "dismiss" : MessageLookupByLibrary.simpleMessage("Passer"), "done" : MessageLookupByLibrary.simpleMessage("Fait"), "download" : MessageLookupByLibrary.simpleMessage("Téléchargés"), "downloaded" : MessageLookupByLibrary.simpleMessage("Téléchargés"), "editGroupName" : MessageLookupByLibrary.simpleMessage("Modifier le nom du groupe"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("Fin de l\'épisode"), "episode" : m4, - "featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("Appuyez pour éditer le groupe"), - "featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez supprimer ou modifier le nom du groupe, le groupe Home ne peut être modifié ni supprimé."), + "fastForward" : MessageLookupByLibrary.simpleMessage("Fast forward"), + "fastRewind" : MessageLookupByLibrary.simpleMessage("Fast rewind"), + "featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("Gestion des groupes"), + "featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("Ici vous pouvez supprimer ou modifier le nom des groupes, seul le groupe Home ne peut être édité."), "featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("Vue épisode"), "featureDiscoveryEpisodeDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez effectuer un appui long pour jouer un épisode ou l\'ajouter à la playlist."), - "featureDiscoveryEpisodeTitle" : MessageLookupByLibrary.simpleMessage("Effectuez un appui long pour jouer un épisode immédiatement"), - "featureDiscoveryGroup" : MessageLookupByLibrary.simpleMessage("Appuyez pour ajouter un groupe."), + "featureDiscoveryEpisodeTitle" : MessageLookupByLibrary.simpleMessage("Effectuez un appui long pour lancer un épisode"), + "featureDiscoveryGroup" : MessageLookupByLibrary.simpleMessage("Appuyez ici pour créer un groupe"), "featureDiscoveryGroupDes" : MessageLookupByLibrary.simpleMessage("Pour les nouveaux podcasts le groupe par défaut est Home. Vous pouvez créer de nouveaux groupes et y déplacer vos podcasts. Un podcast peut être associé à plusieurs groupes."), - "featureDiscoveryGroupPodcast" : MessageLookupByLibrary.simpleMessage("Un appui long pour classer les podcasts"), - "featureDiscoveryGroupPodcastDes" : MessageLookupByLibrary.simpleMessage("Appuyez pour accéder à plus d\'options, un appui long permet de classer les podcasts du groupe."), - "featureDiscoveryOMPL" : MessageLookupByLibrary.simpleMessage("Appuyez pour importer un fichier OPML"), + "featureDiscoveryGroupPodcast" : MessageLookupByLibrary.simpleMessage("Classement des podcasts"), + "featureDiscoveryGroupPodcastDes" : MessageLookupByLibrary.simpleMessage("Appuyez ici pour accéder à plus d\'options, un appui long permet de classer les podcasts d\'un groupe."), + "featureDiscoveryOMPL" : MessageLookupByLibrary.simpleMessage("Appuyez ici pour importer un fichier OPML"), "featureDiscoveryOMPLDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez importer un fichier OPML, accéder aux paramètres ou actualiser tous les podcasts."), - "featureDiscoveryPlaylist" : MessageLookupByLibrary.simpleMessage("Appuyez pour ouvrir la playlist"), - "featureDiscoveryPlaylistDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez ajouter des épisodes dans la playlist. Ils seront automatiquement retirés l\'écoute finie."), + "featureDiscoveryPlaylist" : MessageLookupByLibrary.simpleMessage("Appuyez ici pour ouvrir la playlist"), + "featureDiscoveryPlaylistDes" : MessageLookupByLibrary.simpleMessage("Ajoutez des épisodes dans la playlist. Ils seront automatiquement retirés une fois écoutés."), "featureDiscoveryPodcast" : MessageLookupByLibrary.simpleMessage("Vue podcasts"), - "featureDiscoveryPodcastDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez appuyer sur Tout Voir pour ajouter des groupes ou gérer les podcasts."), + "featureDiscoveryPodcastDes" : MessageLookupByLibrary.simpleMessage("Appuyez sur Tout Voir pour ajouter des groupes et gérer les podcasts."), "featureDiscoveryPodcastTitle" : MessageLookupByLibrary.simpleMessage("Effectuez un défilement vertical pour changer de groupe."), - "featureDiscoverySearch" : MessageLookupByLibrary.simpleMessage("Appuyez pour chercher un podcast"), - "featureDiscoverySearchDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez effectuer une recherche par titre, mots clés ou lien RSS pour vous abonner à un nouveau podcast."), + "featureDiscoverySearch" : MessageLookupByLibrary.simpleMessage("Appuyez ici pour rechercher un podcast"), + "featureDiscoverySearchDes" : MessageLookupByLibrary.simpleMessage("Pour trouver vos podcasts vous pouvez effectuer une recherche par titres, mots clés ou liens RSS."), "feedbackEmail" : MessageLookupByLibrary.simpleMessage("Contact"), "feedbackGithub" : MessageLookupByLibrary.simpleMessage("GitHub"), "feedbackPlay" : MessageLookupByLibrary.simpleMessage("PlayStore"), @@ -140,21 +142,22 @@ class MessageLookup extends MessageLookupByLibrary { "groupFilter" : MessageLookupByLibrary.simpleMessage("Filtrer par groupe"), "groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("Êtes-vous sûr de vouloir supprimer ce groupe ? Les podcasts seront déplacés vers le groupe Home."), "groups" : m6, + "hideListenedSetting" : MessageLookupByLibrary.simpleMessage("Hide listened"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("Tout Voir"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("Playlist"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("Classé par"), "homeTabMenuFavotite" : MessageLookupByLibrary.simpleMessage("Favoris"), "homeTabMenuRecent" : MessageLookupByLibrary.simpleMessage("Récents"), "homeToprightMenuAbout" : MessageLookupByLibrary.simpleMessage("À propos"), - "homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("Importer le fichier OPML"), + "homeToprightMenuImportOMPL" : MessageLookupByLibrary.simpleMessage("Importer un fichier OPML"), "homeToprightMenuRefreshAll" : MessageLookupByLibrary.simpleMessage("Tout actualiser"), "hostedOn" : m7, "hoursAgo" : m8, "hoursCount" : m9, "import" : MessageLookupByLibrary.simpleMessage("Importer"), - "introFourthPage" : MessageLookupByLibrary.simpleMessage("Vous pouvez effectuer un appui long sur un épisode pour accéder aux actions rapides."), - "introSecondPage" : MessageLookupByLibrary.simpleMessage("Souscrivez aux podcasts via la section recherche ou importez un fichier OPML."), - "introThirdPage" : MessageLookupByLibrary.simpleMessage("Vous pouvez créer un nouveau groupe de podcasts."), + "introFourthPage" : MessageLookupByLibrary.simpleMessage("Un appui long sur un épisode lance les actions rapides."), + "introSecondPage" : MessageLookupByLibrary.simpleMessage("S\'abonner aux podcasts via la section recherche ou un fichier OPML."), + "introThirdPage" : MessageLookupByLibrary.simpleMessage("Vous pouvez créer des groupes de podcasts."), "later" : MessageLookupByLibrary.simpleMessage("Plus tard"), "lightMode" : MessageLookupByLibrary.simpleMessage("Mode clair"), "like" : MessageLookupByLibrary.simpleMessage("Like"), @@ -166,7 +169,7 @@ class MessageLookup extends MessageLookupByLibrary { "mark" : MessageLookupByLibrary.simpleMessage("✓"), "markConfirm" : MessageLookupByLibrary.simpleMessage("Marquage effectué"), "markConfirmContent" : MessageLookupByLibrary.simpleMessage("Marquer tous les épisodes comme lus ?"), - "markListened" : MessageLookupByLibrary.simpleMessage("Marquer comme lu"), + "markListened" : MessageLookupByLibrary.simpleMessage("Marquage"), "markNotListened" : MessageLookupByLibrary.simpleMessage("Mark not listened"), "menu" : MessageLookupByLibrary.simpleMessage("Menu"), "menuAllPodcasts" : MessageLookupByLibrary.simpleMessage("Tous les podcasts"), @@ -181,32 +184,34 @@ class MessageLookup extends MessageLookupByLibrary { "next" : MessageLookupByLibrary.simpleMessage("Suivant"), "noEpisodeDownload" : MessageLookupByLibrary.simpleMessage("Aucun épisode téléchargé."), "noEpisodeFavorite" : MessageLookupByLibrary.simpleMessage("Aucun épisode ajouté."), - "noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("Aucun épisode récupéré."), + "noEpisodeRecent" : MessageLookupByLibrary.simpleMessage("Aucun épisode récent."), "noPodcastGroup" : MessageLookupByLibrary.simpleMessage("Ce groupe ne contient aucun podcast"), "noShownote" : MessageLookupByLibrary.simpleMessage("Notes de l\'épisode manquantes."), "notificaitonFatch" : m12, "notificationNetworkError" : m13, + "notificationSetting" : MessageLookupByLibrary.simpleMessage("Notification panel"), "notificationSubscribe" : m14, "notificationSubscribeExisted" : m15, "notificationSuccess" : m16, "notificationUpdate" : m17, "notificationUpdateError" : m18, "oldestFirst" : MessageLookupByLibrary.simpleMessage("Le plus ancien en premier"), + "pause" : MessageLookupByLibrary.simpleMessage("Pause"), "play" : MessageLookupByLibrary.simpleMessage("Lecture"), "playback" : MessageLookupByLibrary.simpleMessage("Commandes du lecteur"), "player" : MessageLookupByLibrary.simpleMessage("Player"), - "playerHeightMed" : MessageLookupByLibrary.simpleMessage("Medium"), - "playerHeightShort" : MessageLookupByLibrary.simpleMessage("Low"), - "playerHeightTall" : MessageLookupByLibrary.simpleMessage("High"), + "playerHeightMed" : MessageLookupByLibrary.simpleMessage("Moyen"), + "playerHeightShort" : MessageLookupByLibrary.simpleMessage("Petit"), + "playerHeightTall" : MessageLookupByLibrary.simpleMessage("Grand"), "playing" : MessageLookupByLibrary.simpleMessage("En cours"), "plugins" : MessageLookupByLibrary.simpleMessage("Plugins"), "podcast" : m19, - "podcastSubscribed" : MessageLookupByLibrary.simpleMessage("Abonnements"), + "podcastSubscribed" : MessageLookupByLibrary.simpleMessage("Abonné au podcast"), "popupMenuDownloadDes" : MessageLookupByLibrary.simpleMessage("Télécharger l\'épisode"), - "popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("Ajouter l\'épisode à la playlist"), + "popupMenuLaterDes" : MessageLookupByLibrary.simpleMessage("Ajouter à la playlist"), "popupMenuLikeDes" : MessageLookupByLibrary.simpleMessage("Ajouter l\'épisode aux favoris"), "popupMenuMarkDes" : MessageLookupByLibrary.simpleMessage("Marquer l\'épisode comme lu"), - "popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("Jouer l\'épisode"), + "popupMenuPlayDes" : MessageLookupByLibrary.simpleMessage("Lancer l\'épisode"), "privacyPolicy" : MessageLookupByLibrary.simpleMessage("Gestion des données"), "published" : m20, "publishedDaily" : MessageLookupByLibrary.simpleMessage("Quotidien"), @@ -231,7 +236,7 @@ class MessageLookup extends MessageLookupByLibrary { "settings" : MessageLookupByLibrary.simpleMessage("Paramètres"), "settingsAccentColor" : MessageLookupByLibrary.simpleMessage("Couleur principale"), "settingsAccentColorDes" : MessageLookupByLibrary.simpleMessage("Sélection de la couleur du thème"), - "settingsAppIntro" : MessageLookupByLibrary.simpleMessage("App intro"), + "settingsAppIntro" : MessageLookupByLibrary.simpleMessage("Revoir l\'introduction"), "settingsAppearance" : MessageLookupByLibrary.simpleMessage("Apparence"), "settingsAppearanceDes" : MessageLookupByLibrary.simpleMessage("Couleurs et thèmes"), "settingsAudioCache" : MessageLookupByLibrary.simpleMessage("Cache audio"), @@ -241,25 +246,25 @@ class MessageLookup extends MessageLookupByLibrary { "settingsAutoPlayDes" : MessageLookupByLibrary.simpleMessage("Lancer automatiquement l\'épisode suivant"), "settingsBackup" : MessageLookupByLibrary.simpleMessage("Backup"), "settingsBackupDes" : MessageLookupByLibrary.simpleMessage("Sauvegarde des données de l\'application"), - "settingsBoostVolume" : MessageLookupByLibrary.simpleMessage("Volume boost level"), - "settingsBoostVolumeDes" : MessageLookupByLibrary.simpleMessage("Change volume boost level"), + "settingsBoostVolume" : MessageLookupByLibrary.simpleMessage("Booster le volume"), + "settingsBoostVolumeDes" : MessageLookupByLibrary.simpleMessage("Définir la puissance du volume"), "settingsDefaultGrid" : MessageLookupByLibrary.simpleMessage("Vue par défaut"), "settingsDefaultGridDownload" : MessageLookupByLibrary.simpleMessage("Onglet Téléchargés"), "settingsDefaultGridFavorite" : MessageLookupByLibrary.simpleMessage("Onglet Favoris"), - "settingsDefaultGridPodcast" : MessageLookupByLibrary.simpleMessage("Page du podcast"), + "settingsDefaultGridPodcast" : MessageLookupByLibrary.simpleMessage("Onglet podcasts"), "settingsDefaultGridRecent" : MessageLookupByLibrary.simpleMessage("Onglet Récents"), "settingsDiscovery" : MessageLookupByLibrary.simpleMessage("Revoir le tutoriel"), "settingsEnableSyncing" : MessageLookupByLibrary.simpleMessage("Activer la synchronisation"), "settingsEnableSyncingDes" : MessageLookupByLibrary.simpleMessage("Actualiser tous les podcasts en arrière-plan pour toujours afficher les derniers épisodes"), "settingsExportDes" : MessageLookupByLibrary.simpleMessage("Exporter et importer les paramètres de l\'application."), "settingsFastForwardSec" : MessageLookupByLibrary.simpleMessage("Avance rapide"), - "settingsFastForwardSecDes" : MessageLookupByLibrary.simpleMessage("Saut avant en secondes"), + "settingsFastForwardSecDes" : MessageLookupByLibrary.simpleMessage("Saut avant"), "settingsFeedback" : MessageLookupByLibrary.simpleMessage("Feedback"), "settingsFeedbackDes" : MessageLookupByLibrary.simpleMessage("Report de bug et demande d\'ajout de fonction"), "settingsHistory" : MessageLookupByLibrary.simpleMessage("Historique"), "settingsHistoryDes" : MessageLookupByLibrary.simpleMessage("Gestion des données"), - "settingsInfo" : MessageLookupByLibrary.simpleMessage("Infos"), - "settingsInterface" : MessageLookupByLibrary.simpleMessage("Interface"), + "settingsInfo" : MessageLookupByLibrary.simpleMessage("Informations"), + "settingsInterface" : MessageLookupByLibrary.simpleMessage("Interface utilisateur"), "settingsLanguages" : MessageLookupByLibrary.simpleMessage("Langues"), "settingsLanguagesDes" : MessageLookupByLibrary.simpleMessage("Sélection de la langue"), "settingsLayout" : MessageLookupByLibrary.simpleMessage("Style"), @@ -267,47 +272,49 @@ class MessageLookup extends MessageLookupByLibrary { "settingsLibraries" : MessageLookupByLibrary.simpleMessage("Librairies"), "settingsLibrariesDes" : MessageLookupByLibrary.simpleMessage("Librairies opensource utilisées"), "settingsManageDownload" : MessageLookupByLibrary.simpleMessage("Gérer les téléchargements"), - "settingsManageDownloadDes" : MessageLookupByLibrary.simpleMessage("Gérer les fichiers audio téléchargés"), + "settingsManageDownloadDes" : MessageLookupByLibrary.simpleMessage("Gestion des fichiers audio téléchargés"), "settingsMenuAutoPlay" : MessageLookupByLibrary.simpleMessage("Lecture automatique"), "settingsNetworkCellular" : MessageLookupByLibrary.simpleMessage("Utilisation du réseau mobile"), "settingsNetworkCellularAuto" : MessageLookupByLibrary.simpleMessage("Téléchargement automatique sur réseau mobile"), - "settingsNetworkCellularAutoDes" : MessageLookupByLibrary.simpleMessage("Vous pouvez automatiser le téléchargement des podcasts sur la page de gestion des groupes."), - "settingsNetworkCellularDes" : MessageLookupByLibrary.simpleMessage("Si connecté à un réseau mobile, demander une confirmation avant de télécharger."), + "settingsNetworkCellularAutoDes" : MessageLookupByLibrary.simpleMessage("L\'automatisation du téléchargement peut aussi être configurée sur page de gestion des groupes"), + "settingsNetworkCellularDes" : MessageLookupByLibrary.simpleMessage("Demander une confirmation avant de lancer un téléchargement"), "settingsPlayDes" : MessageLookupByLibrary.simpleMessage("Playlist et lecteur"), - "settingsPlayerHeight" : MessageLookupByLibrary.simpleMessage("Player height"), - "settingsPlayerHeightDes" : MessageLookupByLibrary.simpleMessage("Change player widget height as you like"), + "settingsPlayerHeight" : MessageLookupByLibrary.simpleMessage("Taille du player"), + "settingsPlayerHeightDes" : MessageLookupByLibrary.simpleMessage("Changer la hauteur du widget"), "settingsPopupMenu" : MessageLookupByLibrary.simpleMessage("Menu popup des épisodes"), "settingsPopupMenuDes" : MessageLookupByLibrary.simpleMessage("Configuration du menu popup"), "settingsPrefrence" : MessageLookupByLibrary.simpleMessage("Préférences"), "settingsRealDark" : MessageLookupByLibrary.simpleMessage("Noir profond"), - "settingsRealDarkDes" : MessageLookupByLibrary.simpleMessage("Activer pour un mode sombre accentué"), + "settingsRealDarkDes" : MessageLookupByLibrary.simpleMessage("Mode sombre accentué"), "settingsRewindSec" : MessageLookupByLibrary.simpleMessage("Retour rapide"), - "settingsRewindSecDes" : MessageLookupByLibrary.simpleMessage("Saut arrière en secondes"), + "settingsRewindSecDes" : MessageLookupByLibrary.simpleMessage("Saut arrière"), "settingsSTAuto" : MessageLookupByLibrary.simpleMessage("Activation automatique de la minuterie"), "settingsSTAutoDes" : MessageLookupByLibrary.simpleMessage("Démarrer la minuterie à l\'horaire programmé"), - "settingsSTDefaultTime" : MessageLookupByLibrary.simpleMessage("Temps par défaut"), + "settingsSTDefaultTime" : MessageLookupByLibrary.simpleMessage("Durée par défaut"), "settingsSTDefautTimeDes" : MessageLookupByLibrary.simpleMessage("Configuration de la minuterie"), "settingsSTMode" : MessageLookupByLibrary.simpleMessage("Mode minuterie automatique"), "settingsStorageDes" : MessageLookupByLibrary.simpleMessage("Gestion du cache et de l\'espace de stockage"), "settingsSyncing" : MessageLookupByLibrary.simpleMessage("Synchronisation"), "settingsSyncingDes" : MessageLookupByLibrary.simpleMessage("Actualisation des podcasts en arrière-plan"), - "settingsTapToOpenPopupMenu" : MessageLookupByLibrary.simpleMessage("Appuyer pour ouvrir le menu"), - "settingsTapToOpenPopupMenuDes" : MessageLookupByLibrary.simpleMessage("Vous devez effectuer un appui long pour ouvrir la page de l\'épisode"), + "settingsTapToOpenPopupMenu" : MessageLookupByLibrary.simpleMessage("Ouverture du menu"), + "settingsTapToOpenPopupMenuDes" : MessageLookupByLibrary.simpleMessage("Effectuer un appui long pour ouvrir la page de l\'épisode"), "settingsTheme" : MessageLookupByLibrary.simpleMessage("Thème"), - "settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("Intervalle des mises à jour"), - "settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("24 heures par défaut"), + "settingsUpdateInterval" : MessageLookupByLibrary.simpleMessage("Intervalle de mise à jour"), + "settingsUpdateIntervalDes" : MessageLookupByLibrary.simpleMessage("L\'intervalle par défaut est de 24 heures"), "share" : MessageLookupByLibrary.simpleMessage("Partager"), "size" : MessageLookupByLibrary.simpleMessage("Taille"), "skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("Passer les premières secondes du début"), "skipSilence" : MessageLookupByLibrary.simpleMessage("Skip silence"), + "skipToNext" : MessageLookupByLibrary.simpleMessage("Skip to next"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("Minuterie"), - "subscribe" : MessageLookupByLibrary.simpleMessage("Abonnements"), + "stop" : MessageLookupByLibrary.simpleMessage("Stop"), + "subscribe" : MessageLookupByLibrary.simpleMessage("S\'abonner"), "subscribeExportDes" : MessageLookupByLibrary.simpleMessage("Exporter le fichier OPML de tous les podcasts."), "systemDefault" : MessageLookupByLibrary.simpleMessage("Système par défaut"), "timeLastPlayed" : m24, "timeLeft" : m25, "to" : m26, - "toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("Ajouté à la playlist."), + "toastAddPlaylist" : MessageLookupByLibrary.simpleMessage("Ajouter l\'épisode à la playlist."), "toastDiscovery" : MessageLookupByLibrary.simpleMessage("Tutoriel réinitialisé, veuillez redémarrer l\'application."), "toastFileError" : MessageLookupByLibrary.simpleMessage("Erreur du fichier, échec de l\'abonnement."), "toastFileNotValid" : MessageLookupByLibrary.simpleMessage("Fichier invalide."), diff --git a/lib/generated/intl/messages_zh-Hans.dart b/lib/generated/intl/messages_zh-Hans.dart index f7a93c3..4cace47 100644 --- a/lib/generated/intl/messages_zh-Hans.dart +++ b/lib/generated/intl/messages_zh-Hans.dart @@ -110,6 +110,8 @@ class MessageLookup extends MessageLookupByLibrary { "editGroupName" : MessageLookupByLibrary.simpleMessage("修改组名"), "endOfEpisode" : MessageLookupByLibrary.simpleMessage("节目结束"), "episode" : m4, + "fastForward" : MessageLookupByLibrary.simpleMessage("快进"), + "fastRewind" : MessageLookupByLibrary.simpleMessage("快退"), "featureDiscoveryEditGroup" : MessageLookupByLibrary.simpleMessage("点击修改分组"), "featureDiscoveryEditGroupDes" : MessageLookupByLibrary.simpleMessage("您可以修改分组名或者删除分组,注意 Home 分组无法修改,也不能被删除。"), "featureDiscoveryEpisode" : MessageLookupByLibrary.simpleMessage("节目界面"), @@ -140,6 +142,7 @@ class MessageLookup extends MessageLookupByLibrary { "groupFilter" : MessageLookupByLibrary.simpleMessage("分组"), "groupRemoveConfirm" : MessageLookupByLibrary.simpleMessage("您确认要移除该分组吗?播客将被移动到 Home 分组。"), "groups" : m6, + "hideListenedSetting" : MessageLookupByLibrary.simpleMessage("隐藏已收听"), "homeGroupsSeeAll" : MessageLookupByLibrary.simpleMessage("查看全部"), "homeMenuPlaylist" : MessageLookupByLibrary.simpleMessage("播放列表"), "homeSubMenuSortBy" : MessageLookupByLibrary.simpleMessage("排序"), @@ -186,12 +189,14 @@ class MessageLookup extends MessageLookupByLibrary { "noShownote" : MessageLookupByLibrary.simpleMessage("节目简介暂未收到。"), "notificaitonFatch" : m12, "notificationNetworkError" : m13, + "notificationSetting" : MessageLookupByLibrary.simpleMessage("通知栏"), "notificationSubscribe" : m14, "notificationSubscribeExisted" : m15, "notificationSuccess" : m16, "notificationUpdate" : m17, "notificationUpdateError" : m18, "oldestFirst" : MessageLookupByLibrary.simpleMessage("由旧到新"), + "pause" : MessageLookupByLibrary.simpleMessage("暂停"), "play" : MessageLookupByLibrary.simpleMessage("播放"), "playback" : MessageLookupByLibrary.simpleMessage("播放控制"), "player" : MessageLookupByLibrary.simpleMessage("播放器"), @@ -300,7 +305,9 @@ class MessageLookup extends MessageLookupByLibrary { "size" : MessageLookupByLibrary.simpleMessage("大小"), "skipSecondsAtStart" : MessageLookupByLibrary.simpleMessage("开头跳过秒数"), "skipSilence" : MessageLookupByLibrary.simpleMessage("跳过无声"), + "skipToNext" : MessageLookupByLibrary.simpleMessage("下一首"), "sleepTimer" : MessageLookupByLibrary.simpleMessage("睡眠模式"), + "stop" : MessageLookupByLibrary.simpleMessage("停止"), "subscribe" : MessageLookupByLibrary.simpleMessage("订阅"), "subscribeExportDes" : MessageLookupByLibrary.simpleMessage("导出 OMPL 文件"), "systemDefault" : MessageLookupByLibrary.simpleMessage("系统默认"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index fbd3e4d..eccfd61 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -358,6 +358,26 @@ class S { ); } + /// `Fast forward` + String get fastForward { + return Intl.message( + 'Fast forward', + name: 'fastForward', + desc: '', + args: [], + ); + } + + /// `Fast rewind` + String get fastRewind { + return Intl.message( + 'Fast rewind', + name: 'fastRewind', + desc: '', + args: [], + ); + } + /// `Tap to edit group` String get featureDiscoveryEditGroup { return Intl.message( @@ -661,6 +681,16 @@ class S { ); } + /// `Hide listened` + String get hideListenedSetting { + return Intl.message( + 'Hide listened', + name: 'hideListenedSetting', + desc: '', + args: [], + ); + } + /// `See All` String get homeGroupsSeeAll { return Intl.message( @@ -1133,6 +1163,16 @@ class S { ); } + /// `Notification panel` + String get notificationSetting { + return Intl.message( + 'Notification panel', + name: 'notificationSetting', + desc: '', + args: [], + ); + } + /// `Subscribe {title}` String notificationSubscribe(Object title) { return Intl.message( @@ -1193,6 +1233,16 @@ class S { ); } + /// `Pause` + String get pause { + return Intl.message( + 'Pause', + name: 'pause', + desc: '', + args: [], + ); + } + /// `Play` String get play { return Intl.message( @@ -2282,6 +2332,16 @@ class S { ); } + /// `Skip to next` + String get skipToNext { + return Intl.message( + 'Skip to next', + name: 'skipToNext', + desc: '', + args: [], + ); + } + /// `Sleep timer` String get sleepTimer { return Intl.message( @@ -2292,6 +2352,16 @@ class S { ); } + /// `Stop` + String get stop { + return Intl.message( + 'Stop', + name: 'stop', + desc: '', + args: [], + ); + } + /// `Subscribe` String get subscribe { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 3f026a6..8fb0345 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -74,6 +74,10 @@ "@endOfEpisode": {}, "episode": "{count, plural, zero{} one{Episode} other{Episodes}}", "@episode": {}, + "fastForward": "Fast forward", + "@fastForward": {}, + "fastRewind": "Fast rewind", + "@fastRewind": {}, "featureDiscoveryEditGroup": "Tap to edit group", "@featureDiscoveryEditGroup": {}, "featureDiscoveryEditGroupDes": "You can change group name or delete it here, but the home group can not be edited or deleted", @@ -142,6 +146,8 @@ "@groupRemoveConfirm": {}, "groups": "{count, plural, zero{Group} one{Group} other{Groups}}", "@groups": {}, + "hideListenedSetting": "Hide listened", + "@hideListenedSetting": {}, "homeGroupsSeeAll": "See All", "@homeGroupsSeeAll": {}, "homeMenuPlaylist": "Playlist", @@ -248,6 +254,8 @@ "title": {} } }, + "notificationSetting": "Notification panel", + "@notificationSetting": {}, "notificationSubscribe": "Subscribe {title}", "@notificationSubscribe": { "placeholders": { @@ -280,6 +288,8 @@ }, "oldestFirst": "Oldest first", "@oldestFirst": {}, + "pause": "Pause", + "@pause": {}, "play": "Play", "@play": {}, "playback": "Playback control", @@ -517,8 +527,12 @@ "@skipSilence": { "description": "Feature skip silence" }, + "skipToNext": "Skip to next", + "@skipToNext": {}, "sleepTimer": "Sleep timer", "@sleepTimer": {}, + "stop": "Stop", + "@stop": {}, "subscribe": "Subscribe", "@subscribe": {}, "subscribeExportDes": "Export OMPL file of all podcasts", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 8ea4e1b..4fca8c5 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -74,6 +74,10 @@ "@endOfEpisode": {}, "episode": "{count, plural, zero{} one{Episodio} other{Episodios}}", "@episode": {}, + "fastForward": "Fast forward", + "@fastForward": {}, + "fastRewind": "Fast rewind", + "@fastRewind": {}, "featureDiscoveryEditGroup": "Toca para editar grupo", "@featureDiscoveryEditGroup": {}, "featureDiscoveryEditGroupDes": "Puedes cambiar el nombre del grupo o eliminar el grupo aquí, el grupo Home no puede ser editado ni borrado", @@ -142,6 +146,8 @@ "@groupRemoveConfirm": {}, "groups": "{count, plural, zero{Grupo} one{Grupo} other{Grupos}}", "@groups": {}, + "hideListenedSetting": "Hide listened", + "@hideListenedSetting": {}, "homeGroupsSeeAll": "Ver todo", "@homeGroupsSeeAll": {}, "homeMenuPlaylist": "Lista de reproducción", @@ -248,6 +254,8 @@ "title": {} } }, + "notificationSetting": "Notification panel", + "@notificationSetting": {}, "notificationSubscribe": "Suscribir {title}", "@notificationSubscribe": { "placeholders": { @@ -280,6 +288,8 @@ }, "oldestFirst": "Mas antiguos primero", "@oldestFirst": {}, + "pause": "Pause", + "@pause": {}, "play": "Reproducir", "@play": {}, "playback": "Control de reproducción", @@ -517,8 +527,12 @@ "@skipSilence": { "description": "Feature skip silence" }, + "skipToNext": "Skip to next", + "@skipToNext": {}, "sleepTimer": "Temporizador de sueño", "@sleepTimer": {}, + "stop": "Stop", + "@stop": {}, "subscribe": "Suscribir", "@subscribe": {}, "subscribeExportDes": "Exportar OPML de todos los podcasts", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 5bdb944..de6f58e 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -20,11 +20,11 @@ }, "all": "Tout", "@all": {}, - "autoDownload": "Téléchargements auto", + "autoDownload": "Automatisation", "@autoDownload": {}, "back": "Retour", "@back": {}, - "boostVolume": "Boost volume", + "boostVolume": "Booster le volume", "@boostVolume": { "description": "Boost volume in player widget." }, @@ -60,7 +60,7 @@ "@developer": { "description": "Can also translate to About me" }, - "dismiss": "Rejeter", + "dismiss": "Passer", "@dismiss": {}, "done": "Fait", "@done": {}, @@ -74,41 +74,45 @@ "@endOfEpisode": {}, "episode": "{count, plural, zero{} one{Épisode} other{Épisodes }}", "@episode": {}, - "featureDiscoveryEditGroup": "Appuyez pour éditer le groupe", + "fastForward": "Fast forward", + "@fastForward": {}, + "fastRewind": "Fast rewind", + "@fastRewind": {}, + "featureDiscoveryEditGroup": "Gestion des groupes", "@featureDiscoveryEditGroup": {}, - "featureDiscoveryEditGroupDes": "Vous pouvez supprimer ou modifier le nom du groupe, le groupe Home ne peut être modifié ni supprimé.", + "featureDiscoveryEditGroupDes": "Ici vous pouvez supprimer ou modifier le nom des groupes, seul le groupe Home ne peut être édité.", "@featureDiscoveryEditGroupDes": {}, "featureDiscoveryEpisode": "Vue épisode", "@featureDiscoveryEpisode": {}, "featureDiscoveryEpisodeDes": "Vous pouvez effectuer un appui long pour jouer un épisode ou l'ajouter à la playlist.", "@featureDiscoveryEpisodeDes": {}, - "featureDiscoveryEpisodeTitle": "Effectuez un appui long pour jouer un épisode immédiatement", + "featureDiscoveryEpisodeTitle": "Effectuez un appui long pour lancer un épisode", "@featureDiscoveryEpisodeTitle": {}, - "featureDiscoveryGroup": "Appuyez pour ajouter un groupe.", + "featureDiscoveryGroup": "Appuyez ici pour créer un groupe", "@featureDiscoveryGroup": {}, "featureDiscoveryGroupDes": "Pour les nouveaux podcasts le groupe par défaut est Home. Vous pouvez créer de nouveaux groupes et y déplacer vos podcasts. Un podcast peut être associé à plusieurs groupes.", "@featureDiscoveryGroupDes": {}, - "featureDiscoveryGroupPodcast": "Un appui long pour classer les podcasts", + "featureDiscoveryGroupPodcast": "Classement des podcasts", "@featureDiscoveryGroupPodcast": {}, - "featureDiscoveryGroupPodcastDes": "Appuyez pour accéder à plus d'options, un appui long permet de classer les podcasts du groupe.", + "featureDiscoveryGroupPodcastDes": "Appuyez ici pour accéder à plus d'options, un appui long permet de classer les podcasts d'un groupe.", "@featureDiscoveryGroupPodcastDes": {}, - "featureDiscoveryOMPL": "Appuyez pour importer un fichier OPML", + "featureDiscoveryOMPL": "Appuyez ici pour importer un fichier OPML", "@featureDiscoveryOMPL": {}, "featureDiscoveryOMPLDes": "Vous pouvez importer un fichier OPML, accéder aux paramètres ou actualiser tous les podcasts.", "@featureDiscoveryOMPLDes": {}, - "featureDiscoveryPlaylist": "Appuyez pour ouvrir la playlist", + "featureDiscoveryPlaylist": "Appuyez ici pour ouvrir la playlist", "@featureDiscoveryPlaylist": {}, - "featureDiscoveryPlaylistDes": "Vous pouvez ajouter des épisodes dans la playlist. Ils seront automatiquement retirés l'écoute finie.", + "featureDiscoveryPlaylistDes": "Ajoutez des épisodes dans la playlist. Ils seront automatiquement retirés une fois écoutés.", "@featureDiscoveryPlaylistDes": {}, "featureDiscoveryPodcast": "Vue podcasts", "@featureDiscoveryPodcast": {}, - "featureDiscoveryPodcastDes": "Vous pouvez appuyer sur Tout Voir pour ajouter des groupes ou gérer les podcasts.", + "featureDiscoveryPodcastDes": "Appuyez sur Tout Voir pour ajouter des groupes et gérer les podcasts.", "@featureDiscoveryPodcastDes": {}, "featureDiscoveryPodcastTitle": "Effectuez un défilement vertical pour changer de groupe.", "@featureDiscoveryPodcastTitle": {}, - "featureDiscoverySearch": "Appuyez pour chercher un podcast", + "featureDiscoverySearch": "Appuyez ici pour rechercher un podcast", "@featureDiscoverySearch": {}, - "featureDiscoverySearchDes": "Vous pouvez effectuer une recherche par titre, mots clés ou lien RSS pour vous abonner à un nouveau podcast.", + "featureDiscoverySearchDes": "Pour trouver vos podcasts vous pouvez effectuer une recherche par titres, mots clés ou liens RSS.", "@featureDiscoverySearchDes": {}, "feedbackEmail": "Contact", "@feedbackEmail": {}, @@ -142,6 +146,8 @@ "@groupRemoveConfirm": {}, "groups": "{count, plural, zero{Groupe} one{Groupe} other{Groupes}}", "@groups": {}, + "hideListenedSetting": "Hide listened", + "@hideListenedSetting": {}, "homeGroupsSeeAll": "Tout Voir", "@homeGroupsSeeAll": {}, "homeMenuPlaylist": "Playlist", @@ -154,7 +160,7 @@ "@homeTabMenuRecent": {}, "homeToprightMenuAbout": "À propos", "@homeToprightMenuAbout": {}, - "homeToprightMenuImportOMPL": "Importer le fichier OPML", + "homeToprightMenuImportOMPL": "Importer un fichier OPML", "@homeToprightMenuImportOMPL": {}, "homeToprightMenuRefreshAll": "Tout actualiser", "@homeToprightMenuRefreshAll": {}, @@ -170,11 +176,11 @@ "@hoursCount": {}, "import": "Importer", "@import": {}, - "introFourthPage": "Vous pouvez effectuer un appui long sur un épisode pour accéder aux actions rapides.", + "introFourthPage": "Un appui long sur un épisode lance les actions rapides.", "@introFourthPage": {}, - "introSecondPage": "Souscrivez aux podcasts via la section recherche ou importez un fichier OPML.", + "introSecondPage": "S'abonner aux podcasts via la section recherche ou un fichier OPML.", "@introSecondPage": {}, - "introThirdPage": "Vous pouvez créer un nouveau groupe de podcasts.", + "introThirdPage": "Vous pouvez créer des groupes de podcasts.", "@introThirdPage": {}, "later": "Plus tard", "@later": {}, @@ -202,7 +208,7 @@ "@markConfirm": {}, "markConfirmContent": "Marquer tous les épisodes comme lus ?", "@markConfirmContent": {}, - "markListened": "Marquer comme lu", + "markListened": "Marquage", "@markListened": {}, "markNotListened": "Mark not listened", "@markNotListened": {}, @@ -232,7 +238,7 @@ "@noEpisodeDownload": {}, "noEpisodeFavorite": "Aucun épisode ajouté.", "@noEpisodeFavorite": {}, - "noEpisodeRecent": "Aucun épisode récupéré.", + "noEpisodeRecent": "Aucun épisode récent.", "@noEpisodeRecent": {}, "noPodcastGroup": "Ce groupe ne contient aucun podcast", "@noPodcastGroup": {}, @@ -248,7 +254,9 @@ "title": {} } }, - "notificationSubscribe": "S'abonner", + "notificationSetting": "Notification panel", + "@notificationSetting": {}, + "notificationSubscribe": "Abonnement en cours", "@notificationSubscribe": { "placeholders": { "title": {} @@ -280,17 +288,19 @@ }, "oldestFirst": "Le plus ancien en premier", "@oldestFirst": {}, + "pause": "Pause", + "@pause": {}, "play": "Lecture", "@play": {}, "playback": "Commandes du lecteur", "@playback": {}, "player": "Player", "@player": {}, - "playerHeightMed": "Medium", + "playerHeightMed": "Moyen", "@playerHeightMed": {}, - "playerHeightShort": "Low", + "playerHeightShort": "Petit", "@playerHeightShort": {}, - "playerHeightTall": "High", + "playerHeightTall": "Grand", "@playerHeightTall": {}, "playing": "En cours", "@playing": {}, @@ -298,17 +308,17 @@ "@plugins": {}, "podcast": "{count, plural, zero{} one{Podcast} other{Podcasts}}", "@podcast": {}, - "podcastSubscribed": "Abonnements", + "podcastSubscribed": "Abonné au podcast", "@podcastSubscribed": {}, "popupMenuDownloadDes": "Télécharger l'épisode", "@popupMenuDownloadDes": {}, - "popupMenuLaterDes": "Ajouter l'épisode à la playlist", + "popupMenuLaterDes": "Ajouter à la playlist", "@popupMenuLaterDes": {}, "popupMenuLikeDes": "Ajouter l'épisode aux favoris", "@popupMenuLikeDes": {}, "popupMenuMarkDes": "Marquer l'épisode comme lu", "@popupMenuMarkDes": {}, - "popupMenuPlayDes": "Jouer l'épisode", + "popupMenuPlayDes": "Lancer l'épisode", "@popupMenuPlayDes": {}, "privacyPolicy": "Gestion des données", "@privacyPolicy": {}, @@ -377,7 +387,7 @@ "@settingsAppearance": {}, "settingsAppearanceDes": "Couleurs et thèmes", "@settingsAppearanceDes": {}, - "settingsAppIntro": "App intro", + "settingsAppIntro": "Revoir l'introduction", "@settingsAppIntro": {}, "settingsAudioCache": "Cache audio", "@settingsAudioCache": {}, @@ -393,9 +403,9 @@ "@settingsBackup": {}, "settingsBackupDes": "Sauvegarde des données de l'application", "@settingsBackupDes": {}, - "settingsBoostVolume": "Volume boost level", + "settingsBoostVolume": "Booster le volume", "@settingsBoostVolume": {}, - "settingsBoostVolumeDes": "Change volume boost level", + "settingsBoostVolumeDes": "Définir la puissance du volume", "@settingsBoostVolumeDes": {}, "settingsDefaultGrid": "Vue par défaut", "@settingsDefaultGrid": {}, @@ -403,7 +413,7 @@ "@settingsDefaultGridDownload": {}, "settingsDefaultGridFavorite": "Onglet Favoris", "@settingsDefaultGridFavorite": {}, - "settingsDefaultGridPodcast": "Page du podcast", + "settingsDefaultGridPodcast": "Onglet podcasts", "@settingsDefaultGridPodcast": {}, "settingsDefaultGridRecent": "Onglet Récents", "@settingsDefaultGridRecent": {}, @@ -419,7 +429,7 @@ "@settingsExportDes": {}, "settingsFastForwardSec": "Avance rapide", "@settingsFastForwardSec": {}, - "settingsFastForwardSecDes": "Saut avant en secondes", + "settingsFastForwardSecDes": "Saut avant", "@settingsFastForwardSecDes": {}, "settingsFeedback": "Feedback", "@settingsFeedback": {}, @@ -429,9 +439,9 @@ "@settingsHistory": {}, "settingsHistoryDes": "Gestion des données", "@settingsHistoryDes": {}, - "settingsInfo": "Infos", + "settingsInfo": "Informations", "@settingsInfo": {}, - "settingsInterface": "Interface", + "settingsInterface": "Interface utilisateur", "@settingsInterface": {}, "settingsLanguages": "Langues", "@settingsLanguages": {}, @@ -447,7 +457,7 @@ "@settingsLibrariesDes": {}, "settingsManageDownload": "Gérer les téléchargements", "@settingsManageDownload": {}, - "settingsManageDownloadDes": "Gérer les fichiers audio téléchargés", + "settingsManageDownloadDes": "Gestion des fichiers audio téléchargés", "@settingsManageDownloadDes": {}, "settingsMenuAutoPlay": "Lecture automatique", "@settingsMenuAutoPlay": {}, @@ -455,15 +465,15 @@ "@settingsNetworkCellular": {}, "settingsNetworkCellularAuto": "Téléchargement automatique sur réseau mobile", "@settingsNetworkCellularAuto": {}, - "settingsNetworkCellularAutoDes": "Vous pouvez automatiser le téléchargement des podcasts sur la page de gestion des groupes.", + "settingsNetworkCellularAutoDes": "L'automatisation du téléchargement peut aussi être configurée sur page de gestion des groupes", "@settingsNetworkCellularAutoDes": {}, - "settingsNetworkCellularDes": "Si connecté à un réseau mobile, demander une confirmation avant de télécharger.", + "settingsNetworkCellularDes": "Demander une confirmation avant de lancer un téléchargement", "@settingsNetworkCellularDes": {}, "settingsPlayDes": "Playlist et lecteur", "@settingsPlayDes": {}, - "settingsPlayerHeight": "Player height", + "settingsPlayerHeight": "Taille du player", "@settingsPlayerHeight": {}, - "settingsPlayerHeightDes": "Change player widget height as you like", + "settingsPlayerHeightDes": "Changer la hauteur du widget", "@settingsPlayerHeightDes": {}, "settingsPopupMenu": "Menu popup des épisodes", "@settingsPopupMenu": {}, @@ -473,17 +483,17 @@ "@settingsPrefrence": {}, "settingsRealDark": "Noir profond", "@settingsRealDark": {}, - "settingsRealDarkDes": "Activer pour un mode sombre accentué", + "settingsRealDarkDes": "Mode sombre accentué", "@settingsRealDarkDes": {}, "settingsRewindSec": "Retour rapide", "@settingsRewindSec": {}, - "settingsRewindSecDes": "Saut arrière en secondes", + "settingsRewindSecDes": "Saut arrière", "@settingsRewindSecDes": {}, "settingsSTAuto": "Activation automatique de la minuterie", "@settingsSTAuto": {}, "settingsSTAutoDes": "Démarrer la minuterie à l'horaire programmé", "@settingsSTAutoDes": {}, - "settingsSTDefaultTime": "Temps par défaut", + "settingsSTDefaultTime": "Durée par défaut", "@settingsSTDefaultTime": {}, "settingsSTDefautTimeDes": "Configuration de la minuterie", "@settingsSTDefautTimeDes": {}, @@ -495,17 +505,17 @@ "@settingsSyncing": {}, "settingsSyncingDes": "Actualisation des podcasts en arrière-plan", "@settingsSyncingDes": {}, - "settingsTapToOpenPopupMenu": "Appuyer pour ouvrir le menu", + "settingsTapToOpenPopupMenu": "Ouverture du menu", "@settingsTapToOpenPopupMenu": {}, - "settingsTapToOpenPopupMenuDes": "Vous devez effectuer un appui long pour ouvrir la page de l'épisode", + "settingsTapToOpenPopupMenuDes": "Effectuer un appui long pour ouvrir la page de l'épisode", "@settingsTapToOpenPopupMenuDes": {}, "settingsTheme": "Thème", "@settingsTheme": {}, "settingStorage": "Espace de stockage", "@settingStorage": {}, - "settingsUpdateInterval": "Intervalle des mises à jour", + "settingsUpdateInterval": "Intervalle de mise à jour", "@settingsUpdateInterval": {}, - "settingsUpdateIntervalDes": "24 heures par défaut", + "settingsUpdateIntervalDes": "L'intervalle par défaut est de 24 heures", "@settingsUpdateIntervalDes": {}, "share": "Partager", "@share": {}, @@ -517,9 +527,13 @@ "@skipSilence": { "description": "Feature skip silence" }, + "skipToNext": "Skip to next", + "@skipToNext": {}, "sleepTimer": "Minuterie", "@sleepTimer": {}, - "subscribe": "Abonnements", + "stop": "Stop", + "@stop": {}, + "subscribe": "S'abonner", "@subscribe": {}, "subscribeExportDes": "Exporter le fichier OPML de tous les podcasts.", "@subscribeExportDes": {}, @@ -544,7 +558,7 @@ "time": {} } }, - "toastAddPlaylist": "Ajouté à la playlist.", + "toastAddPlaylist": "Ajouter l'épisode à la playlist.", "@toastAddPlaylist": {}, "toastDiscovery": "Tutoriel réinitialisé, veuillez redémarrer l'application.", "@toastDiscovery": { diff --git a/lib/l10n/intl_zh_Hans.arb b/lib/l10n/intl_zh_Hans.arb index a8e91ab..e5e32e2 100644 --- a/lib/l10n/intl_zh_Hans.arb +++ b/lib/l10n/intl_zh_Hans.arb @@ -74,6 +74,10 @@ "@endOfEpisode": {}, "episode": "{count, plural, zero{} other{节目}}", "@episode": {}, + "fastForward": "快进", + "@fastForward": {}, + "fastRewind": "快退", + "@fastRewind": {}, "featureDiscoveryEditGroup": "点击修改分组", "@featureDiscoveryEditGroup": {}, "featureDiscoveryEditGroupDes": "您可以修改分组名或者删除分组,注意 Home 分组无法修改,也不能被删除。", @@ -142,6 +146,8 @@ "@groupRemoveConfirm": {}, "groups": "{count, plural, zero{分组} other{分组}}", "@groups": {}, + "hideListenedSetting": "隐藏已收听", + "@hideListenedSetting": {}, "homeGroupsSeeAll": "查看全部", "@homeGroupsSeeAll": {}, "homeMenuPlaylist": "播放列表", @@ -248,6 +254,8 @@ "title": {} } }, + "notificationSetting": "通知栏", + "@notificationSetting": {}, "notificationSubscribe": "订阅 {title}", "@notificationSubscribe": { "placeholders": { @@ -280,6 +288,8 @@ }, "oldestFirst": "由旧到新", "@oldestFirst": {}, + "pause": "暂停", + "@pause": {}, "play": "播放", "@play": {}, "playback": "播放控制", @@ -517,8 +527,12 @@ "@skipSilence": { "description": "Feature skip silence" }, + "skipToNext": "下一首", + "@skipToNext": {}, "sleepTimer": "睡眠模式", "@sleepTimer": {}, + "stop": "停止", + "@stop": {}, "subscribe": "订阅", "@subscribe": {}, "subscribeExportDes": "导出 OMPL 文件", diff --git a/lib/local_storage/key_value_storage.dart b/lib/local_storage/key_value_storage.dart index 0a4854b..1da10fb 100644 --- a/lib/local_storage/key_value_storage.dart +++ b/lib/local_storage/key_value_storage.dart @@ -42,6 +42,7 @@ const String localeKey = 'localeKey'; const String boostVolumeKey = 'boostVolumeKey'; const String volumeGainKey = 'volumeGainKey'; const String hideListenedKey = 'hideListenedKey'; +const String notificationLayoutKey = 'notificationLayoutKey'; class KeyValueStorage { final String key; diff --git a/lib/settings/play_setting.dart b/lib/settings/play_setting.dart index 5bd9990..5154239 100644 --- a/lib/settings/play_setting.dart +++ b/lib/settings/play_setting.dart @@ -7,6 +7,7 @@ import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; import '../home/audioplayer.dart'; +import '../local_storage/key_value_storage.dart'; import '../state/audio_state.dart'; import '../state/setting_state.dart'; import '../util/custom_dropdown.dart'; @@ -201,7 +202,7 @@ class PlaySetting extends StatelessWidget { appBar: AppBar( title: Text(s.play), elevation: 0, - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: context.primaryColor, ), body: SingleChildScrollView( scrollDirection: Axis.vertical, @@ -209,218 +210,200 @@ class PlaySetting extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + Container( + height: 60.0, + padding: EdgeInsets.symmetric(horizontal: 40), + alignment: Alignment.center, + child: Text(s.notificationSetting, + style: context.textTheme.bodyText1 + .copyWith(color: context.accentColor)), + ), + _NotificationLayout(), + Divider( + height: 1, + ), + Padding( + padding: const EdgeInsets.all(10.0), + ), + Container( + height: 30.0, + padding: EdgeInsets.symmetric(horizontal: 70), + alignment: Alignment.centerLeft, + child: Text(s.homeMenuPlaylist, + style: Theme.of(context) + .textTheme + .bodyText1 + .copyWith(color: Theme.of(context).accentColor)), + ), + Selector( + selector: (_, settings) => settings.autoPlay, + builder: (_, data, __) => ListTile( + onTap: () => settings.setAutoPlay = !data, + contentPadding: + EdgeInsets.only(left: 70.0, right: 20, bottom: 10), + title: Text(s.settingsMenuAutoPlay), + subtitle: Text(s.settingsAutoPlayDes), + trailing: Transform.scale( + scale: 0.9, + child: Switch( + value: data, + onChanged: (boo) => settings.setAutoPlay = boo), + ), + ), + ), + Divider(height: 1), + Padding( + padding: const EdgeInsets.all(10.0), + ), + Container( + height: 30.0, + padding: EdgeInsets.symmetric(horizontal: 70), + alignment: Alignment.centerLeft, + child: Text(s.playback, + style: Theme.of(context) + .textTheme + .bodyText1 + .copyWith(color: Theme.of(context).accentColor)), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 70.0, right: 20, bottom: 10, top: 10), + title: Text(s.settingsFastForwardSec), + subtitle: Text(s.settingsFastForwardSecDes), + trailing: Selector( + selector: (_, settings) => settings.fastForwardSeconds, + builder: (_, data, __) => MyDropdownButton( + hint: Text(s.secCount(data)), + underline: Center(), + elevation: 1, + displayItemCount: 5, + isDense: true, + value: data, + onChanged: (value) => + settings.setFastForwardSeconds = value, + items: secondsToSelect.map>((e) { + return DropdownMenuItem( + value: e, child: Text(s.secCount(e))); + }).toList()), + ), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 70.0, right: 20, bottom: 10, top: 10), + title: Text(s.settingsRewindSec), + subtitle: Text(s.settingsRewindSecDes), + trailing: Selector( + selector: (_, settings) => settings.rewindSeconds, + builder: (_, data, __) => MyDropdownButton( + hint: Text(s.secCount(data)), + underline: Center(), + elevation: 1, + displayItemCount: 5, + isDense: true, + value: data, + onChanged: (value) => settings.setRewindSeconds = value, + items: secondsToSelect.map>((e) { + return DropdownMenuItem( + value: e, child: Text(s.secCount(e))); + }).toList()), + ), + ), + ListTile( + contentPadding: + EdgeInsets.only(left: 70.0, right: 20, bottom: 10, top: 10), + title: Text(s.settingsBoostVolume), + subtitle: Text(s.settingsBoostVolumeDes), + trailing: Selector( + selector: (_, audio) => audio.volumeGain, + builder: (_, volumeGain, __) => MyDropdownButton( + hint: Text(_volumeEffect(context, volumeGain)), + underline: Center(), + elevation: 1, + displayItemCount: 5, + isDense: true, + value: volumeGain, + onChanged: (value) => audio.setVolumeGain = value, + items: [2000, 3000, 4000].map>((e) { + return DropdownMenuItem( + value: e, child: Text(_volumeEffect(context, e))); + }).toList()), + ), + ), + Divider(height: 1), + Padding( + padding: const EdgeInsets.all(10.0), + ), + Container( + height: 30.0, + padding: EdgeInsets.symmetric(horizontal: 70), + alignment: Alignment.centerLeft, + child: Text(s.sleepTimer, + style: context.textTheme.bodyText1 + .copyWith(color: Theme.of(context).accentColor)), + ), + ListView( + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + scrollDirection: Axis.vertical, children: [ - Padding( - padding: const EdgeInsets.all(10.0), + ListTile( + contentPadding: EdgeInsets.only(left: 70.0, right: 20), + title: Text(s.settingsSTDefaultTime), + subtitle: Text(s.settingsSTDefautTimeDes), + trailing: Selector( + selector: (_, settings) => settings.defaultSleepTimer, + builder: (_, data, __) => MyDropdownButton( + hint: Text(s.minsCount(data)), + underline: Center(), + elevation: 1, + displayItemCount: 5, + isDense: true, + value: data, + onChanged: (value) => + settings.setDefaultSleepTimer = value, + items: kMinsToSelect.map>((e) { + return DropdownMenuItem( + value: e, child: Text(s.minsCount(e))); + }).toList()), + ), ), - Container( - height: 30.0, - padding: EdgeInsets.symmetric(horizontal: 70), - alignment: Alignment.centerLeft, - child: Text(s.homeMenuPlaylist, - style: Theme.of(context) - .textTheme - .bodyText1 - .copyWith(color: Theme.of(context).accentColor)), - ), - ListView( - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - scrollDirection: Axis.vertical, - children: [ - Selector( - selector: (_, settings) => settings.autoPlay, - builder: (_, data, __) => ListTile( - onTap: () => settings.setAutoPlay = !data, - contentPadding: EdgeInsets.only( - left: 70.0, right: 20, bottom: 10), - title: Text(s.settingsMenuAutoPlay), - subtitle: Text(s.settingsAutoPlayDes), - trailing: Transform.scale( - scale: 0.9, - child: Switch( - value: data, - onChanged: (boo) => settings.setAutoPlay = boo), - ), - ), + Selector( + selector: (_, settings) => settings.autoSleepTimer, + builder: (_, data, __) => ListTile( + onTap: () => settings.setAutoSleepTimer = !data, + contentPadding: const EdgeInsets.only( + left: 70.0, right: 20.0, bottom: 10.0, top: 10.0), + title: Text(s.settingsSTAuto), + subtitle: Text(s.settingsSTAutoDes), + trailing: Transform.scale( + scale: 0.9, + child: Switch( + value: data, + onChanged: (boo) => + settings.setAutoSleepTimer = boo), ), - Divider(height: 1), - ], + ), ), - Padding( - padding: const EdgeInsets.all(10.0), - ), - Container( - height: 30.0, - padding: EdgeInsets.symmetric(horizontal: 70), - alignment: Alignment.centerLeft, - child: Text(s.playback, - style: Theme.of(context) - .textTheme - .bodyText1 - .copyWith(color: Theme.of(context).accentColor)), - ), - ListView( - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - scrollDirection: Axis.vertical, - children: [ - ListTile( - contentPadding: EdgeInsets.only( - left: 70.0, right: 20, bottom: 10, top: 10), - title: Text(s.settingsFastForwardSec), - subtitle: Text(s.settingsFastForwardSecDes), - trailing: Selector( - selector: (_, settings) => - settings.fastForwardSeconds, - builder: (_, data, __) => MyDropdownButton( - hint: Text(s.secCount(data)), - underline: Center(), - elevation: 1, - displayItemCount: 5, - isDense: true, - value: data, - onChanged: (value) => - settings.setFastForwardSeconds = value, - items: secondsToSelect - .map>((e) { - return DropdownMenuItem( - value: e, child: Text(s.secCount(e))); - }).toList()), - ), - ), - ListTile( - contentPadding: EdgeInsets.only( - left: 70.0, right: 20, bottom: 10, top: 10), - title: Text(s.settingsRewindSec), - subtitle: Text(s.settingsRewindSecDes), - trailing: Selector( - selector: (_, settings) => settings.rewindSeconds, - builder: (_, data, __) => MyDropdownButton( - hint: Text(s.secCount(data)), - underline: Center(), - elevation: 1, - displayItemCount: 5, - isDense: true, - value: data, - onChanged: (value) => - settings.setRewindSeconds = value, - items: secondsToSelect - .map>((e) { - return DropdownMenuItem( - value: e, child: Text(s.secCount(e))); - }).toList()), - ), - ), - ListTile( - contentPadding: EdgeInsets.only( - left: 70.0, right: 20, bottom: 10, top: 10), - title: Text(s.settingsBoostVolume), - subtitle: Text(s.settingsBoostVolumeDes), - trailing: Selector( - selector: (_, audio) => audio.volumeGain, - builder: (_, volumeGain, __) => MyDropdownButton( - hint: Text(_volumeEffect(context, volumeGain)), - underline: Center(), - elevation: 1, - displayItemCount: 5, - isDense: true, - value: volumeGain, - onChanged: (value) => - audio.setVolumeGain = value, - items: [2000, 3000, 4000] - .map>((e) { - return DropdownMenuItem( - value: e, - child: Text(_volumeEffect(context, e))); - }).toList()), - ), - ), - Divider(), - ]), - Padding( - padding: const EdgeInsets.all(10.0), - ), - Container( - height: 30.0, - padding: EdgeInsets.symmetric(horizontal: 70), - alignment: Alignment.centerLeft, - child: Text(s.sleepTimer, - style: context.textTheme.bodyText1 - .copyWith(color: Theme.of(context).accentColor)), - ), - ListView( - physics: const BouncingScrollPhysics(), - shrinkWrap: true, - scrollDirection: Axis.vertical, - children: [ - ListTile( - contentPadding: EdgeInsets.only(left: 70.0, right: 20), - title: Text(s.settingsSTDefaultTime), - subtitle: Text(s.settingsSTDefautTimeDes), - trailing: Selector( - selector: (_, settings) => settings.defaultSleepTimer, - builder: (_, data, __) => MyDropdownButton( - hint: Text(s.minsCount(data)), - underline: Center(), - elevation: 1, - displayItemCount: 5, - isDense: true, - value: data, - onChanged: (value) => - settings.setDefaultSleepTimer = value, - items: - kMinsToSelect.map>((e) { - return DropdownMenuItem( - value: e, child: Text(s.minsCount(e))); - }).toList()), - ), - ), - Selector( - selector: (_, settings) => settings.autoSleepTimer, - builder: (_, data, __) => ListTile( - onTap: () => settings.setAutoSleepTimer = !data, - contentPadding: const EdgeInsets.only( - left: 70.0, right: 20.0, bottom: 10.0, top: 10.0), - title: Text(s.settingsSTAuto), - subtitle: Text(s.settingsSTAutoDes), - trailing: Transform.scale( - scale: 0.9, - child: Switch( - value: data, - onChanged: (boo) => - settings.setAutoSleepTimer = boo), - ), - ), - ), - ListTile( - contentPadding: const EdgeInsets.only( - left: 70.0, right: 20.0, bottom: 10.0, top: 10.0), - title: Text(s.settingsSTMode), - subtitle: - context.width > 360 ? null : _modeWidget(context), - trailing: context.width > 360 - ? _modeWidget(context) - : null), - ListTile( - contentPadding: - EdgeInsets.only(left: 70.0, right: 20), - title: Text(s.schedule), - subtitle: context.width > 360 - ? null - : _scheduleWidget(context), - trailing: context.width > 360 - ? _scheduleWidget(context) - : null), - Divider(height: 1) - ], - ), - SizedBox(height: 20) + ListTile( + contentPadding: const EdgeInsets.only( + left: 70.0, right: 20.0, bottom: 10.0, top: 10.0), + title: Text(s.settingsSTMode), + subtitle: + context.width > 360 ? null : _modeWidget(context), + trailing: + context.width > 360 ? _modeWidget(context) : null), + ListTile( + contentPadding: EdgeInsets.only(left: 70.0, right: 20), + title: Text(s.schedule), + subtitle: + context.width > 360 ? null : _scheduleWidget(context), + trailing: context.width > 360 + ? _scheduleWidget(context) + : null), + Divider(height: 1) ], ), + SizedBox(height: 20) ], ), ), @@ -428,3 +411,121 @@ class PlaySetting extends StatelessWidget { ); } } + +class _NotificationLayout extends StatefulWidget { + _NotificationLayout({Key key}) : super(key: key); + + @override + __NotificationLayoutState createState() => __NotificationLayoutState(); +} + +class __NotificationLayoutState extends State<_NotificationLayout> { + Future _getNotificationLayout() async { + final storage = KeyValueStorage(notificationLayoutKey); + var index = await storage.getInt(defaultValue: 0); + return index; + } + + Future _setNotificationLayout(int index) async { + final storage = KeyValueStorage(notificationLayoutKey); + await storage.saveInt(index); + if (mounted) setState(() {}); + } + + Widget _notificationIcon(Widget icon, String des) { + return LimitedBox( + maxWidth: 60, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + icon, + SizedBox(height: 8), + Text(des, + style: TextStyle( + fontSize: 12, color: context.textColor.withOpacity(0.5)), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.clip), + ], + ), + ); + } + + Widget _notificationOptions(int index, {int selected}) { + final s = context.s; + return InkWell( + borderRadius: BorderRadius.circular(10.0), + onTap: () => _setNotificationLayout(index), + child: Container( + padding: EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + border: Border.all( + color: index == selected + ? context.accentColor.withAlpha(70) + : context.primaryColorDark, + ), + borderRadius: BorderRadius.circular(10), + color: index == selected + ? context.accentColor.withAlpha(70) + : Colors.transparent, + ), + child: index == 0 + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _notificationIcon( + Icon(Icons.pause_circle_filled), '${s.play}| ${s.pause}'), + _notificationIcon(Icon(Icons.fast_forward), s.fastForward), + _notificationIcon(Icon(Icons.skip_next), s.skipToNext), + _notificationIcon(Icon(Icons.close), s.stop), + ], + ) + : index == 1 + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _notificationIcon(Icon(Icons.pause_circle_filled), + '${s.play}| ${s.pause}'), + _notificationIcon( + Icon(Icons.fast_rewind), s.fastRewind), + _notificationIcon(Icon(Icons.skip_next), s.skipToNext), + _notificationIcon(Icon(Icons.close), s.stop), + ]) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _notificationIcon(Icon(Icons.fast_rewind), s.fastRewind), + _notificationIcon(Icon(Icons.pause_circle_filled), + '${s.play}| ${s.pause}'), + _notificationIcon( + Icon(Icons.fast_forward), s.fastForward), + _notificationIcon(Icon(Icons.close), s.stop), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.fromLTRB(40, 0, 40, 30), + child: FutureBuilder( + future: _getNotificationLayout(), + initialData: 0, + builder: (context, snapshot) => Column( + children: [ + _notificationOptions(0, selected: snapshot.data), + SizedBox(height: 20), + _notificationOptions(1, selected: snapshot.data), + SizedBox(height: 20), + _notificationOptions(2, selected: snapshot.data), + ], + ), + ), + ); + } +} diff --git a/lib/state/audio_state.dart b/lib/state/audio_state.dart index ad5c800..dca5800 100644 --- a/lib/state/audio_state.dart +++ b/lib/state/audio_state.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math' as math; import 'package:audio_service/audio_service.dart'; +import 'package:audio_session/audio_session.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:just_audio/just_audio.dart'; @@ -43,6 +44,12 @@ MediaControl forward = MediaControl( action: MediaAction.fastForward, ); +MediaControl rewind = MediaControl( + androidIcon: 'drawable/baseline_fast_rewind_white_24', + label: 'rewind', + action: MediaAction.rewind, +); + void _audioPlayerTaskEntrypoint() async { AudioServiceBackground.run(() => AudioPlayerTask()); } @@ -718,10 +725,11 @@ class AudioPlayerNotifier extends ChangeNotifier { } class AudioPlayerTask extends BackgroundAudioTask { - KeyValueStorage cacheStorage = KeyValueStorage(cacheMaxKey); - + final cacheStorage = KeyValueStorage(cacheMaxKey); + final layoutStorage = KeyValueStorage(notificationLayoutKey); final List _queue = []; final AudioPlayer _audioPlayer = AudioPlayer(); + AudioSession _session; AudioProcessingState _skipState; bool _playing; bool _interrupted = false; @@ -737,6 +745,9 @@ class AudioPlayerTask extends BackgroundAudioTask { @override Future onStart(Map params) async { _stopAtEnd = false; + _session = await AudioSession.instance; + await _session.configure(AudioSessionConfiguration.speech()); + _handleInterruption(_session); _playerStateSubscription = _audioPlayer.playbackStateStream .where((state) => state == AudioPlaybackState.completed) .listen((state) { @@ -786,6 +797,52 @@ class AudioPlayerTask extends BackgroundAudioTask { } } + void _handleInterruption(AudioSession session) async { + session.interruptionEventStream.listen((event) { + if (event.begin) { + switch (event.type) { + case AudioInterruptionType.pause: + if (_playing) { + onPause(); + _interrupted = true; + } + break; + case AudioInterruptionType.duck: + if (_playing) { + onPause(); + _interrupted = true; + } + break; + case AudioInterruptionType.unknown: + if (_playing) { + onPause(); + _interrupted = true; + } + break; + } + } else { + switch (event.type) { + case AudioInterruptionType.pause: + if (!_playing && _interrupted) { + onPlay(); + } + break; + case AudioInterruptionType.duck: + if (!_playing && _interrupted) { + onPlay(); + } + break; + case AudioInterruptionType.unknown: + break; + } + _interrupted = false; + } + }); + session.becomingNoisyEventStream.listen((_) { + if (_playing) onPause(); + }); + } + void playPause() { if (AudioServiceBackground.state.playing) { onPause(); @@ -828,7 +885,7 @@ class AudioPlayerTask extends BackgroundAudioTask { } @override - void onPlay() async { + Future onPlay() async { if (_skipState == null) { if (_playing == null) { _playing = true; @@ -847,6 +904,7 @@ class AudioPlayerTask extends BackgroundAudioTask { _playFromStart(); } else { _playing = true; + _session.setActive(true); if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting || _audioPlayer.playbackEvent.state != AudioPlaybackState.none) { _audioPlayer.play(); @@ -855,8 +913,9 @@ class AudioPlayerTask extends BackgroundAudioTask { } } - _playFromStart() async { + Future _playFromStart() async { _playing = true; + _session.setActive(true); if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting || _audioPlayer.playbackEvent.state != AudioPlaybackState.none) { try { @@ -871,7 +930,7 @@ class AudioPlayerTask extends BackgroundAudioTask { } @override - void onPause() { + Future onPause() async { if (_skipState == null) { if (_playing == null) { } else if (_playing) { @@ -882,20 +941,22 @@ class AudioPlayerTask extends BackgroundAudioTask { } @override - void onSeekTo(Duration position) { + Future onSeekTo(Duration position) async { if (_audioPlayer.playbackEvent.state != AudioPlaybackState.connecting || _audioPlayer.playbackEvent.state != AudioPlaybackState.none) { - _audioPlayer.seek(position); + await _audioPlayer.seek(position); } } @override - void onClick(MediaButton button) { + Future onClick(MediaButton button) async { if (button == MediaButton.media) { - playPause(); + await playPause(); } else if (button == MediaButton.next) { - _seekRelative(fastForwardInterval); - } else if (button == MediaButton.previous) _seekRelative(-rewindInterval); + await _seekRelative(fastForwardInterval); + } else if (button == MediaButton.previous) { + await _seekRelative(-rewindInterval); + } } Future _seekRelative(Duration offset) async { @@ -918,19 +979,19 @@ class AudioPlayerTask extends BackgroundAudioTask { } @override - void onAddQueueItem(MediaItem mediaItem) async { + Future onAddQueueItem(MediaItem mediaItem) async { _queue.add(mediaItem); await AudioServiceBackground.setQueue(_queue); } @override - void onRemoveQueueItem(MediaItem mediaItem) async { + Future onRemoveQueueItem(MediaItem mediaItem) async { _queue.removeWhere((item) => item.id == mediaItem.id); await AudioServiceBackground.setQueue(_queue); } @override - void onAddQueueItemAt(MediaItem mediaItem, int index) async { + Future onAddQueueItemAt(MediaItem mediaItem, int index) async { if (index == 0) { await _audioPlayer.stop(); _queue.removeAt(0); @@ -951,57 +1012,57 @@ class AudioPlayerTask extends BackgroundAudioTask { } @override - void onFastForward() async { + Future onFastForward() async { await _seekRelative(fastForwardInterval); } @override - void onRewind() async { + Future onRewind() async { await _seekRelative(-rewindInterval); } - @override - void onAudioFocusLost(AudioInterruption interruption) { - if (_playing) _interrupted = true; - switch (interruption) { - case AudioInterruption.pause: - case AudioInterruption.temporaryPause: - case AudioInterruption.unknownPause: - onPause(); - break; - case AudioInterruption.temporaryDuck: - _audioPlayer.setVolume(0.5); - break; - } - } - - @override - void onAudioBecomingNoisy() { - if (_skipState == null) { - if (_playing == null) { - } else if (_audioPlayer.playbackEvent.state == - AudioPlaybackState.playing) { - _playing = false; - _audioPlayer.pause(); - } - } - } - - @override - void onAudioFocusGained(AudioInterruption interruption) { - switch (interruption) { - case AudioInterruption.temporaryPause: - if (!_playing && _interrupted) onPlay(); - break; - case AudioInterruption.temporaryDuck: - _audioPlayer.setVolume(1.0); - break; - default: - break; - } - _interrupted = false; - } - +// @override +// Future onAudioFocusLost(AudioInterruption interruption) { +// if (_playing) _interrupted = true; +// switch (interruption) { +// case AudioInterruption.pause: +// case AudioInterruption.temporaryPause: +// case AudioInterruption.unknownPause: +// onPause(); +// break; +// case AudioInterruption.temporaryDuck: +// _audioPlayer.setVolume(0.5); +// break; +// } +// } +// +// @override +// Future onAudioBecomingNoisy() async{ +// if (_skipState == null) { +// if (_playing == null) { +// } else if (_audioPlayer.playbackEvent.state == +// AudioPlaybackState.playing) { +// _playing = false; +// _audioPlayer.pause(); +// } +// } +// } +// +// @override +// void onAudioFocusGained(AudioInterruption interruption) { +// switch (interruption) { +// case AudioInterruption.temporaryPause: +// if (!_playing && _interrupted) onPlay(); +// break; +// case AudioInterruption.temporaryDuck: +// _audioPlayer.setVolume(1.0); +// break; +// default: +// break; +// } +// _interrupted = false; +// } +// @override Future onCustomAction(funtion, argument) async { switch (funtion) { @@ -1041,9 +1102,14 @@ class AudioPlayerTask extends BackgroundAudioTask { if (position == null) { position = _audioPlayer.playbackEvent.position; } + final index = await layoutStorage.getInt(defaultValue: 0); await AudioServiceBackground.setState( - controls: getControls(), - systemActions: [MediaAction.seekTo], + controls: getControls(index), + systemActions: [ + MediaAction.seekTo, + MediaAction.seekForward, + MediaAction.seekBackward, + ], processingState: processingState ?? AudioServiceBackground.state.processingState, playing: _playing ?? false, @@ -1053,11 +1119,36 @@ class AudioPlayerTask extends BackgroundAudioTask { ); } - List getControls() { - if (_playing) { - return [pauseControl, forward, skipToNextControl, stopControl]; - } else { - return [playControl, forward, skipToNextControl, stopControl]; + List getControls(int index) { + switch (index) { + case 0: + if (_playing) { + return [pauseControl, forward, skipToNextControl, stopControl]; + } else { + return [playControl, forward, skipToNextControl, stopControl]; + } + break; + case 1: + if (_playing) { + return [pauseControl, rewind, skipToNextControl, stopControl]; + } else { + return [playControl, rewind, skipToNextControl, stopControl]; + } + break; + case 2: + if (_playing) { + return [rewind, pauseControl, forward, stopControl]; + } else { + return [rewind, playControl, forward, stopControl]; + } + break; + default: + if (_playing) { + return [pauseControl, forward, skipToNextControl, stopControl]; + } else { + return [playControl, forward, skipToNextControl, stopControl]; + } + break; } } } diff --git a/lib/state/setting_state.dart b/lib/state/setting_state.dart index d020367..b1104ff 100644 --- a/lib/state/setting_state.dart +++ b/lib/state/setting_state.dart @@ -456,35 +456,37 @@ class SettingState extends ChangeNotifier { localeList.isEmpty ? '' : '${'${localeList.first}-'}${localeList[1]}'; var hideListened = await KeyValueStorage(hideListenedKey).getBool(defaultValue: false); + var notificationLayout = + await KeyValueStorage(notificationLayoutKey).getInt(defaultValue: 0); return SettingsBackup( - theme: theme, - accentColor: accentColor, - realDark: realDark, - autoPlay: autoPlay, - autoUpdate: autoUpdate, - updateInterval: updateInterval, - downloadUsingData: downloadUsingData, - cacheMax: cacheMax, - podcastLayout: podcastLayout, - recentLayout: recentLayout, - favLayout: favLayout, - downloadLayout: downloadLayout, - autoDownloadNetwork: autoDownloadNetwork, - episodePopupMenu: episodePopupMenu.map((e) => e.toString()).toList(), - autoDelete: autoDelete, - autoSleepTimer: autoSleepTimer, - autoSleepTimerStart: autoSleepTimerStart, - autoSleepTimerEnd: autoSleepTimerEnd, - autoSleepTimerMode: autoSleepTimerMode, - defaultSleepTime: defaultSleepTime, - tapToOpenPopupMenu: tapToOpenPopupMenu, - fastForwardSeconds: fastForwardSeconds, - rewindSeconds: rewindSeconds, - playerHeight: playerHeight, - locale: backupLocale, - hideListened: hideListened, - ); + theme: theme, + accentColor: accentColor, + realDark: realDark, + autoPlay: autoPlay, + autoUpdate: autoUpdate, + updateInterval: updateInterval, + downloadUsingData: downloadUsingData, + cacheMax: cacheMax, + podcastLayout: podcastLayout, + recentLayout: recentLayout, + favLayout: favLayout, + downloadLayout: downloadLayout, + autoDownloadNetwork: autoDownloadNetwork, + episodePopupMenu: episodePopupMenu.map((e) => e.toString()).toList(), + autoDelete: autoDelete, + autoSleepTimer: autoSleepTimer, + autoSleepTimerStart: autoSleepTimerStart, + autoSleepTimerEnd: autoSleepTimerEnd, + autoSleepTimerMode: autoSleepTimerMode, + defaultSleepTime: defaultSleepTime, + tapToOpenPopupMenu: tapToOpenPopupMenu, + fastForwardSeconds: fastForwardSeconds, + rewindSeconds: rewindSeconds, + playerHeight: playerHeight, + locale: backupLocale, + hideListened: hideListened, + notificationLayout: notificationLayout); } Future restore(SettingsBackup backup) async { @@ -516,6 +518,8 @@ class SettingState extends ChangeNotifier { await KeyValueStorage(tapToOpenPopupMenuKey) .saveBool(backup.tapToOpenPopupMenu); await KeyValueStorage(hideListenedKey).saveBool(backup.hideListened); + await KeyValueStorage(notificationLayoutKey) + .saveInt(backup.notificationLayout); if (backup.locale == '') { await localeStorage.saveStringList([]); await S.load(Locale(Intl.systemLocale)); diff --git a/lib/type/settings_backup.dart b/lib/type/settings_backup.dart index e6c64a8..fe0c995 100644 --- a/lib/type/settings_backup.dart +++ b/lib/type/settings_backup.dart @@ -25,6 +25,7 @@ class SettingsBackup { final int playerHeight; final String locale; final bool hideListened; + final int notificationLayout; SettingsBackup( {this.theme, this.accentColor, @@ -51,7 +52,8 @@ class SettingsBackup { this.rewindSeconds, this.playerHeight, this.locale, - this.hideListened}); + this.hideListened, + this.notificationLayout}); Map toJson() { return { @@ -79,7 +81,8 @@ class SettingsBackup { 'rewindSeconds': rewindSeconds, 'playerHeight': playerHeight, 'locale': locale, - 'hideListened': hideListened + 'hideListened': hideListened, + 'notificationLayout': notificationLayout }; } @@ -110,6 +113,7 @@ class SettingsBackup { rewindSeconds: json['rewindSeconds'] as int, playerHeight: json['playerHeight'] as int, locale: json['locale'] as String, - hideListened: json['hideListened'] as bool); + hideListened: json['hideListened'] as bool, + notificationLayout: json['notificationLayout'] as int); } } diff --git a/pubspec.yaml b/pubspec.yaml index 230ffce..37cb71b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,7 +12,8 @@ dependencies: flutter_localizations: sdk: flutter auto_animated: ^2.1.0 - audio_service: ^0.11.2 + audio_service: ^0.14.0 + audio_session: ^0.0.3 cached_network_image: ^2.2.0+1 color_thief_flutter: ^1.0.2 cupertino_icons: ^0.1.3