diff --git a/README.md b/README.md index 7f931caf..f720fd12 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c * More convenient player control displayed on all pages * Revamped and more efficient expanded player view showing episode description on the front * Playback speed setting has been straightened up, three speed can be set separately or combined: current audio, podcast, and global +* There are two mechanisms in updating playback progress (configurable in Settings): every 5 seconds or adaptively at the interval of 2 percent of the media duration +* Volume adaptation control is added to player detailed view to set for current media and it takes precedence over that in feed settings * Added preference "Fast Forward Speed" under "Playback" in settings with default value of 0.0, dialog allows setting a number between 0.0 and 10.0 * The "Skip to next episode" button on the player * long-press moves to the next episode @@ -95,6 +97,7 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c * List info is shown in Queue and Downloads views * Local search for feeds or episodes can be separately specified on title, author(feed only), description(including transcript in episodes), and comment (My opinion) * Left and right swipe actions on lists now have telltales and can be configured on the spot +* Swipe actions are brought to perform anything on the multi-select menu, and there is a Combo swipe action * Played or new episodes have clearer markings * Sort dialog no longer dims the main view * An all new way of filtering for both podcasts and episodes with expanded criteria @@ -113,9 +116,9 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c * Every feed (podcast) can be associated with a queue allowing downloaded media to be added to the queue * FeedInfo view offers a link for direct search of feeds related to author * FeedInfo view has button showing number of episodes to open the FeedEpisodes view -* instead of isFavorite, there is a new rating system for every episode: Trash, Bad, Neutral, Good, Favorite -* instead of Played or Unplayed, there is a new play state system Unspecified, Building, New, Unplayed, Later, Soon, InQueue, InProgress, Skipped, Played, Ignored - * among which Unplayed, Later, Soon, Skipped, Played, Ignored are settable by the user +* instead of isFavorite, there is a new rating system for every episode: Trash, Bad, OK, Good, Super +* instead of Played or Unplayed, there is a new play state system Unspecified, Building, New, Unplayed, Later, Soon, InQueue, InProgress, Skipped, Played, Again, Forever, Ignored + * among which Unplayed, Later, Soon, Skipped, Played, Again, Forever, Ignored are settable by the user * when an episode is started to play, its state is set to InProgress * when episode is added to a queue, its state is set to InQueue, when it's removed from a queue, the state (if lower than Skipped) is set to Skipped * in EpisodeInfo view, one can enter personal comments/notes under "My opinion" for the episode @@ -155,7 +158,7 @@ While podcast subscriptions' OPML files (from AntennaPod or any other sources) c * auto download algorithm is changed to individual feed based. * When auto download is enabled in the Settings, feeds to be auto-downloaded need to be separately enabled in the feed settings. - * Each feed also has its own download policy (only new episodes, newest episodes, and oldest episodes. "newest episodes" meaning most recent episodes, new or old) + * Each feed also has its own download policy (only new episodes, newest episodes, oldest episodes or episodes marked as Soon. "newest episodes" meaning most recent episodes, new or old) * Each feed has its own limit (Episode cache) for number of episodes downloaded, this limit rules in combination of the overall limit for the app. * Auto downloads run feeds or feed refreshes, scheduled or manual * auto download always includes any undownloaded episodes (regardless of feeds) added in the Default queue diff --git a/app/build.gradle b/app/build.gradle index 102057bd..6f38231e 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 3020287 - versionName "6.13.0" + versionCode 3020288 + versionName "6.13.1" applicationId "ac.mdiq.podcini.R" def commit = "" 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 14648e5a..74e8c49f 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 @@ -384,7 +384,8 @@ class PlaybackService : MediaLibraryService() { Logd(TAG, "onPlaybackStart position: $position") val delayInterval = positionUpdateInterval(playable.getDuration()) taskManager.startWidgetUpdater(delayInterval) - if (position != Playable.INVALID_TIME) playable.setPosition(position + (delayInterval/2).toInt()) +// if (position != Playable.INVALID_TIME) playable.setPosition(position + (delayInterval/2).toInt()) + if (position != Playable.INVALID_TIME) playable.setPosition(position) else skipIntro(playable) playable.onPlaybackStart() taskManager.startPositionSaver(delayInterval) 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 9ac24877..b7d5e20b 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 @@ -6,14 +6,16 @@ import androidx.compose.ui.graphics.Color 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), + NEW(-1, R.drawable.outline_new_releases_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), + SOON(2, R.drawable.baseline_access_alarms_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 + PLAYED(10, R.drawable.ic_check, null, true), // was 1 + AGAIN(12, R.drawable.baseline_replay_24, null, true), + FOREVER(15, R.drawable.baseline_light_mode_24, null, true), IGNORED(20, R.drawable.baseline_visibility_off_24, null, true); companion object { diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt index b0c06b96..500d2eb5 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt @@ -27,15 +27,15 @@ interface SwipeAction { enum class ActionTypes { NO_ACTION, COMBO, + RATING, + SET_PLAY_STATE, ADD_TO_QUEUE, PUT_TO_QUEUE, - START_DOWNLOAD, - MARK_FAV, - SET_PLAY_STATE, - SHELVE, - ERASE, REMOVE_FROM_QUEUE, + START_DOWNLOAD, DELETE, - REMOVE_FROM_HISTORY + REMOVE_FROM_HISTORY, + SHELVE, + ERASE } } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt index 2495a03c..89db227b 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeActions.kt @@ -163,6 +163,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String) Surface(shape = RoundedCornerShape(16.dp)) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { for (action in swipeActions) { + if (action.getId() == NO_ACTION.name || action.getId() == ActionTypes.COMBO.name) continue Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(4.dp).clickable { action.performAction(item, fragment, filter) showDialog = false @@ -212,7 +213,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String) class SetRatingSwipeAction : SwipeAction { override fun getId(): String { - return ActionTypes.MARK_FAV.name + return ActionTypes.RATING.name } override fun getActionIcon(): Int { return R.drawable.ic_star @@ -221,7 +222,7 @@ open class SwipeActions(private val fragment: Fragment, private val tag: String) return R.attr.icon_yellow } override fun getTitle(context: Context): String { - return context.getString(R.string.switch_rating_label) + return context.getString(R.string.set_rating_label) } @OptIn(UnstableApi::class) override fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter) { 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 58f65ef4..fecaaf9a 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 @@ -30,6 +30,7 @@ import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk import ac.mdiq.podcini.storage.model.* import ac.mdiq.podcini.storage.model.Feed.Companion.MAX_SYNTHETIC_ID import ac.mdiq.podcini.storage.model.Feed.Companion.newId +import ac.mdiq.podcini.storage.model.PlayState.Companion.fromCode import ac.mdiq.podcini.storage.utils.DurationConverter import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded import ac.mdiq.podcini.storage.utils.ImageResourceUtils @@ -692,13 +693,14 @@ fun EpisodeLazyColumn(activity: MainActivity, vms: MutableList, feed: if (selectMode) toggleSelected() else if (vm.episode.feed != null) activity.loadChildFragment(FeedInfoFragment.newInstance(vm.episode.feed!!)) })) - val alpha = if (vm.playedState >= PlayState.SKIPPED.code) 1.0f else 0f - if (vm.playedState >= PlayState.SKIPPED.code) Icon(imageVector = ImageVector.vectorResource(R.drawable.ic_check), tint = textColor, contentDescription = "played_mark", - modifier = Modifier.background(Color.Green).alpha(alpha) - .constrainAs(checkMark) { - bottom.linkTo(parent.bottom) - end.linkTo(parent.end) - }) + if (vm.playedState >= PlayState.SKIPPED.code) { + Icon(imageVector = ImageVector.vectorResource(fromCode(vm.playedState).res), tint = textColor, contentDescription = "play state", + modifier = Modifier.background(Color.Green.copy(alpha = 0.6f)).width(20.dp).height(20.dp) + .constrainAs(checkMark) { + bottom.linkTo(parent.bottom) + end.linkTo(parent.end) + }) + } } Column(Modifier.weight(1f).padding(start = 6.dp, end = 6.dp) .combinedClickable(onClick = { diff --git a/app/src/main/res/drawable/baseline_access_alarms_24.xml b/app/src/main/res/drawable/baseline_access_alarms_24.xml new file mode 100644 index 00000000..4779e29b --- /dev/null +++ b/app/src/main/res/drawable/baseline_access_alarms_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_av_timer_24.xml b/app/src/main/res/drawable/baseline_av_timer_24.xml new file mode 100644 index 00000000..a200cd60 --- /dev/null +++ b/app/src/main/res/drawable/baseline_av_timer_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_light_mode_24.xml b/app/src/main/res/drawable/baseline_light_mode_24.xml new file mode 100644 index 00000000..385a20e9 --- /dev/null +++ b/app/src/main/res/drawable/baseline_light_mode_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_replay_24.xml b/app/src/main/res/drawable/baseline_replay_24.xml new file mode 100644 index 00000000..de6f5a2a --- /dev/null +++ b/app/src/main/res/drawable/baseline_replay_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/outline_new_releases_24.xml b/app/src/main/res/drawable/outline_new_releases_24.xml new file mode 100644 index 00000000..e347f947 --- /dev/null +++ b/app/src/main/res/drawable/outline_new_releases_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a26c920f..194aa208 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -298,7 +298,6 @@ Play video Add to favorites - Swtich rating Toggle favorites Media type Unknown diff --git a/changelog.md b/changelog.md index f7a139b4..aa9ea6c4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,10 @@ +# 6.13.1 + +* fixed the misbehavior (from 6.13.0) of rewind/forward/progress in PlayerUI +* added Again and Forever in PlayState, and changed some PlayState icons +* in episodes list, when an episode's play state is higher than Skipped, state icon (rather than only a check) is on the cover image +* in Combo swipe actions, removed NoAction and ComboAction + # 6.13.0 * updates playback position adaptively (in app and in widget) in an interval being the longer of 5 seconds and 2 percent of the media duration diff --git a/fastlane/metadata/android/en-US/changelogs/3020288.txt b/fastlane/metadata/android/en-US/changelogs/3020288.txt new file mode 100644 index 00000000..7c92954b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3020288.txt @@ -0,0 +1,6 @@ + Version 6.13.1 + +* fixed the misbehavior (from 6.13.0) of rewind/forward/progress in PlayerUI +* added Again and Forever in PlayState, and changed some PlayState icons +* in episodes list, when an episode's play state is higher than Skipped, state icon (rather than only a check) is on the cover image +* in Combo swipe actions, removed NoAction and ComboAction