diff --git a/app/build.gradle b/app/build.gradle index bb47167c..686defd3 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 3020250 - versionName "6.6.5" + versionCode 3020251 + versionName "6.6.6" applicationId "ac.mdiq.podcini.R" def commit = "" diff --git a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt index b7adccb3..c200519e 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt @@ -25,18 +25,39 @@ object InTheatre { var curEpisode: Episode? = null // unmanged set(value) { - field = if (value != null) unmanaged(value) else null - if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = unmanaged(field!!.media!!) + when { + value != null -> { + field = unmanaged(value) + if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = unmanaged(field!!.media!!) + } + else -> { + field = null + if (curMedia != null) curMedia = null + } + } +// field = if (value != null) unmanaged(value) else null +// if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = unmanaged(field!!.media!!) } var curMedia: Playable? = null // unmanged if EpisodeMedia set(value) { - if (value is EpisodeMedia) { - field = unmanaged(value) - if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = unmanaged(value.episode!!) - } else { - field = value + when { + value is EpisodeMedia -> { + field = unmanaged(value) + if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = unmanaged(value.episode!!) + } + value == null -> { + field = null + if (curEpisode != null) curEpisode = null + } + else -> field = value } +// if (value is EpisodeMedia) { +// field = unmanaged(value) +// if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = unmanaged(value.episode!!) +// } else { +// field = value +// } } var curState: CurrentState // managed 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 a8e1a5ea..d4a9bd7f 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 @@ -66,6 +66,7 @@ import ac.mdiq.podcini.util.FlowEvent.PlayEvent.Action import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast import ac.mdiq.podcini.util.Logd import ac.mdiq.podcini.util.config.ClientConfig +import ac.mdiq.podcini.util.showStackTrace import ac.mdiq.vista.extractor.MediaFormat import ac.mdiq.vista.extractor.stream.AudioStream import ac.mdiq.vista.extractor.stream.DeliveryMethod @@ -1073,8 +1074,8 @@ class PlaybackService : MediaLibraryService() { // Logd(TAG, "onQueueEvent: ending playback curEpisode ${curEpisode?.title}") notifyCurQueueItemsChanged() for (e in event.episodes) { - Logd(TAG, "onQueueEvent: queue event removed ${e.title}") if (e.id == curEpisode?.id) { + Logd(TAG, "onQueueEvent: queue event removed ${e.title}") mPlayer?.endPlayback(hasEnded = false, wasSkipped = true, shouldContinue = true, toStoppedState = true) break } @@ -1758,18 +1759,18 @@ class PlaybackService : MediaLibraryService() { override fun setVolume(volumeLeft: Float, volumeRight: Float) { var volumeLeft = volumeLeft var volumeRight = volumeRight + Logd(TAG, "setVolume: $volumeLeft $volumeRight") val playable = curMedia if (playable is EpisodeMedia) { val preferences = playable.episodeOrFetch()?.feed?.preferences if (preferences != null) { val volumeAdaptionSetting = preferences.volumeAdaptionSetting - if (volumeAdaptionSetting != null) { - val adaptionFactor = volumeAdaptionSetting.adaptionFactor - volumeLeft *= adaptionFactor - volumeRight *= adaptionFactor - } + val adaptionFactor = volumeAdaptionSetting.adaptionFactor + volumeLeft *= adaptionFactor + volumeRight *= adaptionFactor } } + Logd(TAG, "setVolume 1: $volumeLeft $volumeRight") if (volumeLeft > 1) { exoPlayer?.volume = 1f loudnessEnhancer?.setEnabled(true) @@ -1869,6 +1870,7 @@ class PlaybackService : MediaLibraryService() { val position = getPosition() if (position >= 0) curMedia?.setPosition(position) Logd(TAG, "endPlayback hasEnded=$hasEnded wasSkipped=$wasSkipped shouldContinue=$shouldContinue toStoppedState=$toStoppedState") +// showStackTrace() val currentMedia = curMedia var nextMedia: Playable? = null @@ -2563,9 +2565,7 @@ class PlaybackService : MediaLibraryService() { playbackService?.mPlayer?.prepare() playbackService?.taskManager?.restartSleepTimer() } - else -> { - Log.w(TAG, "Play/Pause button was pressed and PlaybackService state was unknown") - } + else -> Log.w(TAG, "Play/Pause button was pressed and PlaybackService state was unknown") } } 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 62a6a0d1..2f89abda 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 @@ -25,11 +25,10 @@ import ac.mdiq.podcini.storage.model.EpisodeMedia import ac.mdiq.podcini.storage.model.EpisodeSortOrder import ac.mdiq.podcini.storage.utils.EpisodesPermutors.getPermutor import ac.mdiq.podcini.storage.utils.FilesUtils.getMediafilename -import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast -import ac.mdiq.podcini.util.Logd import ac.mdiq.podcini.util.EventFlow import ac.mdiq.podcini.util.FlowEvent -import ac.mdiq.vista.extractor.playlist.PlaylistInfo +import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast +import ac.mdiq.podcini.util.Logd import ac.mdiq.vista.extractor.stream.StreamInfo import ac.mdiq.vista.extractor.stream.StreamInfoItem import android.app.backup.BackupManager @@ -240,10 +239,13 @@ object Episodes { * @param date PlaybackCompletionDate for `media` */ fun addToHistory(episode: Episode, date: Date? = Date()) : Job { - Logd(TAG, "addToHistory called") + Logd(TAG, "addToHistory called played: ${episode.playState}") return runOnIOScope { - upsert(episode) { it.media?.playbackCompletionDate = date } - EventFlow.postEvent(FlowEvent.HistoryEvent()) + val episode_ = realm.query(Episode::class).query("id == $0", episode.id).first().find() + if (episode_ != null) { + upsert(episode_) { it.media?.playbackCompletionDate = date } + EventFlow.postEvent(FlowEvent.HistoryEvent()) + } } } @@ -274,7 +276,7 @@ object Episodes { @OptIn(UnstableApi::class) suspend fun setPlayStateSync(played: Int, resetMediaPosition: Boolean, episode: Episode) : Episode { - Logd(TAG, "setPlayStateSync called resetMediaPosition: $resetMediaPosition") + Logd(TAG, "setPlayStateSync called played: $played resetMediaPosition: $resetMediaPosition ${episode.title}") val result = upsert(episode) { if (played >= PlayState.NEW.code && played <= PlayState.BUILDING.code) it.playState = played else { @@ -284,6 +286,7 @@ object Episodes { if (resetMediaPosition) it.media?.setPosition(0) } if (played == PlayState.PLAYED.code && shouldMarkedPlayedRemoveFromQueues()) removeFromAllQueuesSync(result) + Logd(TAG, "setPlayStateSync played: ${result.playState}") EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(result)) return result } diff --git a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/VolumeAdaptionSetting.kt b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/VolumeAdaptionSetting.kt index c5ad3d31..820e5d1e 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/storage/model/VolumeAdaptionSetting.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/storage/model/VolumeAdaptionSetting.kt @@ -6,9 +6,12 @@ enum class VolumeAdaptionSetting(private val value: Int, @JvmField val adaptionF OFF(0, 1.0f, R.string.feed_volume_reduction_off), LIGHT_REDUCTION(1, 0.5f, R.string.feed_volume_reduction_light), HEAVY_REDUCTION(2, 0.2f, R.string.feed_volume_reduction_heavy), - LIGHT_BOOST(3, 1.5f, R.string.feed_volume_boost_light), - MEDIUM_BOOST(4, 2f, R.string.feed_volume_boost_medium), - HEAVY_BOOST(5, 2.5f, R.string.feed_volume_boost_heavy); +// LIGHT_BOOST(3, 1.5f, R.string.feed_volume_boost_light), +// MEDIUM_BOOST(4, 2f, R.string.feed_volume_boost_medium), +// HEAVY_BOOST(5, 2.5f, R.string.feed_volume_boost_heavy); + LIGHT_BOOST(3, 2f, R.string.feed_volume_boost_light), + MEDIUM_BOOST(4, 4f, R.string.feed_volume_boost_medium), + HEAVY_BOOST(5, 7f, R.string.feed_volume_boost_heavy); fun toInteger(): Int { return value diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt index d2b82f88..ef78c73a 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/activity/MainActivity.kt @@ -32,9 +32,9 @@ import ac.mdiq.podcini.ui.utils.LockableBottomSheetBehavior import ac.mdiq.podcini.ui.utils.ThemeUtils.getDrawableFromAttr import ac.mdiq.podcini.ui.utils.TransitionEffect import ac.mdiq.podcini.ui.view.EpisodesRecyclerView -import ac.mdiq.podcini.util.Logd import ac.mdiq.podcini.util.EventFlow import ac.mdiq.podcini.util.FlowEvent +import ac.mdiq.podcini.util.Logd import android.Manifest import android.annotation.SuppressLint import android.content.ComponentName 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 b479509b..acc846c5 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 @@ -76,7 +76,7 @@ import kotlin.math.min } if (allEpisodes.isEmpty()) return listOf() allEpisodes = allEpisodes.filter { filter.matchesForQueues(it) } - return allEpisodes.subList(0, min(allEpisodes.size-1, page * EPISODES_PER_PAGE)) + return allEpisodes.subList(0, min(allEpisodes.size, page * EPISODES_PER_PAGE)) } override fun loadMoreData(page: Int): List { diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt index 8d885b37..fa4a340b 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt @@ -170,7 +170,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar cardViewSeek = binding.cardViewSeek initDetailedView() - + (activity as MainActivity).setPlayerVisible(false) return binding.root } @@ -199,7 +199,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar if (isCollapsed) { isCollapsed = false playerUI = playerUI2 - playerUI?.updateUi(currentMedia) + if (currentMedia != null) playerUI?.updateUi(currentMedia!!) playerUI?.butPlay?.setIsShowPlay(isShowPlay) playerDetailsFragment?.updateInfo() } @@ -209,7 +209,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar Logd(TAG, "onCollaped()") isCollapsed = true playerUI = playerUI1 - playerUI?.updateUi(currentMedia) + if (currentMedia != null) playerUI?.updateUi(currentMedia!!) playerUI?.butPlay?.setIsShowPlay(isShowPlay) } @@ -256,7 +256,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar val item = (currentMedia as? EpisodeMedia)?.episodeOrFetch() if (item != null) playerDetailsFragment?.setItem(item) updateUi() - playerUI?.updateUi(currentMedia) + if (currentMedia != null) playerUI?.updateUi(currentMedia!!) // TODO: disable for now // if (!includingChapters) loadMediaInfo(true) }.invokeOnCompletion { throwable -> @@ -363,7 +363,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar val media = event.media ?: return if (currentMedia?.getIdentifier() == null || media.getIdentifier() != currentMedia?.getIdentifier()) { currentMedia = media - playerUI?.updateUi(currentMedia) + playerUI?.updateUi(currentMedia!!) playerDetailsFragment?.setItem(curEpisode!!) } playerUI?.onPositionUpdate(event) @@ -707,7 +707,9 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar fun onPlaybackServiceChanged(event: FlowEvent.PlaybackServiceEvent) { when (event.action) { FlowEvent.PlaybackServiceEvent.Action.SERVICE_SHUT_DOWN -> (activity as MainActivity).setPlayerVisible(false) - FlowEvent.PlaybackServiceEvent.Action.SERVICE_STARTED -> (activity as MainActivity).setPlayerVisible(true) + FlowEvent.PlaybackServiceEvent.Action.SERVICE_STARTED -> { + if (curMedia != null) (activity as MainActivity).setPlayerVisible(true) + } // PlaybackServiceEvent.Action.SERVICE_RESTARTED -> (activity as MainActivity).setPlayerVisible(true) } } @@ -736,9 +738,9 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar } } @UnstableApi - fun updateUi(media: Playable?) { + fun updateUi(media: Playable) { Logd(TAG, "updateUi called $media") - if (media == null) return +// if (media == null) return binding.titleView.text = media.getEpisodeTitle() // (activity as MainActivity).setPlayerVisible(true) onPositionUpdate(FlowEvent.PlaybackPositionEvent(media, media.getPosition(), media.getDuration())) @@ -815,7 +817,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { Logd(TAG, "fragment onCreateView") - _binding = PlayerDetailsFragmentBinding.inflate(inflater) + _binding = PlayerDetailsFragmentBinding.inflate(inflater, container, false) val colorFilter: ColorFilter? = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(binding.txtvPodcastTitle.currentTextColor, BlendModeCompat.SRC_IN) binding.butNextChapter.colorFilter = colorFilter diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt index 758b946f..73d5074b 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/HistoryFragment.kt @@ -171,7 +171,7 @@ import kotlin.math.min loadItemsRunning = false } if (allHistory.isEmpty()) return listOf() - return allHistory.subList(0, min(allHistory.size-1, page * EPISODES_PER_PAGE)) + return allHistory.subList(0, min(allHistory.size, page * EPISODES_PER_PAGE)) } override fun loadMoreData(page: Int): List { diff --git a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt index 70ddaae0..46919d62 100644 --- a/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt +++ b/app/src/main/kotlin/ac/mdiq/podcini/ui/fragment/OnlineFeedFragment.kt @@ -597,7 +597,7 @@ class OnlineFeedFragment : Fragment() { val feed1 = getFeed(feedId, true)?: return if (feed1.preferences == null) feed1.preferences = FeedPreferences(feed1.id, false, FeedPreferences.AutoDeleteAction.GLOBAL, VolumeAdaptionSetting.OFF, "", "") - if (feedSource != "VistaGuide") { + if (feedSource == "VistaGuide") { feed1.preferences!!.prefStreamOverDownload = true feed1.preferences!!.autoDownload = false } else if (isEnableAutodownload) { @@ -823,7 +823,7 @@ class OnlineFeedFragment : Fragment() { } override fun loadData(): List { if (episodeList.isEmpty()) return listOf() - return episodeList.subList(0, min(episodeList.size-1, page * EPISODES_PER_PAGE)) + return episodeList.subList(0, min(episodeList.size, page * EPISODES_PER_PAGE)) } override fun loadMoreData(page: Int): List { val offset = (page - 1) * EPISODES_PER_PAGE diff --git a/build.gradle b/build.gradle index afb1d008..08e3bb7a 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ buildscript { plugins { alias(libs.plugins.compose.compiler) apply false - id 'io.realm.kotlin' version '2.1.0' apply false + id 'io.realm.kotlin' version '2.3.0' apply false } allprojects { diff --git a/changelog.md b/changelog.md index 367c4600..cc684b28 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,13 @@ +# 6.6.6 + +* fixed difference between the count of episodes and the actual number of episodes (seen when the number is small) in History, AllEpisodes, and OnlineFeed views +* fixed an error (introduced in 6.6.3) in setting feed preferences when subscribing one +* upon start, if no previously played media, the player is set invisible +* fixed an issue of fully played episode not correctly recorded as such when Podcini is in the background +* volume adaptation numbers were changed from 0.2, 0.5, 1, 1.5, 2, 2.5 to 0.2, 0.5, 1, 2, 4, 7 (the max boost being 6dB) +* Kotlin upped to 2.0.20 +* Realm upped to 2.3.0 + # 6.6.5 * fixed the issue of subscriptions not filtered correctly. diff --git a/fastlane/metadata/android/en-US/changelogs/3020251.txt b/fastlane/metadata/android/en-US/changelogs/3020251.txt new file mode 100644 index 00000000..73fdaee3 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/3020251.txt @@ -0,0 +1,9 @@ + Version 6.6.6: + +* fixed difference between the count of episodes and the actual number of episodes (seen when the number is small) in History, AllEpisodes, and OnlineFeed views +* fixed an error (introduced in 6.6.3) in setting feed preferences when subscribing one +* upon start, if no previously played media, the player is set invisible +* fixed an issue of fully played episode not correctly recorded as such when Podcini is in the background +* volume adaptation numbers were changed from 0.2, 0.5, 1, 1.5, 2, 2.5 to 0.2, 0.5, 1, 2, 4, 7 (the max boost being 6dB) +* Kotlin upped to 2.0.20 +* Realm upped to 2.3.0 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 70a44f6d..44bc4fc1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] -kotlin = "2.0.10" +kotlin = "2.0.20" [plugins] org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }