diff --git a/app/build.gradle b/app/build.gradle index d25c5014..068f6808 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ android { testApplicationId "ac.mdiq.podcini.tests" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 3020285 - versionName "6.12.7" + versionCode 3020286 + versionName "6.12.8" applicationId "ac.mdiq.podcini.R" def commit = "" diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt index b9805e7f..aa9c3872 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/net/sync/wifi/WifiSyncService.kt @@ -261,7 +261,7 @@ import kotlin.math.min .position(media.getPosition() / 1000) .playedDuration(media.playedDuration / 1000) .total(media.getDuration() / 1000) - .isFavorite(item.isFavorite) + .isFavorite(item.isSUPER) .playState(item.playState) .build() queuedEpisodeActions.add(played) @@ -334,7 +334,7 @@ import kotlin.math.min it.media!!.setPosition(action.position * 1000) it.media!!.playedDuration = action.playedDuration * 1000 it.media!!.setLastPlayedTime(action.timestamp!!.time) - it.rating = if (action.isFavorite) Rating.FAVORITE.code else Rating.UNRATED.code + it.rating = if (action.isFavorite) Rating.SUPER.code else Rating.UNRATED.code it.playState = action.playState if (hasAlmostEnded(it.media!!)) { Logd(TAG, "Marking as played") diff --git a/app/src/main/kotlin/ac/mdiq/podcini/net/utils/NetworkUtils.kt b/app/src/main/kotlin/ac/mdiq/podcini/net/utils/NetworkUtils.kt index fa7b2305..9a1813a2 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/net/utils/NetworkUtils.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/net/utils/NetworkUtils.kt @@ -44,7 +44,10 @@ object NetworkUtils { return when (networkInfo.type) { ConnectivityManager.TYPE_WIFI -> { if (isEnableAutodownloadWifiFilter) isInAllowedWifiNetwork - else !isNetworkMetered + else { + if (!isNetworkMetered) true + else isAllowMobileAutoDownload + } } ConnectivityManager.TYPE_ETHERNET -> true else -> isAllowMobileAutoDownload || !isNetworkRestricted @@ -158,7 +161,6 @@ object NetworkUtils { val allowed: MutableSet = HashSet(getValueStringSet!!) if (allow) allowed.add(type) else allowed.remove(type) - appPrefs.edit().putStringSet(UserPreferences.Prefs.prefMobileUpdateTypes.name, allowed).apply() } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt index 27a2c0e9..db3d9830 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/service/PlaybackService.kt @@ -368,7 +368,7 @@ class PlaybackService : MediaLibraryService() { val action = item?.feed?.preferences?.autoDeleteAction val shouldAutoDelete = (action == AutoDeleteAction.ALWAYS || (action == AutoDeleteAction.GLOBAL && item?.feed != null && shouldAutoDeleteItem(item!!.feed!!))) - if (playable is EpisodeMedia && shouldAutoDelete && (item?.isFavorite != true || !shouldFavoriteKeepEpisode)) { + if (playable is EpisodeMedia && shouldAutoDelete && (item?.isSUPER != true || !shouldFavoriteKeepEpisode)) { item = deleteMediaSync(this@PlaybackService, item!!) if (shouldDeleteRemoveFromQueue()) removeFromQueueSync(null, item!!) } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt index ceffe1d8..1cd226e1 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/preferences/fragments/ImportExportPreferencesFragment.kt @@ -938,7 +938,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() { it.media!!.setPosition(action.position * 1000) it.media!!.playedDuration = action.playedDuration * 1000 it.media!!.setLastPlayedTime(action.timestamp!!.time) - it.rating = if (action.isFavorite) Rating.FAVORITE.code else Rating.UNRATED.code + it.rating = if (action.isFavorite) Rating.SUPER.code else Rating.UNRATED.code it.playState = action.playState if (hasAlmostEnded(it.media!!)) { Logd(TAG, "Marking as played: $action") @@ -973,7 +973,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() { .position(media.getPosition() / 1000) .playedDuration(media.playedDuration / 1000) .total(media.getDuration() / 1000) - .isFavorite(item.isFavorite) + .isFavorite(item.isSUPER) .playState(item.playState) .build() queuedEpisodeActions.add(played) diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt index 57d311ba..637f51a3 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoCleanups.kt @@ -64,7 +64,7 @@ object AutoCleanups { val candidates: MutableList = ArrayList() val downloadedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.downloaded.name), EpisodeSortOrder.DATE_NEW_OLD) for (item in downloadedItems) { - if (item.media != null && item.media!!.downloaded && !item.isFavorite) candidates.add(item) + if (item.media != null && item.media!!.downloaded && !item.isSUPER) candidates.add(item) } return candidates } @@ -117,7 +117,7 @@ object AutoCleanups { val downloadedItems = getEpisodes(0, Int.MAX_VALUE, EpisodeFilter(EpisodeFilter.States.downloaded.name), EpisodeSortOrder.DATE_NEW_OLD) val idsInQueues = getInQueueEpisodeIds() for (item in downloadedItems) { - if (item.media != null && item.media!!.downloaded && !idsInQueues.contains(item.id) && !item.isFavorite) + if (item.media != null && item.media!!.downloaded && !idsInQueues.contains(item.id) && !item.isSUPER) candidates.add(item) } return candidates @@ -183,7 +183,7 @@ object AutoCleanups { val idsInQueues = getInQueueEpisodeIds() val mostRecentDateForDeletion = calcMostRecentDateForDeletion(Date()) for (item in downloadedItems) { - if (item.media != null && item.media!!.downloaded && !idsInQueues.contains(item.id) && item.playState >= PlayState.PLAYED.code && !item.isFavorite) { + if (item.media != null && item.media!!.downloaded && !idsInQueues.contains(item.id) && item.playState >= PlayState.PLAYED.code && !item.isSUPER) { val media = item.media // make sure this candidate was played at least the proper amount of days prior to now if (media?.playbackCompletionDate != null && media.playbackCompletionDate!!.before(mostRecentDateForDeletion)) candidates.add(item) diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt index f1db4d9a..4b607142 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/algorithms/AutoDownloads.kt @@ -123,11 +123,11 @@ object AutoDownloads { episodes = realm.query(Episode::class).query(queryString).find().toMutableList() } FeedPreferences.AutoDownloadPolicy.NEWER -> { - queryString += " AND playState < ${PlayState.SKIPPED.code} SORT(pubDate DESC) LIMIT(${3*allowedDLCount})" + queryString += " AND playState <= ${PlayState.SOON.code} SORT(pubDate DESC) LIMIT(${3*allowedDLCount})" episodes = realm.query(Episode::class).query(queryString).find().toMutableList() } FeedPreferences.AutoDownloadPolicy.OLDER -> { - queryString += " AND playState < ${PlayState.SKIPPED.code} SORT(pubDate ASC) LIMIT(${3*allowedDLCount})" + queryString += " AND playState <= ${PlayState.SOON.code} SORT(pubDate ASC) LIMIT(${3*allowedDLCount})" episodes = realm.query(Episode::class).query(queryString).find().toMutableList() } else -> {} diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt index fb8f6438..2dce6a37 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt @@ -129,7 +129,9 @@ object Episodes { episode = upsertBlk(episode) { it.media?.setfileUrlOrNull(null) if (media.downloadUrl.isNullOrEmpty()) it.media = null + it.playState = PlayState.SKIPPED.code } + EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(episode)) localDelete = true } url != null -> { @@ -145,8 +147,10 @@ object Episodes { it.media?.downloaded = false it.media?.setfileUrlOrNull(null) it.media?.hasEmbeddedPicture = false + it.playState = PlayState.SKIPPED.code if (media.downloadUrl.isNullOrEmpty()) it.media = null } + EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(episode)) } } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt index 6f0bd98a..157803a7 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt @@ -287,7 +287,6 @@ object Feeds { episode.feed = savedFeed episode.id = idLong++ episode.feedId = savedFeed.id - episode.playState = PlayState.NEW.code if (episode.media != null) { episode.media!!.id = episode.id if (!savedFeed.hasVideoMedia && episode.media!!.getMediaType() == MediaType.VIDEO) savedFeed.hasVideoMedia = true @@ -298,7 +297,8 @@ object Feeds { val pubDate = episode.getPubDate() if (pubDate == null || priorMostRecentDate == null || priorMostRecentDate.before(pubDate) || priorMostRecentDate == pubDate) { Logd(TAG, "Marking episode published on $pubDate new, prior most recent date = $priorMostRecentDate") - episode.setNew() + episode.playState = PlayState.NEW.code +// episode.setNew() if (savedFeed.preferences?.autoAddNewToQueue == true) { val q = savedFeed.preferences?.queue if (q != null) runOnIOScope { addToQueueSync(episode, q) } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Episode.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Episode.kt index 6095cff2..b56b7ca3 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Episode.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Episode.kt @@ -86,7 +86,7 @@ class Episode : RealmObject { var rating: Int = Rating.UNRATED.code @Ignore - var isFavorite: Boolean = (rating == Rating.FAVORITE.code) + var isSUPER: Boolean = (rating == Rating.SUPER.code) private set @FullText @@ -172,7 +172,8 @@ class Episode : RealmObject { media == null -> { setMedia(other.media) // reset to new if feed item did link to a file before - setNew() +// setNew() + playState = PlayState.NEW.code } media!!.compareWithOther(other.media!!) -> media!!.updateFromOther(other.media!!) } @@ -206,9 +207,9 @@ class Episode : RealmObject { this.media = media } - fun setNew() { - playState = PlayState.NEW.code - } +// fun setNew() { +// playState = PlayState.NEW.code +// } fun isPlayed(): Boolean { return playState >= PlayState.SKIPPED.code @@ -218,9 +219,9 @@ class Episode : RealmObject { playState = if (played) PlayState.PLAYED.code else PlayState.UNPLAYED.code } - fun setBuilding() { - playState = PlayState.BUILDING.code - } +// fun setBuilding() { +// playState = PlayState.BUILDING.code +// } /** * Updates this item's description property if the given argument is longer than the already stored description diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/EpisodeFilter.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/EpisodeFilter.kt index ca682005..8b0e1284 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/EpisodeFilter.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/EpisodeFilter.kt @@ -56,9 +56,9 @@ class EpisodeFilter(vararg properties_: String) : Serializable { if (properties.contains(States.unrated.name)) ratingQuerys.add(" rating == ${Rating.UNRATED.code} ") if (properties.contains(States.trash.name)) ratingQuerys.add(" rating == ${Rating.TRASH.code} ") if (properties.contains(States.bad.name)) ratingQuerys.add(" rating == ${Rating.BAD.code} ") - if (properties.contains(States.neutral.name)) ratingQuerys.add(" rating == ${Rating.NEUTRAL.code} ") + if (properties.contains(States.neutral.name)) ratingQuerys.add(" rating == ${Rating.OK.code} ") if (properties.contains(States.good.name)) ratingQuerys.add(" rating == ${Rating.GOOD.code} ") - if (properties.contains(States.favorite.name)) ratingQuerys.add(" rating == ${Rating.FAVORITE.code} ") + if (properties.contains(States.favorite.name)) ratingQuerys.add(" rating == ${Rating.SUPER.code} ") if (ratingQuerys.isNotEmpty()) { val query = StringBuilder(" (" + ratingQuerys[0]) if (ratingQuerys.size > 1) for (r in ratingQuerys.subList(1, ratingQuerys.size)) { @@ -183,9 +183,9 @@ class EpisodeFilter(vararg properties_: String) : Serializable { RATING(R.string.rating_label, ItemProperties(R.string.unrated, States.unrated.name), ItemProperties(R.string.trash, States.trash.name), ItemProperties(R.string.bad, States.bad.name), - ItemProperties(R.string.neutral, States.neutral.name), + ItemProperties(R.string.OK, States.neutral.name), ItemProperties(R.string.good, States.good.name), - ItemProperties(R.string.favorite, States.favorite.name), + ItemProperties(R.string.Super, States.favorite.name), ), PLAY_STATE(R.string.playstate, ItemProperties(R.string.unspecified, States.unspecified.name), ItemProperties(R.string.building, States.building.name), diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt index 1a81b9fa..b62a17a2 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt @@ -97,7 +97,7 @@ class Feed : RealmObject { var hasVideoMedia: Boolean = false - var rating: Int = Rating.NEUTRAL.code + var rating: Int = Rating.OK.code @FullText var comment: String = "" diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/FeedFilter.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/FeedFilter.kt index 234db64e..56f1d5a4 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/FeedFilter.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/FeedFilter.kt @@ -51,9 +51,9 @@ class FeedFilter(vararg properties_: String) : Serializable { if (properties.contains(States.unrated.name)) ratingQuerys.add(" rating == ${Rating.UNRATED.code} ") if (properties.contains(States.trash.name)) ratingQuerys.add(" rating == ${Rating.TRASH.code} ") if (properties.contains(States.bad.name)) ratingQuerys.add(" rating == ${Rating.BAD.code} ") - if (properties.contains(States.neutral.name)) ratingQuerys.add(" rating == ${Rating.NEUTRAL.code} ") + if (properties.contains(States.OK.name)) ratingQuerys.add(" rating == ${Rating.OK.code} ") if (properties.contains(States.good.name)) ratingQuerys.add(" rating == ${Rating.GOOD.code} ") - if (properties.contains(States.favorite.name)) ratingQuerys.add(" rating == ${Rating.FAVORITE.code} ") + if (properties.contains(States.Super.name)) ratingQuerys.add(" rating == ${Rating.SUPER.code} ") if (ratingQuerys.isNotEmpty()) { val query = StringBuilder(" (" + ratingQuerys[0]) if (ratingQuerys.size > 1) for (r in ratingQuerys.subList(1, ratingQuerys.size)) { @@ -120,9 +120,9 @@ class FeedFilter(vararg properties_: String) : Serializable { unrated, trash, bad, - neutral, + OK, good, - favorite, + Super, } enum class FeedFilterGroup(val nameRes: Int, vararg values_: ItemProperties) { @@ -131,9 +131,9 @@ class FeedFilter(vararg properties_: String) : Serializable { RATING(R.string.rating_label, ItemProperties(R.string.unrated, States.unrated.name), ItemProperties(R.string.trash, States.trash.name), ItemProperties(R.string.bad, States.bad.name), - ItemProperties(R.string.neutral, States.neutral.name), + ItemProperties(R.string.OK, States.OK.name), ItemProperties(R.string.good, States.good.name), - ItemProperties(R.string.favorite, States.favorite.name), + ItemProperties(R.string.Super, States.Super.name), ), HAS_VIDEO(R.string.has_video, ItemProperties(R.string.yes, States.has_video.name), ItemProperties(R.string.no, States.no_video.name)), PLAY_SPEED(R.string.play_speed, ItemProperties(R.string.global_speed, States.global_playSpeed.name), ItemProperties(R.string.custom_speed, States.custom_playSpeed.name)), diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/PlayState.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/PlayState.kt index 6f7776ff..9ac24877 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/PlayState.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/PlayState.kt @@ -1,19 +1,20 @@ package ac.mdiq.podcini.storage.model import ac.mdiq.podcini.R +import androidx.compose.ui.graphics.Color -enum class PlayState(val code: Int, val res: Int, val userSet: Boolean) { - UNSPECIFIED(-10, R.drawable.ic_questionmark, false), - BUILDING(-2, R.drawable.baseline_build_24, false), - NEW(-1, R.drawable.baseline_fiber_new_24, false), - UNPLAYED(0, R.drawable.baseline_new_label_24, true), - LATER(1, R.drawable.baseline_watch_later_24, true), - SOON(2, R.drawable.baseline_local_play_24, true), - INQUEUE(3, R.drawable.ic_playlist_play_black, false), - INPROGRESS(5, R.drawable.baseline_play_circle_outline_24, false), - SKIPPED(6, R.drawable.ic_skip_24dp, true), - PLAYED(10, R.drawable.ic_mark_played, true), // was 1 - IGNORED(20, R.drawable.baseline_visibility_off_24, true); +enum class PlayState(val code: Int, val res: Int, color: Color?, val userSet: Boolean) { + UNSPECIFIED(-10, R.drawable.ic_questionmark, null, false), + BUILDING(-2, R.drawable.baseline_build_24, null, false), + NEW(-1, R.drawable.baseline_fiber_new_24, Color.Green, false), + UNPLAYED(0, R.drawable.baseline_new_label_24, null, true), + LATER(1, R.drawable.baseline_watch_later_24, Color.Green, true), + SOON(2, R.drawable.baseline_local_play_24, Color.Green, true), + INQUEUE(3, R.drawable.ic_playlist_play_black, Color.Green, false), + INPROGRESS(5, R.drawable.baseline_play_circle_outline_24, Color.Green, false), + SKIPPED(6, R.drawable.ic_skip_24dp, null, true), + PLAYED(10, R.drawable.ic_mark_played, null, true), // was 1 + IGNORED(20, R.drawable.baseline_visibility_off_24, null, true); companion object { fun fromCode(code: Int): PlayState { diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Rating.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Rating.kt index 75962b2a..487459dd 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Rating.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/Rating.kt @@ -6,13 +6,13 @@ enum class Rating(val code: Int, val res: Int) { UNRATED(-3, R.drawable.ic_questionmark), TRASH(-2, R.drawable.ic_delete), BAD(-1, androidx.media3.session.R.drawable.media3_icon_thumb_down_filled), - NEUTRAL(0, R.drawable.baseline_sentiment_neutral_24), + OK(0, R.drawable.baseline_sentiment_neutral_24), GOOD(1, androidx.media3.session.R.drawable.media3_icon_thumb_up_filled), - FAVORITE(2, R.drawable.ic_star); + SUPER(2, R.drawable.ic_star); companion object { fun fromCode(code: Int): Rating { - return enumValues().firstOrNull { it.code == code } ?: NEUTRAL + return enumValues().firstOrNull { it.code == code } ?: OK } } } \ No newline at end of file diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt index 6fbab966..b286b417 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/EpisodeActionButton.kt @@ -81,6 +81,24 @@ abstract class EpisodeActionButton internal constructor(@JvmField var item: Epis abstract fun onClick(context: Context) + fun forItem(): EpisodeActionButton { + val media = item.media ?: return TTSActionButton(item) + val isDownloadingMedia = when (media.downloadUrl) { + null -> false + else -> DownloadServiceInterface.get()?.isDownloadingEpisode(media.downloadUrl!!)?:false + } + Logd("ItemActionButton", "forItem: local feed: ${item.feed?.isLocalFeed} downloaded: ${media.downloaded} playing: ${isCurrentlyPlaying(media)} ${item.title} ") + return when { + isCurrentlyPlaying(media) -> PauseActionButton(item) + item.feed != null && item.feed!!.isLocalFeed -> PlayLocalActionButton(item) + media.downloaded -> PlayActionButton(item) + isDownloadingMedia -> CancelDownloadActionButton(item) + isStreamOverDownload || item.feed == null || item.feedId == null || item.feed?.type == Feed.FeedType.YOUTUBE.name + || item.feed?.preferences?.prefStreamOverDownload == true -> StreamActionButton(item) + else -> DownloadActionButton(item) + } + } + @Composable fun AltActionsDialog(context: Context, showDialog: Boolean, onDismiss: () -> Unit) { if (showDialog) { @@ -127,23 +145,23 @@ abstract class EpisodeActionButton internal constructor(@JvmField var item: Epis @UnstableApi companion object { - fun forItem(episode: Episode): EpisodeActionButton { - val media = episode.media ?: return TTSActionButton(episode) - val isDownloadingMedia = when (media.downloadUrl) { - null -> false - else -> DownloadServiceInterface.get()?.isDownloadingEpisode(media.downloadUrl!!)?:false - } - Logd("ItemActionButton", "forItem: local feed: ${episode.feed?.isLocalFeed} downloaded: ${media.downloaded} playing: ${isCurrentlyPlaying(media)} ${episode.title} ") - return when { - isCurrentlyPlaying(media) -> PauseActionButton(episode) - episode.feed != null && episode.feed!!.isLocalFeed -> PlayLocalActionButton(episode) - media.downloaded -> PlayActionButton(episode) - isDownloadingMedia -> CancelDownloadActionButton(episode) - isStreamOverDownload || episode.feed == null || episode.feedId == null || episode.feed?.type == Feed.FeedType.YOUTUBE.name - || episode.feed?.preferences?.prefStreamOverDownload == true -> StreamActionButton(episode) - else -> DownloadActionButton(episode) - } - } +// fun forItem(episode: Episode): EpisodeActionButton { +// val media = episode.media ?: return TTSActionButton(episode) +// val isDownloadingMedia = when (media.downloadUrl) { +// null -> false +// else -> DownloadServiceInterface.get()?.isDownloadingEpisode(media.downloadUrl!!)?:false +// } +// Logd("ItemActionButton", "forItem: local feed: ${episode.feed?.isLocalFeed} downloaded: ${media.downloaded} playing: ${isCurrentlyPlaying(media)} ${episode.title} ") +// return when { +// isCurrentlyPlaying(media) -> PauseActionButton(episode) +// episode.feed != null && episode.feed!!.isLocalFeed -> PlayLocalActionButton(episode) +// media.downloaded -> PlayActionButton(episode) +// isDownloadingMedia -> CancelDownloadActionButton(episode) +// isStreamOverDownload || episode.feed == null || episode.feedId == null || episode.feed?.type == Feed.FeedType.YOUTUBE.name +// || episode.feed?.preferences?.prefStreamOverDownload == true -> StreamActionButton(episode) +// else -> DownloadActionButton(episode) +// } +// } fun playVideoIfNeeded(context: Context, media: Playable) { val item = (media as? EpisodeMedia)?.episode @@ -255,7 +273,6 @@ class PlayActionButton(item: Episode) : EpisodeActionButton(item) { } class DeleteActionButton(item: Episode) : EpisodeActionButton(item) { - override val visibility: Boolean get() { return item.media != null && (item.media!!.downloaded || item.feed?.isLocalFeed == true) @@ -274,6 +291,17 @@ class DeleteActionButton(item: Episode) : EpisodeActionButton(item) { } } +class NullActionButton(item: Episode) : EpisodeActionButton(item) { + override fun getLabel(): Int { + return R.string.null_label + } + override fun getDrawable(): Int { + return R.drawable.ic_questionmark + } + @UnstableApi + override fun onClick(context: Context) {} +} + class PauseActionButton(item: Episode) : EpisodeActionButton(item) { override fun getLabel(): Int { return R.string.pause_label @@ -405,7 +433,7 @@ class TTSActionButton(item: Episode) : EpisodeActionButton(item) { return } processing = 0.01f - item.setBuilding() + item.playState = PlayState.BUILDING.code EventFlow.postEvent(FlowEvent.EpisodeEvent.updated(item)) RealmDB.runOnIOScope { if (item.transcript == null) { diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt index b6ca9033..7a4a21a6 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt @@ -728,7 +728,7 @@ class VideoplayerActivity : CastEnabledActivity() { withContext(Dispatchers.Main) { Logd(TAG, "load() item ${episode?.id}") if (episode != null) { - val isFav = episode!!.isFavorite + val isFav = episode!!.isSUPER if (isFavorite != isFav) { isFavorite = isFav invalidateOptionsMenu(activity) diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt index d909b4ed..43c3f953 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/compose/EpisodesVM.kt @@ -32,8 +32,10 @@ import ac.mdiq.podcini.storage.model.Feed.Companion.newId import ac.mdiq.podcini.storage.utils.DurationConverter import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded import ac.mdiq.podcini.storage.utils.ImageResourceUtils +import ac.mdiq.podcini.ui.actions.DownloadActionButton import ac.mdiq.podcini.ui.actions.EpisodeActionButton -import ac.mdiq.podcini.ui.actions.EpisodeActionButton.Companion.forItem +//import ac.mdiq.podcini.ui.actions.EpisodeActionButton.Companion.forItem +import ac.mdiq.podcini.ui.actions.NullActionButton import ac.mdiq.podcini.ui.actions.SwipeAction import ac.mdiq.podcini.ui.activity.MainActivity import ac.mdiq.podcini.ui.fragment.EpisodeInfoFragment @@ -140,11 +142,12 @@ class EpisodeVM(var episode: Episode) { var ratingState by mutableIntStateOf(episode.rating) var inProgressState by mutableStateOf(episode.isInProgress) var downloadState by mutableIntStateOf(if (episode.media?.downloaded == true) DownloadStatus.State.COMPLETED.ordinal else DownloadStatus.State.UNKNOWN.ordinal) - var actionButton by mutableStateOf(forItem(episode)) +// var actionButton by mutableStateOf(forItem(episode)) + var actionButton by mutableStateOf(NullActionButton(episode)) var actionRes by mutableIntStateOf(actionButton.getDrawable()) var showAltActionsDialog by mutableStateOf(false) var dlPercent by mutableIntStateOf(0) - var inQueueState by mutableStateOf(curQueue.contains(episode)) +// var inQueueState by mutableStateOf(curQueue.contains(episode)) var isSelected by mutableStateOf(false) var prog by mutableFloatStateOf(0f) @@ -196,6 +199,7 @@ class EpisodeVM(var episode: Episode) { withContext(Dispatchers.Main) { positionState = changes.obj.media?.position ?: 0 inProgressState = changes.obj.isInProgress + downloadState = if (changes.obj.media?.downloaded == true) DownloadStatus.State.COMPLETED.ordinal else DownloadStatus.State.UNKNOWN.ordinal Logd("EpisodeVM", "mediaMonitor $positionState $inProgressState ${episode.title}") episode = changes.obj // Logd("EpisodeVM", "mediaMonitor downloaded: ${changes.obj.media?.downloaded} ${episode.media?.downloaded}") @@ -711,10 +715,10 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList, feed: } Logd(TAG, "long clicked: ${vm.episode.title}") })) { - LaunchedEffect(key1 = queueChanged) { - if (index >= vms.size) return@LaunchedEffect - vms[index].inQueueState = curQueue.contains(vms[index].episode) - } +// LaunchedEffect(key1 = queueChanged) { +// if (index >= vms.size) return@LaunchedEffect +// vms[index].inQueueState = curQueue.contains(vms[index].episode) +// } Row(verticalAlignment = Alignment.CenterVertically) { // Logd(TAG, "info row") val ratingIconRes = Rating.fromCode(vm.ratingState).res @@ -735,6 +739,7 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList, feed: } Text(vm.episode.title ?: "", color = textColor, maxLines = 2, overflow = TextOverflow.Ellipsis) } + var actionButton by remember(vm.episode.id) { mutableStateOf(vm.actionButton.forItem()) } fun isDownloading(): Boolean { return vms[index].downloadState > DownloadStatus.State.UNKNOWN.ordinal && vms[index].downloadState < DownloadStatus.State.COMPLETED.ordinal } @@ -744,28 +749,32 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList, feed: if (isDownloading()) vm.dlPercent = dls?.getProgress(vms[index].episode.media?.downloadUrl ?: "") ?: 0 Logd(TAG, "LaunchedEffect $index isPlayingState: ${vms[index].isPlayingState} ${vms[index].episode.title}") Logd(TAG, "LaunchedEffect $index downloadState: ${vms[index].downloadState} ${vm.episode.media?.downloaded} ${vm.dlPercent}") - vm.actionButton = forItem(vm.episode) -// vm.actionRes = vm.actionButton!!.getDrawable() + vm.actionButton = vm.actionButton.forItem() + actionButton = vm.actionButton } } else { LaunchedEffect(Unit) { Logd(TAG, "LaunchedEffect init actionButton") vm.actionButton = actionButton_(vm.episode) + actionButton = vm.actionButton // vm.actionRes = vm.actionButton!!.getDrawable() } } Box(contentAlignment = Alignment.Center, modifier = Modifier.width(40.dp).height(40.dp).padding(end = 10.dp).align(Alignment.CenterVertically) .pointerInput(Unit) { detectTapGestures(onLongPress = { vms[index].showAltActionsDialog = true }, - onTap = { vms[index].actionButton.onClick(activity) }) + onTap = { +// vms[index].actionButton.onClick(activity) + actionButton.onClick(activity) + }) }, ) { // Logd(TAG, "button box") - vm.actionRes = vm.actionButton.getDrawable() + vm.actionRes = actionButton.getDrawable() Icon(imageVector = ImageVector.vectorResource(vm.actionRes), tint = textColor, contentDescription = null, modifier = Modifier.width(28.dp).height(32.dp)) if (isDownloading() && vm.dlPercent >= 0) CircularProgressIndicator(progress = { 0.01f * vm.dlPercent }, strokeWidth = 4.dp, color = textColor, modifier = Modifier.width(30.dp).height(35.dp)) } - if (vm.showAltActionsDialog) vm.actionButton.AltActionsDialog(activity, vm.showAltActionsDialog, + if (vm.showAltActionsDialog) actionButton.AltActionsDialog(activity, vm.showAltActionsDialog, onDismiss = { vm.showAltActionsDialog = false }) } } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt index 1cf38573..2e8613c8 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AllEpisodesFragment.kt @@ -69,7 +69,7 @@ class AllEpisodesFragment : BaseEpisodesFragment() { loadItemsRunning = false } if (allEpisodes.isEmpty()) return listOf() - allEpisodes = allEpisodes.filter { filter.matchesForQueues(it) } +// allEpisodes = allEpisodes.filter { filter.matchesForQueues(it) } return allEpisodes } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt index da1d37e9..bfdbae10 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/DownloadsFragment.kt @@ -369,7 +369,7 @@ import java.util.* episodes.clear() episodes.addAll(currentDownloads) } - episodes.retainAll { filter.matchesForQueues(it) } +// episodes.retainAll { filter.matchesForQueues(it) } withContext(Dispatchers.Main) { vms.clear() for (e in episodes) vms.add(EpisodeVM(e)) diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt index 02d6b540..474007d8 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/EpisodeInfoFragment.kt @@ -220,7 +220,7 @@ class EpisodeInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener { // } // } })) - if (episode?.media != null) { + if (episode?.media != null && !inQueue) { Spacer(modifier = Modifier.weight(0.2f)) val inQueueIconRes = if (inQueue) R.drawable.ic_playlist_play else R.drawable.ic_playlist_remove Icon(imageVector = ImageVector.vectorResource(inQueueIconRes), tint = MaterialTheme.colorScheme.tertiary, contentDescription = "inQueue", diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt index 87259efa..ddd65c73 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/FeedEpisodesFragment.kt @@ -172,7 +172,7 @@ import java.util.concurrent.Semaphore requireActivity().supportFragmentManager.executePendingTransactions() } if (showFilterDialog) EpisodesFilterDialog(filter = feed!!.episodeFilter, - filtersDisabled = mutableSetOf(EpisodeFilter.EpisodesFilterGroup.DOWNLOADED, EpisodeFilter.EpisodesFilterGroup.MEDIA), +// filtersDisabled = mutableSetOf(EpisodeFilter.EpisodesFilterGroup.DOWNLOADED, EpisodeFilter.EpisodesFilterGroup.MEDIA), onDismissRequest = { showFilterDialog = false } ) { filterValues -> if (feed != null) { Logd(TAG, "persist Episode Filter(): feedId = [${feed?.id}], filterValues = [$filterValues]") @@ -238,7 +238,7 @@ import java.util.concurrent.Semaphore cancelFlowEvents() } - @kotlin.OptIn(ExperimentalFoundationApi::class) + @OptIn(ExperimentalFoundationApi::class) @Composable fun FeedEpisodesHeader(activity: MainActivity, filterButColor: Color, filterClickCB: ()->Unit, filterLongClickCB: ()->Unit) { val textColor = MaterialTheme.colorScheme.onSurface diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt index c7f0e4f7..366bc59c 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/SubscriptionsFragment.kt @@ -375,6 +375,20 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener { val feedList_ = getFeedList(fQueryStr).toMutableList() val feedOrder = feedOrderBy val dir = 1 - 2*feedOrderDir // get from 0, 1 to 1, -1 + + fun comparator(counterMap: Map, dir: Int): Comparator { + return Comparator { lhs: Feed, rhs: Feed -> + val counterLhs = counterMap[lhs.id]?:0 + val counterRhs = counterMap[rhs.id]?:0 + when { + // reverse natural order: podcast with most unplayed episodes first + counterLhs > counterRhs -> -dir + counterLhs == counterRhs -> (lhs.title?.compareTo(rhs.title!!, ignoreCase = true) ?: -1) * dir + else -> dir + } + } + } + val comparator: Comparator = when (feedOrder) { FeedSortOrder.UNPLAYED_NEW_OLD.index -> { // val queryString = "feedId == $0 AND (playState == ${PlayState.NEW.code} OR playState == ${PlayState.UNPLAYED.code})" @@ -483,19 +497,6 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener { return feedList_.sortedWith(comparator) } - private fun comparator(counterMap: Map, dir: Int): Comparator { - return Comparator { lhs: Feed, rhs: Feed -> - val counterLhs = counterMap[lhs.id]?:0 - val counterRhs = counterMap[rhs.id]?:0 - when { - // reverse natural order: podcast with most unplayed episodes first - counterLhs > counterRhs -> -dir - counterLhs == counterRhs -> (lhs.title?.compareTo(rhs.title!!, ignoreCase = true) ?: -1) * dir - else -> dir - } - } - } - @Composable fun InforBar() { Row(Modifier.padding(start = 20.dp, end = 20.dp)) { @@ -903,8 +904,8 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener { if (feed.rating != Rating.UNRATED.code) Icon(imageVector = ImageVector.vectorResource(Rating.fromCode(feed.rating).res), tint = MaterialTheme.colorScheme.tertiary, contentDescription = "rating", modifier = Modifier.background(MaterialTheme.colorScheme.tertiaryContainer).constrainAs(rating) { - start.linkTo(parent.start) - centerVerticallyTo(coverImage) + start.linkTo(coverImage.start) + bottom.linkTo(coverImage.bottom) }) // TODO: need to use state if (feed.lastUpdateFailed) Icon(imageVector = ImageVector.vectorResource(R.drawable.ic_error), tint = Color.Red, contentDescription = "error", diff --git a/app/src/main/kotlin/ac/mdiq/podcini/util/FlowEvent.kt b/app/src/main/kotlin/ac/mdiq/podcini/util/FlowEvent.kt index d39a141d..53359fbb 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/util/FlowEvent.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/util/FlowEvent.kt @@ -165,7 +165,7 @@ sealed class FlowEvent { // TODO: need better handling at receving end data class EpisodePlayedEvent(val episode: Episode? = null) : FlowEvent() - data class RatingEvent(val episode: Episode, val rating: Int = Rating.FAVORITE.code) : FlowEvent() + data class RatingEvent(val episode: Episode, val rating: Int = Rating.SUPER.code) : FlowEvent() // data class AllEpisodesFilterEvent(val filterValues: Set?) : FlowEvent() diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index cbe75c51..619b7220 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -422,7 +422,7 @@ إعادة توصيل سماعات الرأس إعادة توصيل البلوتوث أفضّل البث التدفقي - التحديث باستخدام شبكة الجوال + حدد ما يجب السماح به أثناء الاتصال على شبكة الجوال تحديث البودكاست صور الغلاف diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 7d5f5e6e..27d20916 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -372,7 +372,7 @@ Reconnexió d\'auriculars Reconnexió de Bluetooth Preferir escoltar en directe - Actualitza fent servir dades mòbils + Selecciona què és permès a la connexió de la xarxa mòbil Refrescar podcast Cobre images diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 1d457a2e..bcb81ce2 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -414,7 +414,7 @@ Opětovné připojení Bluetooth Upřednostnit streamování Zobrazit tlačítko streamovat místo tlačítka stáhnout v seznamech. - Aktualizace přes mobilní data + Vyberte, co by mělo být povoleno přes mobilní data Obnovit podcast Obrázky podcastů/epizod diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index ba2e4acf..9908b345 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -389,7 +389,7 @@ Bluetooth forbundet igen Foretræk streaming Vis stream-knap i stedet for overfør-knap i lister - Mobilopdateringer + Vælg hvad der skal være tilladt via mobil dataforbindelse Opdatering af podcast Billeder diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 562cbedd..82704745 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -393,7 +393,7 @@ Bluetooth wieder verbunden Streaming bevorzugen Stream-Button anstatt Download-Button in Listen anzeigen - Mobile Aktualisierungen + Auswählen, was über mobile Daten erlaubt sein soll Aktualisierung der Podcasts Titelbilder diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index dadba586..d25fc2c0 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -404,7 +404,7 @@ Reconectar con Bluetooth Preferir escuchar en directo Mostrar el botón de escuchar en directo en vez del botón de descarga en las listas - Actualizaciones vía datos móviles + Seleccionar lo que se debe permitir descargar con datos móviles Actualizar podcast Imágenes de portada diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 3c0413c5..6041945f 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -376,7 +376,7 @@ وصل دوبارهٔ گوشی وصل دوبارهٔ بلوتوث ترجیح جریان - به‌روز رسانی‌های همراه + آنچه که باید از طریق اتصال داده تلفن همراه مجاز است را انتخاب کنید تازه سازی پادکست تصویر جلد diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 83c8bca4..f7c8cdd8 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -366,7 +366,7 @@ Kuulokkeiden uudelleenyhdistyminen Bluetoothin uudelleenyhdistyminen Suosi suoratoistoa - Mobiilipäivitykset + Valitse, mikä on sallittua mobiiliyhteydellä Podcastien päivitys Kansikuvat diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4bf5625e..cb054bd7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -405,7 +405,7 @@ Connexion du Bluetooth Préférer le streaming Afficher dans les listes le bouton du streaming au lieu de celui du téléchargement - Utilisation de la connexion mobile + Choisir ce qui est autorisé lorsque la connexion mobile est utilisée Mise à jour des podcasts Récupération des images diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 03eeaa03..94edf0b2 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -388,7 +388,7 @@ Reconexión bluetooth Preferir retransmisión Nas listas, mostrar botón de difusión no lugar do botón de descarga - Actualización con móbil + Escolle o que estará permitido utilizando conexión de datos do móbil Actualizar podcast Imaxes de portadas diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index c90b5888..427aa598 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -405,7 +405,7 @@ Riconnessione Bluetooth Preferisci streaming Negli elenchi mostra il tasto stream al posto del tasto download - Aggiornamenti su rete mobile + Seleziona quali operazioni sono consentite su reti mobili Aggiornamento podcast Copertine diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 94349bb4..1c6ec95d 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -413,7 +413,7 @@ חיבור Bluetooth מחדש העדפת הזרמה הצגת כפתור הזרמה במקום כפתור הורדה ברשימות - עדכונים דרך רשת סלולרית + לבחור מה מותר דרך חיבור רשת סלולרית רענון פודקאסטים תמונות נושא diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 41f0564c..6ef4cc6d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -357,7 +357,7 @@ 헤드폰 재연결 블루투스 다시 연결 스트리밍 선호 - 휴대전화 망 업데이트 + 휴대전화 데이터 연결을 통해 무엇을 허용할지 선택합니다. 팟캐스트 새로 고침 커버 이미지 diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 01f45fca..188a280d 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -364,7 +364,7 @@ Gjeninnkopling av hodetelefoner Blutetooth tilkoblet igjen Foretrekk strømming - Mobiloppdateringer + Velg hva som skal tillates over mobildata Last podkast på nytt Cover-bilder diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 780cabad..dbd5703b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -380,7 +380,7 @@ Fones de ouvido ou Bluetooth desconectado Fones de ouvido reconectados Preferir streaming - Atualização usando dados móveis + Selecione o que deve ser permitido na conexão de dados móveis Atualizar podcast Imagens de capa diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 26310d62..36b2e599 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -404,7 +404,7 @@ Ligação bluetooth Preferir emissão Mostrar botão de emissão em vez do botão para descarregar - Dados móveis + Selecione o que pode ser permitido através de dados móveis Atualização de podcasts Descarga de imagens diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index a82f18ee..5215cc01 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -401,7 +401,7 @@ Reconectare Bluetooth Preferă streamingul Afișează butonul de stream în locul butonului de descărcare - Actualizări mobile + Selectează ce ar trebui să fie permis să folosească conexiunea de date mobile Reîmprospătare podcast Imagine de copertă diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index f31fc2b9..ea407ef4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -393,7 +393,7 @@ При подключении наушников При подключении Bluetooth Трансляция вместо загрузки - Обновления в мобильной сети + Выберите, что разрешено загружать через мобильное подключение Обновление подкастов Обложки diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index d65494b9..71eb674b 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -413,7 +413,7 @@ Bluetooth znovu pripojené Uprednostniť streamovanie V zoznamoch zobraziť tlačidlo streamovať namiesto tlačidla stiahnuť - Mobilná aktualizácia + Vyberte, co by malo byť povolené cez mobilné dáta Obnoviť podcast Obrázky podcastov/epizód diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 8d20ad5a..4fbb3b5b 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -389,7 +389,7 @@ Blutetooth återansluts Föredra strömmning Visa knappen för strömming iställer för nedladdning i listor - Mobila uppdateringar + Välj vad som ska tillåtas över mobila dataanslutningar Uppdatera podcasts Omslagsbilder diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 131c8984..a983d178 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -374,7 +374,7 @@ Kulaklıklar yeniden bağlanıyor Bluetooth yeniden bağlanıyor İndirmeden dinle - Mobil güncellemeler + Mobil veri üzerinden nelere izin verileceğini seçiniz Podcast yenileme Kapak görselleri diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index ee0edc43..6c2c6d18 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -413,7 +413,7 @@ Повторне підключення через Bluetooth Надавати перевагу стрімінгу Відображати кнопку стріму замість кнопки завантаження у списках - Оновлення через мобільні дані + Виберіть, що має бути дозволено через мобільне з\'єднання для передачі даних Оновлення подкасту Обкладинки зображень diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 7c727009..c786442b 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -381,7 +381,7 @@ 蓝牙重连 偏好在线 在列表中显示在线播放按钮而不是下载按钮 - 移动数据更新 + 选择使用移动数据连接时应当允许的内容 播客刷新 封面图片 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index f951daa2..93767890 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -68,7 +68,6 @@ @string/pref_mobileUpdate_images @string/synchronization_pref - feed_refresh episode_download diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 56a1045e..fa1db407 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -256,6 +256,7 @@ Stream Erase episodes Reserve episodes + Null Delete Unable to delete file. Rebooting the device could help. Unable to delete file. Try re-connecting the local folder from the podcast info screen. @@ -303,9 +304,9 @@ Unrated Trash Bad - Neutral + OK Good - Favorite + Super Set rating Play state Unspecified @@ -520,7 +521,7 @@ Display stream button instead of download button in lists Prefer low quality on mobile On metered network, only low quality media (if available) is fetched - Mobile updates + Metered network settings Select what should be allowed over the mobile data connection Podcast refresh Cover images diff --git a/app/src/main/res/xml/preferences_downloads.xml b/app/src/main/res/xml/preferences_downloads.xml index c5ad734c..4685a5db 100644 --- a/app/src/main/res/xml/preferences_downloads.xml +++ b/app/src/main/res/xml/preferences_downloads.xml @@ -53,7 +53,7 @@ android:entryValues="@array/mobile_update_values" android:key="prefMobileUpdateTypes" android:summary="@string/pref_mobileUpdate_sum" - android:title="@string/pref_mobileUpdate_title"/> + android:title="@string/pref_metered_network_title"/> OK, Favorite -> Super +* in EpisodeInfo header, only show "add to queue" icon when the episode is not in queue +* in-queue icon is no longer shown on episodes lists +* reduced start lag when opening a large episodes list +* likely fixed the action button not updating issue after download in episodes lists +* in grid layout of Subscriptions view, moved the rating icon to the lower left corner +* in FeedEpisodes view, enabled Downloaded and HasMedia filters +* changed in Settings -> Downloads, "Mobile updates" to "Metered network settings" + * the setting applies to metered mobile and wifi networks + # 6.12.7 * fixed issue in auto-download where number of played is not correctly counted -* in AutoDownloadPolicy, Newer or Older now means include episodes with playState not being Skipped, Played, and Ignored +* in AutoDownloadPolicy, Newer or Older now include episodes with playState not being Skipped, Played, and Ignored * in Subscriptions sorting, Played means Skipped, Played, or Ignored, Unplayed means any state lower than Skipped * fixed high CPU usage in Download view * removed a few useless classes and the useless test modules diff --git a/fastlane/metadata/android/en-US/changelogs/3020286.txt b/fastlane/metadata/android/en-US/changelogs/3020286.txt new file mode 100644 index 00000000..dc7c17ec --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3020286.txt @@ -0,0 +1,13 @@ + Version 6.12.8 + +* set episode's playState to Skipped when its media file is removed +* in AutoDownloadPolicy, Newer or Older now include episodes with playState of New, Unplayed, Later and Soon +* naming change in Rating: Neutral -> OK, Favorite -> Super +* in EpisodeInfo header, only show "add to queue" icon when the episode is not in queue +* in-queue icon is no longer shown on episodes lists +* reduced start lag when opening a large episodes list +* likely fixed the action button not updating issue after download in episodes lists +* in grid layout of Subscriptions view, moved the rating icon to the lower left corner +* in FeedEpisodes view, enabled Downloaded and HasMedia filters +* changed in Settings -> Downloads, "Mobile updates" to "Metered network settings" + * the setting applies to metered mobile and wifi networks