diff --git a/app/src/androidTest/java/ac/test/podcini/EspressoTestUtils.kt b/app/src/androidTest/java/ac/test/podcini/EspressoTestUtils.kt index 19573f5f..0725c1c8 100644 --- a/app/src/androidTest/java/ac/test/podcini/EspressoTestUtils.kt +++ b/app/src/androidTest/java/ac/test/podcini/EspressoTestUtils.kt @@ -171,7 +171,7 @@ object EspressoTestUtils { init(InstrumentationRegistry.getInstrumentation().targetContext) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() } diff --git a/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceMediaPlayerTest.kt b/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceMediaPlayerTest.kt index 6e04a6ac..d0eb9276 100644 --- a/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceMediaPlayerTest.kt +++ b/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceMediaPlayerTest.kt @@ -108,11 +108,11 @@ class PlaybackServiceMediaPlayerTest { f.preferences = prefs f.items = mutableListOf() val i = FeedItem(0, "t", "i", "l", Date(), FeedItem.UNPLAYED, f) - f.items!!.add(i) + f.items.add(i) val media = FeedMedia(0, i, 0, 0, 0, "audio/wav", fileUrl, downloadUrl, fileUrl != null, null, 0, 0) i.setMedia(media) val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(f) Assert.assertTrue(media.id != 0L) adapter.close() @@ -130,14 +130,18 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - countDownLatch.countDown() - } else { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - countDownLatch.countDown() + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 2L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + countDownLatch.countDown() + } + else -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + countDownLatch.countDown() + } } } catch (e: AssertionFailedError) { if (assertionError == null) assertionError = e @@ -168,14 +172,18 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - countDownLatch.countDown() - } else { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - countDownLatch.countDown() + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 2L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + countDownLatch.countDown() + } + else -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + countDownLatch.countDown() + } } } catch (e: AssertionFailedError) { if (assertionError == null) assertionError = e @@ -207,16 +215,22 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 4L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - } else if (countDownLatch.count == 3L) { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) - } else if (countDownLatch.count == 1L) { - Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 4L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + } + 3L -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + } + 2L -> { + Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) + } + 1L -> { + Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + } } countDownLatch.countDown() } catch (e: AssertionFailedError) { @@ -247,18 +261,25 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 5L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - } else if (countDownLatch.count == 4L) { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - } else if (countDownLatch.count == 3L) { - Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) - } else if (countDownLatch.count == 1L) { - Assert.assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus) + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 5L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + } + 4L -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + } + 3L -> { + Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) + } + 2L -> { + Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + } + 1L -> { + Assert.assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus) + } } countDownLatch.countDown() } catch (e: AssertionFailedError) { @@ -288,14 +309,18 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - countDownLatch.countDown() - } else { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - countDownLatch.countDown() + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 2L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + countDownLatch.countDown() + } + else -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + countDownLatch.countDown() + } } } catch (e: AssertionFailedError) { if (assertionError == null) assertionError = e @@ -325,14 +350,18 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - countDownLatch.countDown() - } else { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - countDownLatch.countDown() + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 2L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + countDownLatch.countDown() + } + else -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + countDownLatch.countDown() + } } } catch (e: AssertionFailedError) { if (assertionError == null) assertionError = e @@ -362,16 +391,22 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 4L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - } else if (countDownLatch.count == 3L) { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) - } else if (countDownLatch.count == 1L) { - Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 4L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + } + 3L -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + } + 2L -> { + Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) + } + 1L -> { + Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + } } countDownLatch.countDown() } catch (e: AssertionFailedError) { @@ -401,18 +436,25 @@ class PlaybackServiceMediaPlayerTest { try { checkPSMPInfo(newInfo) check(newInfo!!.playerStatus != PlayerStatus.ERROR) { "MediaPlayer error" } - if (countDownLatch.count == 0L) { - Assert.fail() - } else if (countDownLatch.count == 5L) { - Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) - } else if (countDownLatch.count == 4L) { - Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) - } else if (countDownLatch.count == 3L) { - Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) - } else if (countDownLatch.count == 2L) { - Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) - } else if (countDownLatch.count == 1L) { - Assert.assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus) + when (countDownLatch.count) { + 0L -> { + Assert.fail() + } + 5L -> { + Assert.assertEquals(PlayerStatus.INITIALIZING, newInfo.playerStatus) + } + 4L -> { + Assert.assertEquals(PlayerStatus.INITIALIZED, newInfo.playerStatus) + } + 3L -> { + Assert.assertEquals(PlayerStatus.PREPARING, newInfo.playerStatus) + } + 2L -> { + Assert.assertEquals(PlayerStatus.PREPARED, newInfo.playerStatus) + } + 1L -> { + Assert.assertEquals(PlayerStatus.PLAYING, newInfo.playerStatus) + } } } catch (e: AssertionFailedError) { if (assertionError == null) assertionError = e diff --git a/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceTaskManagerTest.kt b/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceTaskManagerTest.kt index 457dd5a1..32caf647 100644 --- a/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceTaskManagerTest.kt +++ b/app/src/androidTest/java/ac/test/podcini/service/playback/PlaybackServiceTaskManagerTest.kt @@ -43,7 +43,7 @@ class PlaybackServiceTaskManagerTest { init(context) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() setShakeToReset(false) setVibrate(false) @@ -61,15 +61,15 @@ class PlaybackServiceTaskManagerTest { val f = Feed(0, null, "title", "link", "d", null, null, null, null, "id", null, "null", "url", false) f.items = mutableListOf() for (i in 0 until NUM_ITEMS) { - f.items!!.add(FeedItem(0, pref + i, pref + i, "link", Date(), FeedItem.PLAYED, f)) + f.items.add(FeedItem(0, pref + i, pref + i, "link", Date(), FeedItem.PLAYED, f)) } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(f) - adapter.setQueue(f.items!!) + adapter.setQueue(f.items) adapter.close() - for (item in f.items!!) { + for (item in f.items) { Assert.assertTrue(item.id != 0L) } return f.items diff --git a/app/src/androidTest/java/ac/test/podcini/ui/UITestUtils.kt b/app/src/androidTest/java/ac/test/podcini/ui/UITestUtils.kt index 3008acb0..ba72be17 100644 --- a/app/src/androidTest/java/ac/test/podcini/ui/UITestUtils.kt +++ b/app/src/androidTest/java/ac/test/podcini/ui/UITestUtils.kt @@ -189,7 +189,7 @@ class UITestUtils(private val context: Context) { localFeedDataAdded = true val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(*hostedFeeds.toTypedArray()) adapter.setQueue(queue) adapter.close() diff --git a/app/src/main/java/ac/mdiq/podcini/activity/MainActivity.kt b/app/src/main/java/ac/mdiq/podcini/activity/MainActivity.kt index d0ffa184..c0835f61 100644 --- a/app/src/main/java/ac/mdiq/podcini/activity/MainActivity.kt +++ b/app/src/main/java/ac/mdiq/podcini/activity/MainActivity.kt @@ -35,6 +35,7 @@ import com.google.android.material.snackbar.Snackbar import ac.mdiq.podcini.R import ac.mdiq.podcini.core.preferences.ThemeSwitcher.getNoTitleTheme import ac.mdiq.podcini.core.receiver.MediaButtonReceiver.Companion.createIntent +import ac.mdiq.podcini.core.storage.DBReader import ac.mdiq.podcini.core.sync.queue.SynchronizationQueueSink import ac.mdiq.podcini.core.util.download.FeedUpdateManager import ac.mdiq.podcini.core.util.download.FeedUpdateManager.restartUpdateAlarm @@ -103,6 +104,8 @@ class MainActivity : CastEnabledActivity() { .build() } + DBReader.updateFeedList() + val fm = supportFragmentManager if (fm.findFragmentByTag(MAIN_FRAGMENT_TAG) == null) { if (UserPreferences.DEFAULT_PAGE_REMEMBER != defaultPage) { diff --git a/app/src/main/java/ac/mdiq/podcini/activity/OnlineFeedViewActivity.kt b/app/src/main/java/ac/mdiq/podcini/activity/OnlineFeedViewActivity.kt index b8b57397..74a3c19f 100644 --- a/app/src/main/java/ac/mdiq/podcini/activity/OnlineFeedViewActivity.kt +++ b/app/src/main/java/ac/mdiq/podcini/activity/OnlineFeedViewActivity.kt @@ -423,7 +423,7 @@ class OnlineFeedViewActivity : AppCompatActivity() { viewBinding.titleLabel.text = feed.title viewBinding.authorLabel.text = feed.author - headerBinding.txtvDescription.text = HtmlToPlainText.getPlainText(feed.description) + headerBinding.txtvDescription.text = HtmlToPlainText.getPlainText(feed.description?:"") viewBinding.subscribeButton.setOnClickListener { v: View? -> if (feedInFeedlist()) { diff --git a/app/src/main/java/ac/mdiq/podcini/activity/VideoplayerActivity.kt b/app/src/main/java/ac/mdiq/podcini/activity/VideoplayerActivity.kt index 973d18a3..16d7cf25 100644 --- a/app/src/main/java/ac/mdiq/podcini/activity/VideoplayerActivity.kt +++ b/app/src/main/java/ac/mdiq/podcini/activity/VideoplayerActivity.kt @@ -1,28 +1,7 @@ package ac.mdiq.podcini.activity -import ac.mdiq.podcini.activity.MainActivity -import android.content.DialogInterface -import android.content.Intent -import android.graphics.PixelFormat -import android.graphics.drawable.ColorDrawable -import android.media.AudioManager -import android.os.Build -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.util.Log -import android.view.* -import android.view.View.OnTouchListener -import android.view.animation.* -import android.widget.EditText -import android.widget.FrameLayout -import android.widget.SeekBar -import android.widget.SeekBar.OnSeekBarChangeListener -import androidx.interpolator.view.animation.FastOutSlowInInterpolator -import androidx.media3.common.util.UnstableApi -import com.bumptech.glide.Glide -import com.google.android.material.dialog.MaterialAlertDialogBuilder import ac.mdiq.podcini.R +import ac.mdiq.podcini.activity.MainActivity import ac.mdiq.podcini.core.service.playback.PlaybackService.Companion.getPlayerActivityIntent import ac.mdiq.podcini.core.service.playback.PlaybackService.Companion.isCasting import ac.mdiq.podcini.core.storage.DBReader @@ -53,6 +32,27 @@ import ac.mdiq.podcini.storage.preferences.UserPreferences.rewindSecs import ac.mdiq.podcini.storage.preferences.UserPreferences.setShowRemainTimeSetting import ac.mdiq.podcini.storage.preferences.UserPreferences.shouldShowRemainingTime import ac.mdiq.podcini.ui.appstartintent.MainActivityStarter +import android.content.DialogInterface +import android.content.Intent +import android.graphics.PixelFormat +import android.graphics.drawable.ColorDrawable +import android.media.AudioManager +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.view.* +import android.view.View.OnTouchListener +import android.view.animation.* +import android.widget.EditText +import android.widget.FrameLayout +import android.widget.SeekBar +import android.widget.SeekBar.OnSeekBarChangeListener +import androidx.interpolator.view.animation.FastOutSlowInInterpolator +import androidx.media3.common.util.UnstableApi +import com.bumptech.glide.Glide +import com.google.android.material.dialog.MaterialAlertDialogBuilder import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable diff --git a/app/src/main/java/ac/mdiq/podcini/adapter/FeedItemlistDescriptionAdapter.kt b/app/src/main/java/ac/mdiq/podcini/adapter/FeedItemlistDescriptionAdapter.kt index 424f88da..a679dc4f 100644 --- a/app/src/main/java/ac/mdiq/podcini/adapter/FeedItemlistDescriptionAdapter.kt +++ b/app/src/main/java/ac/mdiq/podcini/adapter/FeedItemlistDescriptionAdapter.kt @@ -49,10 +49,10 @@ class FeedItemlistDescriptionAdapter(context: Context, resource: Int, objects: L holder.title!!.text = item!!.title holder.pubDate!!.text = formatAbbrev(context, item.pubDate) if (item.description != null) { - val description = HtmlToPlainText.getPlainText(item.description) - ?.replace("\n".toRegex(), " ") - ?.replace("\\s+".toRegex(), " ") - ?.trim { it <= ' ' } + val description = HtmlToPlainText.getPlainText(item.description!!) + .replace("\n".toRegex(), " ") + .replace("\\s+".toRegex(), " ") + .trim { it <= ' ' } holder.description!!.text = description holder.description!!.maxLines = MAX_LINES_COLLAPSED } diff --git a/app/src/main/java/ac/mdiq/podcini/dialog/PlaybackControlsDialog.kt b/app/src/main/java/ac/mdiq/podcini/dialog/PlaybackControlsDialog.kt index 33288697..fee532b9 100644 --- a/app/src/main/java/ac/mdiq/podcini/dialog/PlaybackControlsDialog.kt +++ b/app/src/main/java/ac/mdiq/podcini/dialog/PlaybackControlsDialog.kt @@ -19,7 +19,7 @@ class PlaybackControlsDialog : DialogFragment() { @UnstableApi override fun onStart() { super.onStart() - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { setupAudioTracks() } diff --git a/app/src/main/java/ac/mdiq/podcini/dialog/SleepTimerDialog.kt b/app/src/main/java/ac/mdiq/podcini/dialog/SleepTimerDialog.kt index 4991aa64..e69a8546 100644 --- a/app/src/main/java/ac/mdiq/podcini/dialog/SleepTimerDialog.kt +++ b/app/src/main/java/ac/mdiq/podcini/dialog/SleepTimerDialog.kt @@ -46,7 +46,7 @@ class SleepTimerDialog : DialogFragment() { @UnstableApi override fun onStart() { super.onStart() - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { } } diff --git a/app/src/main/java/ac/mdiq/podcini/dialog/VariableSpeedDialog.kt b/app/src/main/java/ac/mdiq/podcini/dialog/VariableSpeedDialog.kt index ccc7c57a..f2f79747 100644 --- a/app/src/main/java/ac/mdiq/podcini/dialog/VariableSpeedDialog.kt +++ b/app/src/main/java/ac/mdiq/podcini/dialog/VariableSpeedDialog.kt @@ -42,7 +42,7 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() { @UnstableApi override fun onStart() { super.onStart() - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { updateSpeed(SpeedChangedEvent(controller!!.currentPlaybackSpeedMultiplier)) } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/AudioPlayerFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/AudioPlayerFragment.kt index 28099238..cf6e1b62 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/AudioPlayerFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/AudioPlayerFragment.kt @@ -279,7 +279,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar } private fun newPlaybackController(): PlaybackController { - return object : PlaybackController(activity) { + return object : PlaybackController(requireActivity()) { override fun updatePlayButtonShowsPlay(showPlay: Boolean) { butPlay.setIsShowPlay(showPlay) } @@ -295,10 +295,10 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar } private fun updateUi(media: Playable?) { - if (controller == null || media == null) { + if (controller != null) duration = controller!!.duration + if (media == null) { return } - duration = controller!!.duration updatePosition(PlaybackPositionEvent(media.getPosition(), media.getDuration())) updatePlaybackSpeedButton(SpeedChangedEvent(PlaybackSpeedUtils.getCurrentPlaybackSpeed(media))) setChapterDividers(media) @@ -460,7 +460,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar val isFeedMedia = media is FeedMedia toolbar.menu?.findItem(R.id.open_feed_item)?.setVisible(isFeedMedia) - if (isFeedMedia) { + if (media != null && isFeedMedia) { FeedItemMenuHandler.onPrepareMenu(toolbar.menu, (media as FeedMedia).getItem()) } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/ChaptersFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/ChaptersFragment.kt index 8d5499f4..bc71513b 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/ChaptersFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/ChaptersFragment.kt @@ -91,7 +91,7 @@ class ChaptersFragment : AppCompatDialogFragment() { CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT) recyclerView.layoutParams = wrapHeight - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { this@ChaptersFragment.loadMediaInfo(false) } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/CoverFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/CoverFragment.kt index c32d6bb5..cc239717 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/CoverFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/CoverFragment.kt @@ -56,6 +56,7 @@ import org.greenrobot.eventbus.ThreadMode */ class CoverFragment : Fragment() { private lateinit var viewBinding: CoverFragmentBinding + private var controller: PlaybackController? = null private var disposable: Disposable? = null private var displayedChapterIndex = -1 @@ -80,7 +81,7 @@ class CoverFragment : Fragment() { viewBinding.butPrevChapter.setOnClickListener { v: View? -> seekToPrevChapter() } viewBinding.butNextChapter.setOnClickListener { v: View? -> seekToNextChapter() } - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { this@CoverFragment.loadMediaInfo(false) } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/ExternalPlayerFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/ExternalPlayerFragment.kt index 70171267..329ae7a4 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/ExternalPlayerFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/ExternalPlayerFragment.kt @@ -89,7 +89,7 @@ class ExternalPlayerFragment : Fragment() { if (controller == null) { return@setOnClickListener } - if (controller!!.getMedia() != null && controller!!.getMedia()!!.getMediaType() == MediaType.VIDEO && controller!!.status != PlayerStatus.PLAYING) { + if (controller!!.getMedia()?.getMediaType() == MediaType.VIDEO && controller!!.status != PlayerStatus.PLAYING) { controller!!.playPause() requireContext().startActivity(getPlayerActivityIntent(requireContext(), controller!!.getMedia()!!)) } else { @@ -101,7 +101,7 @@ class ExternalPlayerFragment : Fragment() { @UnstableApi private fun setupPlaybackController(): PlaybackController { - return object : PlaybackController(activity) { + return object : PlaybackController(requireActivity()) { override fun updatePlayButtonShowsPlay(showPlay: Boolean) { butPlay.setIsShowPlay(showPlay) } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/FeedInfoFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/FeedInfoFragment.kt index e4e71f79..1a4fd516 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/FeedInfoFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/FeedInfoFragment.kt @@ -195,7 +195,7 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener { txtvTitle.text = feed!!.title txtvTitle.setMaxLines(6) - val description: String = HtmlToPlainText.getPlainText(feed!!.description)?:"" + val description: String = HtmlToPlainText.getPlainText(feed!!.description?:"") txtvDescription.text = description diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/ItemDescriptionFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/ItemDescriptionFragment.kt index c2b2debf..7f335cdf 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/ItemDescriptionFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/ItemDescriptionFragment.kt @@ -55,7 +55,7 @@ class ItemDescriptionFragment : Fragment() { } }) registerForContextMenu(webvDescription) - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { load() } @@ -91,10 +91,12 @@ class ItemDescriptionFragment : Fragment() { return@create } if (media is FeedMedia) { - if (media.getItem() == null) { - media.setItem(DBReader.getFeedItem(media.itemId)) + var item = media.getItem() + if (item == null) { + item = DBReader.getFeedItem(media.itemId) + media.setItem(item) } - if (media.getItem() != null) DBReader.loadDescriptionOfFeedItem(media.getItem()!!) + if (item != null && item.description == null) DBReader.loadDescriptionOfFeedItem(item) } val shownotesCleaner = ShownotesCleaner(context, media.getDescription()?:"", media.getDuration()) emitter.onSuccess(shownotesCleaner.processShownotes()) diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/ItemFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/ItemFragment.kt index b730aba1..4d336962 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/ItemFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/ItemFragment.kt @@ -156,7 +156,7 @@ class ItemFragment : Fragment() { }) EventBus.getDefault().register(this) - controller = object : PlaybackController(activity) { + controller = object : PlaybackController(requireActivity()) { override fun loadMediaInfo() { // Do nothing } diff --git a/app/src/main/java/ac/mdiq/podcini/fragment/QueueFragment.kt b/app/src/main/java/ac/mdiq/podcini/fragment/QueueFragment.kt index 9c9e0292..b4d065a2 100644 --- a/app/src/main/java/ac/mdiq/podcini/fragment/QueueFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/fragment/QueueFragment.kt @@ -459,7 +459,7 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda } private fun loadItems(restoreScrollPosition: Boolean) { - Log.d(TAG, "loadItems()") + Log.d(TAG, "loadItems() called") disposable?.dispose() if (queue.isEmpty()) { diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/HomeFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/HomeFragment.kt index 15a92a06..4afbbbec 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/HomeFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/HomeFragment.kt @@ -97,10 +97,11 @@ class HomeFragment : Fragment(), Toolbar.OnMenuItemClickListener { } private fun addSection(section: Fragment?) { + if (section == null) return val containerView = FragmentContainerView(requireContext()) containerView.id = View.generateViewId() viewBinding.homeContainer.addView(containerView) - if (section != null) childFragmentManager.beginTransaction().add(containerView.id, section).commit() + childFragmentManager.beginTransaction().add(containerView.id, section).commit() } private fun getSection(tag: String): Fragment? { diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/DownloadsSection.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/DownloadsSection.kt index 411ee673..b437de9d 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/DownloadsSection.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/DownloadsSection.kt @@ -31,7 +31,8 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class DownloadsSection : HomeSection() { - private var adapter: EpisodeItemListAdapter? = null + private lateinit var adapter: EpisodeItemListAdapter + private var disposable: Disposable? = null @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -50,7 +51,7 @@ class DownloadsSection : HomeSection() { } } } - adapter?.setDummyViews(NUM_EPISODES) + adapter.setDummyViews(NUM_EPISODES) viewBinding.recyclerView.adapter = adapter val swipeActions = SwipeActions(this, CompletedDownloadsFragment.TAG) @@ -75,10 +76,7 @@ class DownloadsSection : HomeSection() { @UnstableApi @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(event: PlaybackPositionEvent) { - if (adapter == null) { - return - } - for (i in 0 until adapter!!.itemCount) { + for (i in 0 until adapter.itemCount) { val holder: EpisodeItemViewHolder? = viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder if (holder != null && holder.isCurrentlyPlayingItem) { holder.notifyPlaybackPositionUpdated(event) @@ -117,8 +115,8 @@ class DownloadsSection : HomeSection() { if (downloads.size > NUM_EPISODES) { downloads = downloads.subList(0, NUM_EPISODES) } - adapter?.setDummyViews(0) - adapter?.updateItems(downloads) + adapter.setDummyViews(0) + adapter.updateItems(downloads) }, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) }) } diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/EpisodesSurpriseSection.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/EpisodesSurpriseSection.kt index 8fc1f90b..66819caa 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/EpisodesSurpriseSection.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/EpisodesSurpriseSection.kt @@ -29,7 +29,8 @@ import org.greenrobot.eventbus.ThreadMode import java.util.* class EpisodesSurpriseSection : HomeSection() { - private var listAdapter: HorizontalItemListAdapter? = null + private lateinit var listAdapter: HorizontalItemListAdapter + private var disposable: Disposable? = null private var episodes: MutableList = ArrayList() @@ -52,7 +53,7 @@ class EpisodesSurpriseSection : HomeSection() { } } } - listAdapter?.setDummyViews(NUM_EPISODES) + listAdapter.setDummyViews(NUM_EPISODES) viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) viewBinding.recyclerView.adapter = listAdapter val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt() @@ -94,7 +95,7 @@ class EpisodesSurpriseSection : HomeSection() { if (pos >= 0) { episodes.removeAt(pos) episodes.add(pos, item) - listAdapter?.notifyItemChangedCompat(pos) + listAdapter.notifyItemChangedCompat(pos) } i++ } @@ -104,17 +105,14 @@ class EpisodesSurpriseSection : HomeSection() { fun onEventMainThread(event: EpisodeDownloadEvent) { for (downloadUrl in event.urls) { val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(episodes, downloadUrl) - if (pos >= 0) listAdapter?.notifyItemChangedCompat(pos) + if (pos >= 0) listAdapter.notifyItemChangedCompat(pos) } } @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(event: PlaybackPositionEvent) { - if (listAdapter == null) { - return - } - for (i in 0 until listAdapter!!.itemCount) { + for (i in 0 until listAdapter.itemCount) { val holder: HorizontalItemViewHolder? = viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder if (holder != null && holder.isCurrentlyPlayingItem) { holder.notifyPlaybackPositionUpdated(event) @@ -131,8 +129,8 @@ class EpisodesSurpriseSection : HomeSection() { .observeOn(AndroidSchedulers.mainThread()) .subscribe({ episodes: List -> this.episodes = episodes.toMutableList() - listAdapter?.setDummyViews(0) - listAdapter?.updateData(episodes) + listAdapter.setDummyViews(0) + listAdapter.updateData(episodes) }, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) }) } diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/InboxSection.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/InboxSection.kt index 0c856564..d169da97 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/InboxSection.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/InboxSection.kt @@ -32,7 +32,8 @@ import org.greenrobot.eventbus.ThreadMode import java.util.* class InboxSection : HomeSection() { - private var adapter: EpisodeItemListAdapter? = null + private lateinit var adapter: EpisodeItemListAdapter + private var items: List = ArrayList() private var disposable: Disposable? = null @@ -51,7 +52,7 @@ class InboxSection : HomeSection() { ) { item: MenuItem -> this@InboxSection.onContextItemSelected(item) } } } - adapter?.setDummyViews(NUM_EPISODES) + adapter.setDummyViews(NUM_EPISODES) viewBinding.recyclerView.adapter = adapter val swipeActions = SwipeActions(this, InboxFragment.TAG) @@ -89,7 +90,7 @@ class InboxSection : HomeSection() { for (downloadUrl in event.urls) { val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(items, downloadUrl) if (pos >= 0) { - adapter?.notifyItemChangedCompat(pos) + adapter.notifyItemChangedCompat(pos) } } } @@ -112,8 +113,8 @@ class InboxSection : HomeSection() { .observeOn(AndroidSchedulers.mainThread()) .subscribe({ data: Pair, Int> -> items = data.first - adapter?.setDummyViews(0) - adapter?.updateItems(items) + adapter.setDummyViews(0) + adapter.updateItems(items) viewBinding.numNewItemsLabel.visibility = View.VISIBLE if (data.second >= 100) { viewBinding.numNewItemsLabel.text = String.format(Locale.getDefault(), "%d+", 99) diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/QueueSection.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/QueueSection.kt index 09e0c56c..8b707319 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/QueueSection.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/QueueSection.kt @@ -29,9 +29,10 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class QueueSection : HomeSection() { - private var listAdapter: HorizontalItemListAdapter? = null private var disposable: Disposable? = null - private var queue: MutableList? = ArrayList() + + private lateinit var listAdapter: HorizontalItemListAdapter + private var queue: MutableList = ArrayList() @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -44,7 +45,7 @@ class QueueSection : HomeSection() { ) { item: MenuItem -> this@QueueSection.onContextItemSelected(item) } } } - listAdapter?.setDummyViews(NUM_EPISODES) + listAdapter.setDummyViews(NUM_EPISODES) viewBinding.recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) viewBinding.recyclerView.adapter = listAdapter val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt() @@ -74,18 +75,18 @@ class QueueSection : HomeSection() { @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(event: FeedItemEvent) { Log.d(TAG, "onEventMainThread() called with: event = [$event]") - if (queue == null) { + if (queue.isEmpty()) { return } var i = 0 val size: Int = event.items.size while (i < size) { val item: FeedItem = event.items[i] - val pos: Int = FeedItemUtil.indexOfItemWithId(queue!!, item.id) + val pos: Int = FeedItemUtil.indexOfItemWithId(queue, item.id) if (pos >= 0) { - queue!!.removeAt(pos) - queue!!.add(pos, item) - listAdapter?.notifyItemChangedCompat(pos) + queue.removeAt(pos) + queue.add(pos, item) + listAdapter.notifyItemChangedCompat(pos) } i++ } @@ -93,23 +94,20 @@ class QueueSection : HomeSection() { @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) fun onEventMainThread(event: EpisodeDownloadEvent) { - if (queue == null) return + if (queue.isEmpty()) return for (downloadUrl in event.urls) { - val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(queue!!, downloadUrl) + val pos: Int = FeedItemUtil.indexOfItemWithDownloadUrl(queue, downloadUrl) if (pos >= 0) { - listAdapter?.notifyItemChangedCompat(pos) + listAdapter.notifyItemChangedCompat(pos) } } } @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(event: PlaybackPositionEvent) { - if (listAdapter == null) { - return - } var foundCurrentlyPlayingItem = false var currentlyPlayingItemIsFirst = true - for (i in 0 until listAdapter!!.itemCount) { + for (i in 0 until listAdapter.itemCount) { val holder: HorizontalItemViewHolder = viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? HorizontalItemViewHolder ?: continue if (holder.isCurrentlyPlayingItem) { @@ -140,8 +138,8 @@ class QueueSection : HomeSection() { .observeOn(AndroidSchedulers.mainThread()) .subscribe({ queue: List -> this.queue = queue.toMutableList() - listAdapter?.setDummyViews(0) - listAdapter?.updateData(queue) + listAdapter.setDummyViews(0) + listAdapter.updateData(queue) }, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) }) } diff --git a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/SubscriptionsSection.kt b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/SubscriptionsSection.kt index 31298b54..56ed2846 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/home/sections/SubscriptionsSection.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/home/sections/SubscriptionsSection.kt @@ -27,7 +27,7 @@ import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode class SubscriptionsSection : HomeSection() { - private var listAdapter: HorizontalFeedListAdapter? = null + private lateinit var listAdapter: HorizontalFeedListAdapter private var disposable: Disposable? = null @UnstableApi override fun onCreateView(inflater: LayoutInflater, @@ -45,7 +45,7 @@ class SubscriptionsSection : HomeSection() { } } } - listAdapter?.setDummyViews(NUM_FEEDS) + listAdapter.setDummyViews(NUM_FEEDS) viewBinding.recyclerView.adapter = listAdapter val paddingHorizontal: Int = (12 * resources.displayMetrics.density).toInt() viewBinding.recyclerView.setPadding(paddingHorizontal, 0, paddingHorizontal, 0) @@ -93,8 +93,8 @@ class SubscriptionsSection : HomeSection() { feeds.add(stats[i].feed) i++ } - listAdapter?.setDummyViews(0) - listAdapter?.updateData(feeds) + listAdapter.setDummyViews(0) + listAdapter.updateData(feeds) }, { error: Throwable? -> Log.e(TAG, Log.getStackTraceString(error)) }) } diff --git a/core/src/main/java/ac/mdiq/podcini/core/feed/ChapterMerger.kt b/core/src/main/java/ac/mdiq/podcini/core/feed/ChapterMerger.kt index 247dbc6e..5e98c041 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/feed/ChapterMerger.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/feed/ChapterMerger.kt @@ -33,13 +33,13 @@ object ChapterMerger { return if (score(chapters1) > score(chapters2)) chapters1 else chapters2 } - if (TextUtils.isEmpty(chapterTarget.imageUrl)) { + if (chapterTarget.imageUrl.isNullOrEmpty()) { chapterTarget.imageUrl = chapterOther.imageUrl } - if (TextUtils.isEmpty(chapterTarget.link)) { + if (chapterTarget.link.isNullOrEmpty()) { chapterTarget.link = chapterOther.link } - if (TextUtils.isEmpty(chapterTarget.title)) { + if (chapterTarget.title.isNullOrEmpty()) { chapterTarget.title = chapterOther.title } } @@ -54,9 +54,9 @@ object ChapterMerger { var score = 0 for (chapter in chapters) { score = (score - + (if (TextUtils.isEmpty(chapter.title)) 0 else 1) - + (if (TextUtils.isEmpty(chapter.link)) 0 else 1) - + (if (TextUtils.isEmpty(chapter.imageUrl)) 0 else 1)) + + (if (chapter.title.isNullOrEmpty()) 0 else 1) + + (if (chapter.link.isNullOrEmpty()) 0 else 1) + + (if (chapter.imageUrl.isNullOrEmpty()) 0 else 1)) } return score } diff --git a/core/src/main/java/ac/mdiq/podcini/core/service/playback/LocalPSMP.kt b/core/src/main/java/ac/mdiq/podcini/core/service/playback/LocalPSMP.kt index 52764932..2f426aa8 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/service/playback/LocalPSMP.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/service/playback/LocalPSMP.kt @@ -38,9 +38,8 @@ import kotlin.concurrent.Volatile * Manages the MediaPlayer object of the PlaybackService. */ @UnstableApi -class LocalPSMP(context: Context, - callback: PSMPCallback -) : PlaybackServiceMediaPlayer(context, callback) { +class LocalPSMP(context: Context, callback: PSMPCallback) : PlaybackServiceMediaPlayer(context, callback) { + private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager @Volatile diff --git a/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackService.kt b/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackService.kt index 1a994e3e..4ae2435b 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackService.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackService.kt @@ -1863,7 +1863,7 @@ class PlaybackService : MediaBrowserServiceCompat() { private const val TAG = "PlaybackService" // TODO: need to experiment this value - private const val POSITION_EVENT_INTERVAL = 10L + private const val POSITION_EVENT_INTERVAL = 5L const val ACTION_PLAYER_STATUS_CHANGED: String = "action.ac.mdiq.podcini.core.service.playerStatusChanged" private const val AVRCP_ACTION_PLAYER_STATUS_CHANGED = "com.android.music.playstatechanged" diff --git a/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackServiceTaskManager.kt b/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackServiceTaskManager.kt index e50abda9..1763ebf0 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackServiceTaskManager.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/service/playback/PlaybackServiceTaskManager.kt @@ -212,12 +212,10 @@ class PlaybackServiceTaskManager(private val context: Context, */ @Synchronized fun startChapterLoader(media: Playable) { - if (chapterLoaderFuture != null) { - chapterLoaderFuture!!.dispose() - chapterLoaderFuture = null - } + chapterLoaderFuture?.dispose() + chapterLoaderFuture = null - if (media.getChapters().isEmpty()) { + if (!media.chaptersLoaded()) { chapterLoaderFuture = Completable.create { emitter: CompletableEmitter -> ChapterUtils.loadChapters(media, context, false) emitter.onComplete() diff --git a/core/src/main/java/ac/mdiq/podcini/core/storage/DBReader.kt b/core/src/main/java/ac/mdiq/podcini/core/storage/DBReader.kt index 462ee638..9bf5b825 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/storage/DBReader.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/storage/DBReader.kt @@ -30,6 +30,7 @@ import kotlin.math.min */ object DBReader { private const val TAG = "DBReader" + private var feeds: MutableList = mutableListOf() /** * Maximum size of the list returned by [.getDownloadLog]. @@ -38,36 +39,52 @@ object DBReader { @JvmStatic fun getFeedList(): List { - Log.d(TAG, "Extracting Feedlist") + return feeds +// Log.d(TAG, "Extracting Feedlist") + +// val adapter = getInstance() +// adapter.open() +// try { +// return getFeedList(adapter) +// } finally { +// adapter.close() +// } + } + +// fun getFeedList(adapter: PodDBAdapter): List { +// if (feeds != null) return feeds!! +// updateFeedList(adapter) +// return feeds!! +// } + + fun updateFeedList() { val adapter = getInstance() - adapter!!.open() + adapter.open() try { - return getFeedList(adapter) + updateFeedList(adapter) } finally { adapter.close() } } - fun getFeedList(adapter: PodDBAdapter?): List { - adapter!!.allFeedsCursor.use { cursor -> - val feeds: MutableList = ArrayList(cursor.count) + fun updateFeedList(adapter: PodDBAdapter) { + adapter.allFeedsCursor.use { cursor -> + feeds = ArrayList(cursor.count) while (cursor.moveToNext()) { val feed = extractFeedFromCursorRow(cursor) feeds.add(feed) } - return feeds } } @JvmStatic fun getFeedListDownloadUrls(): List { val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.feedCursorDownloadUrls.use { cursor -> - val result: MutableList = - ArrayList(cursor.count) + val result: MutableList = ArrayList(cursor.count) while (cursor.moveToNext()) { val url = cursor.getString(1) if (url != null && !url.startsWith(Feed.PREFIX_LOCAL_FOLDER)) { @@ -113,8 +130,6 @@ object DBReader { * @param items The FeedItems whose Feed-objects should be loaded. */ private fun loadFeedDataOfFeedItemList(items: List) { - val feeds = getFeedList() - val feedIndex: MutableMap = ArrayMap(feeds.size) for (feed in feeds) { feedIndex[feed.id] = feed @@ -150,7 +165,7 @@ object DBReader { Log.d(TAG, "getFeedItemList() called with: feed = [$feed]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getItemsOfFeedCursor(feed!!, filter).use { cursor -> val items = extractItemlistFromCursor(adapter, cursor).toMutableList() @@ -170,7 +185,7 @@ object DBReader { fun extractItemlistFromCursor(itemlistCursor: Cursor): List { Log.d(TAG, "extractItemlistFromCursor() called with: itemlistCursor = [$itemlistCursor]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { return extractItemlistFromCursor(adapter, itemlistCursor) } finally { @@ -202,7 +217,7 @@ object DBReader { @JvmStatic fun getQueue(adapter: PodDBAdapter?): List { - Log.d(TAG, "getQueue()") +// Log.d(TAG, "getQueue()") adapter!!.queueCursor.use { cursor -> val items = extractItemlistFromCursor(adapter, cursor) loadAdditionalFeedItemListData(items) @@ -213,8 +228,13 @@ object DBReader { @JvmStatic fun getQueueIDList(): LongList { Log.d(TAG, "getQueueIDList() called") +// val stackTraceElements = Thread.currentThread().stackTrace +// stackTraceElements.forEach { element -> +// println(element) +// } + val adapter = getInstance() - adapter!!.open() + adapter.open() try { return getQueueIDList(adapter) } finally { @@ -237,7 +257,7 @@ object DBReader { Log.d(TAG, "getQueue() called") val adapter = getInstance() - adapter!!.open() + adapter.open() try { return getQueue(adapter) } finally { @@ -249,7 +269,7 @@ object DBReader { Log.d(TAG, "getFavoriteIDList() called") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getFavoritesIdsCursor(0, Int.MAX_VALUE).use { cursor -> val favoriteIDs = LongList(cursor.count) @@ -273,7 +293,7 @@ object DBReader { fun getEpisodes(offset: Int, limit: Int, filter: FeedItemFilter?, sortOrder: SortOrder?): List { Log.d(TAG, "getRecentlyPublishedEpisodes() called with: offset=$offset, limit=$limit") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getEpisodesCursor(offset, limit, filter, sortOrder).use { cursor -> val items = extractItemlistFromCursor(adapter, cursor) @@ -288,7 +308,7 @@ object DBReader { @JvmStatic fun getTotalEpisodeCount(filter: FeedItemFilter?): Int { val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getEpisodeCountCursor(filter).use { cursor -> if (cursor.moveToFirst()) { @@ -303,7 +323,7 @@ object DBReader { fun getRandomEpisodes(limit: Int, seed: Int): List { val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getRandomEpisodesCursor(limit, seed).use { cursor -> val items = extractItemlistFromCursor(adapter, cursor) @@ -328,7 +348,7 @@ object DBReader { Log.d(TAG, "getPlaybackHistory() called") val adapter = getInstance() - adapter!!.open() + adapter.open() var mediaCursor: Cursor? = null var itemCursor: Cursor? = null @@ -356,7 +376,7 @@ object DBReader { @JvmStatic fun getPlaybackHistoryLength(): Long { val adapter = getInstance() - adapter!!.open() + adapter.open() try { return adapter.completedMediaLength @@ -370,7 +390,7 @@ object DBReader { Log.d(TAG, "getDownloadLog() called") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE).use { cursor -> val downloadLog: MutableList = @@ -397,7 +417,7 @@ object DBReader { Log.d(TAG, "getFeedDownloadLog() called with: feed = [$feedId]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feedId).use { cursor -> val downloadLog: MutableList = ArrayList(cursor.count) @@ -434,7 +454,7 @@ object DBReader { */ fun getFeed(feedId: Long, filtered: Boolean): Feed? { Log.d(TAG, "getFeed() called with: feedId = [$feedId]") - val adapter = getInstance() ?: return null + val adapter = getInstance() adapter.open() try { adapter.getFeedCursor(feedId).use { cursor -> @@ -484,7 +504,7 @@ object DBReader { Log.d(TAG, "getFeedItem() called with: itemId = [$itemId]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { return getFeedItem(itemId, adapter) } finally { @@ -501,7 +521,7 @@ object DBReader { fun getNextInQueue(item: FeedItem): FeedItem? { Log.d(TAG, "getNextInQueue() called with: " + "itemId = [" + item.id + "]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { var nextItem: FeedItem? = null try { @@ -524,7 +544,7 @@ object DBReader { fun getPausedQueue(limit: Int): List { Log.d(TAG, "getPausedQueue() called ") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getPausedQueueCursor(limit).use { cursor -> val items = extractItemlistFromCursor(adapter, cursor) @@ -569,7 +589,7 @@ object DBReader { Log.d(TAG, "getImageAuthentication() called with: imageUrl = [$imageUrl]") val adapter = getInstance() - adapter!!.open() + adapter.open() try { return getImageAuthentication(imageUrl, adapter) } finally { @@ -606,7 +626,7 @@ object DBReader { @JvmStatic fun getFeedItemByGuidOrEpisodeUrl(guid: String?, episodeUrl: String): FeedItem? { val adapter = getInstance() - adapter!!.open() + adapter.open() try { return getFeedItemByGuidOrEpisodeUrl(guid, episodeUrl, adapter) } finally { @@ -627,7 +647,7 @@ object DBReader { // println(element) // } val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getDescriptionOfItem(item).use { cursor -> if (cursor.moveToFirst()) { @@ -650,14 +670,14 @@ object DBReader { */ @JvmStatic fun loadChaptersOfFeedItem(item: FeedItem): List? { - Log.d(TAG, "loadChaptersOfFeedItem() called with: item = [$item]") + Log.d(TAG, "loadChaptersOfFeedItem() called with: item = [${item.title}]") // TODO: need to find out who are often calling this // val stackTraceElements = Thread.currentThread().stackTrace // stackTraceElements.forEach { element -> // println(element) // } val adapter = getInstance() - adapter!!.open() + adapter.open() try { return loadChaptersOfFeedItem(adapter, item) } finally { @@ -689,7 +709,7 @@ object DBReader { @JvmStatic fun getFeedMedia(mediaId: Long): FeedMedia? { val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getSingleFeedMediaCursor(mediaId).use { mediaCursor -> @@ -714,7 +734,7 @@ object DBReader { fun getFeedItemsWithUrl(urls: List?): List { Log.d(TAG, "getFeedItemsWithUrl() called ") val adapter = getInstance() - adapter!!.open() + adapter.open() try { adapter.getFeedItemCursorByUrl(urls!!).use { itemCursor -> val items = extractItemlistFromCursor(adapter, itemCursor).toMutableList() @@ -730,7 +750,7 @@ object DBReader { fun getMonthlyTimeStatistics(): List { val months: MutableList = ArrayList() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.monthlyStatisticsCursor.use { cursor -> val indexMonth = cursor.getColumnIndexOrThrow("month") val indexYear = cursor.getColumnIndexOrThrow("year") @@ -756,7 +776,7 @@ object DBReader { timeFilterFrom: Long, timeFilterTo: Long ): StatisticsResult { val adapter = getInstance() - adapter!!.open() + adapter.open() val result = StatisticsResult() adapter.getFeedStatisticsCursor(includeMarkedAsPlayed, timeFilterFrom, timeFilterTo).use { cursor -> @@ -792,7 +812,7 @@ object DBReader { fun getTimeBetweenReleaseAndPlayback(timeFilterFrom: Long, timeFilterTo: Long): Long { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.getTimeBetweenReleaseAndPlayback(timeFilterFrom, timeFilterTo).use { cursor -> cursor.moveToFirst() val result = cursor.getString(0).toLong() @@ -810,13 +830,13 @@ object DBReader { fun getNavDrawerData(subscriptionsFilter: SubscriptionsFilter?): NavDrawerData { Log.d(TAG, "getNavDrawerData() called with: " + "") val adapter = getInstance() - adapter!!.open() + adapter.open() val feedCounters: Map = adapter.getFeedCounters(feedCounterSetting) - var feeds = getFeedList(adapter) +// getFeedList(adapter) if (subscriptionsFilter != null) { - feeds = subscriptionsFilter.filter(feeds, feedCounters as Map) + feeds = subscriptionsFilter.filter(feeds, feedCounters as Map).toMutableList() } val comparator: Comparator @@ -875,7 +895,7 @@ object DBReader { } } - feeds = feeds.sortedWith(comparator) + feeds.sortWith(comparator) val queueSize = adapter.queueSize val numNewItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.NEW)) val numDownloadedItems = getTotalEpisodeCount(FeedItemFilter(FeedItemFilter.DOWNLOADED)) diff --git a/core/src/main/java/ac/mdiq/podcini/core/storage/DBTasks.kt b/core/src/main/java/ac/mdiq/podcini/core/storage/DBTasks.kt index 588c68fd..8be30605 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/storage/DBTasks.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/storage/DBTasks.kt @@ -58,7 +58,7 @@ import java.util.concurrent.* @UnstableApi @JvmStatic fun removeFeedWithDownloadUrl(context: Context?, downloadUrl: String) { val adapter = getInstance() - adapter!!.open() + adapter.open() val cursor = adapter.feedCursorDownloadUrls var feedID: Long = 0 if (cursor.moveToFirst()) { @@ -200,7 +200,7 @@ import java.util.concurrent.* val unlistedItems: MutableList = ArrayList() val adapter = getInstance() - adapter!!.open() + adapter.open() // Look up feed in the feedslist val savedFeed = searchFeedByIdentifyingValueOrID(newFeed) @@ -339,6 +339,7 @@ import java.util.concurrent.* } else { DBWriter.setCompleteFeed(savedFeed).get() } + DBReader.updateFeedList(adapter) if (removeUnlistedItems) { DBWriter.deleteFeedItems(context, unlistedItems).get() } @@ -420,7 +421,7 @@ import java.util.concurrent.* @Throws(Exception::class) override fun call(): T? { val adapter = getInstance() - adapter!!.open() + adapter.open() execute(adapter) adapter.close() return result diff --git a/core/src/main/java/ac/mdiq/podcini/core/storage/DBWriter.kt b/core/src/main/java/ac/mdiq/podcini/core/storage/DBWriter.kt index 646d66d9..1489cbb2 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/storage/DBWriter.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/storage/DBWriter.kt @@ -126,9 +126,9 @@ import java.util.concurrent.TimeUnit media.setFile_url(null) media.setHasEmbeddedPicture(false) val adapter = getInstance() - adapter?.open() - adapter?.setMedia(media) - adapter?.close() + adapter.open() + adapter.setMedia(media) + adapter.close() } if (media.id == currentlyPlayingFeedMediaId) { @@ -174,9 +174,9 @@ import java.util.concurrent.TimeUnit // delete feed val adapter = getInstance() - adapter?.open() - adapter?.removeFeed(feed) - adapter?.close() + adapter.open() + adapter.removeFeed(feed) + adapter.close() if (!feed.isLocalFeed && feed.download_url != null) { SynchronizationQueueSink.enqueueFeedRemovedIfSynchronizationIsActive(context, feed.download_url!!) @@ -220,12 +220,12 @@ import java.util.concurrent.TimeUnit } val adapter = getInstance() - adapter?.open() + adapter.open() if (removedFromQueue.isNotEmpty()) { - adapter?.setQueue(queue) + adapter.setQueue(queue) } - adapter?.removeFeedItems(items) - adapter?.close() + adapter.removeFeedItems(items) + adapter.close() for (item in removedFromQueue) { EventBus.getDefault().post(irreversibleRemoved(item)) @@ -246,9 +246,9 @@ import java.util.concurrent.TimeUnit fun clearPlaybackHistory(): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.clearPlaybackHistory() - adapter?.close() + adapter.open() + adapter.clearPlaybackHistory() + adapter.close() EventBus.getDefault().post(PlaybackHistoryEvent.listUpdated()) } } @@ -259,9 +259,9 @@ import java.util.concurrent.TimeUnit fun clearDownloadLog(): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.clearDownloadLog() - adapter?.close() + adapter.open() + adapter.clearDownloadLog() + adapter.close() EventBus.getDefault().post(DownloadLogEvent.listUpdated()) } } @@ -292,9 +292,9 @@ import java.util.concurrent.TimeUnit media!!.setPlaybackCompletionDate(date) val adapter = getInstance() - adapter?.open() - adapter?.setFeedMediaPlaybackCompletionDate(media) - adapter?.close() + adapter.open() + adapter.setFeedMediaPlaybackCompletionDate(media) + adapter.close() EventBus.getDefault().post(PlaybackHistoryEvent.listUpdated()) } } @@ -307,9 +307,9 @@ import java.util.concurrent.TimeUnit fun addDownloadStatus(status: DownloadResult?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setDownloadStatus(status!!) - adapter?.close() + adapter.open() + adapter.setDownloadStatus(status!!) + adapter.close() EventBus.getDefault().post(DownloadLogEvent.listUpdated()) } } @@ -329,7 +329,7 @@ import java.util.concurrent.TimeUnit ): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() + adapter.open() val queue = getQueue(adapter).toMutableList() val item: FeedItem? @@ -337,7 +337,7 @@ import java.util.concurrent.TimeUnit item = getFeedItem(itemId) if (item != null) { queue.add(index, item) - adapter?.setQueue(queue) + adapter.setQueue(queue) item.addTag(FeedItem.TAG_QUEUE) EventBus.getDefault().post(added(item, index)) EventBus.getDefault().post(updated(item)) @@ -347,7 +347,7 @@ import java.util.concurrent.TimeUnit } } - adapter?.close() + adapter.close() if (performAutoDownload) { autodownloadUndownloadedItems(context) } @@ -402,7 +402,7 @@ import java.util.concurrent.TimeUnit return@runOnDbThread } val adapter = getInstance() - adapter?.open() + adapter.open() val queue = getQueue(adapter).toMutableList() var queueModified = false @@ -432,7 +432,7 @@ import java.util.concurrent.TimeUnit } if (queueModified) { applySortOrder(queue, events) - adapter?.setQueue(queue) + adapter.setQueue(queue) for (event in events) { EventBus.getDefault().post(event) } @@ -441,7 +441,7 @@ import java.util.concurrent.TimeUnit markItemPlayed(FeedItem.UNPLAYED, *markAsUnplayedIds.toArray()) } } - adapter?.close() + adapter.close() if (performAutoDownload) { autodownloadUndownloadedItems(context) } @@ -482,9 +482,9 @@ import java.util.concurrent.TimeUnit fun clearQueue(): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.clearQueue() - adapter?.close() + adapter.open() + adapter.clearQueue() + adapter.close() EventBus.getDefault().post(cleared()) } } @@ -518,7 +518,7 @@ import java.util.concurrent.TimeUnit return } val adapter = getInstance() - adapter?.open() + adapter.open() val queue = getQueue(adapter).toMutableList() var queueModified = false @@ -543,7 +543,7 @@ import java.util.concurrent.TimeUnit } } if (queueModified) { - adapter?.setQueue(queue) + adapter.setQueue(queue) for (event in events) { EventBus.getDefault().post(event) } @@ -551,7 +551,7 @@ import java.util.concurrent.TimeUnit } else { Log.w(TAG, "Queue was not modified by call to removeQueueItem") } - adapter?.close() + adapter.close() if (performAutoDownload) { autodownloadUndownloadedItems(context) } @@ -567,9 +567,9 @@ import java.util.concurrent.TimeUnit fun addFavoriteItem(item: FeedItem): Future<*> { return runOnDbThread { - val adapter = getInstance()?.open() - adapter?.addFavoriteItem(item) - adapter?.close() + val adapter = getInstance().open() + adapter.addFavoriteItem(item) + adapter.close() item.addTag(FeedItem.TAG_FAVORITE) EventBus.getDefault().post(FavoritesEvent()) EventBus.getDefault().post(updated(item)) @@ -578,9 +578,9 @@ import java.util.concurrent.TimeUnit fun removeFavoriteItem(item: FeedItem): Future<*> { return runOnDbThread { - val adapter = getInstance()?.open() - adapter?.removeFavoriteItem(item) - adapter?.close() + val adapter = getInstance().open() + adapter.removeFavoriteItem(item) + adapter.close() item.removeTag(FeedItem.TAG_FAVORITE) EventBus.getDefault().post(FavoritesEvent()) EventBus.getDefault().post(updated(item)) @@ -658,7 +658,7 @@ import java.util.concurrent.TimeUnit to: Int, broadcastUpdate: Boolean ) { val adapter = getInstance() - adapter?.open() + adapter.open() val queue = getQueue(adapter).toMutableList() if (queue.isNotEmpty()) { @@ -666,7 +666,7 @@ import java.util.concurrent.TimeUnit val item: FeedItem = queue.removeAt(from) queue.add(to, item) - adapter?.setQueue(queue) + adapter.setQueue(queue) if (broadcastUpdate) { EventBus.getDefault().post(moved(item, to)) } @@ -674,15 +674,15 @@ import java.util.concurrent.TimeUnit } else { Log.e(TAG, "moveQueueItemHelper: Could not load queue") } - adapter?.close() + adapter.close() } fun resetPagedFeedPage(feed: Feed?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.resetPagedFeedPage(feed!!) - adapter?.close() + adapter.open() + adapter.resetPagedFeedPage(feed!!) + adapter.close() } } @@ -711,9 +711,9 @@ import java.util.concurrent.TimeUnit ): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setFeedItemRead(played, *itemIds) - adapter?.close() + adapter.open() + adapter.setFeedItemRead(played, *itemIds) + adapter.close() if (broadcastUpdate) { EventBus.getDefault().post(UnreadItemsUpdateEvent()) } @@ -740,10 +740,10 @@ import java.util.concurrent.TimeUnit ): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setFeedItemRead(played, itemId, mediaId, + adapter.open() + adapter.setFeedItemRead(played, itemId, mediaId, resetMediaPosition) - adapter?.close() + adapter.close() EventBus.getDefault().post(UnreadItemsUpdateEvent()) } } @@ -756,9 +756,9 @@ import java.util.concurrent.TimeUnit fun removeFeedNewFlag(feedId: Long): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED, feedId) - adapter?.close() + adapter.open() + adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED, feedId) + adapter.close() EventBus.getDefault().post(UnreadItemsUpdateEvent()) } } @@ -770,9 +770,9 @@ import java.util.concurrent.TimeUnit fun removeAllNewFlags(): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED) - adapter?.close() + adapter.open() + adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED) + adapter.close() EventBus.getDefault().post(UnreadItemsUpdateEvent()) } } @@ -780,9 +780,9 @@ import java.util.concurrent.TimeUnit fun addNewFeed(context: Context, vararg feeds: Feed): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setCompleteFeed(*feeds) - adapter?.close() + adapter.open() + adapter.setCompleteFeed(*feeds) + adapter.close() for (feed in feeds) { if (!feed.isLocalFeed && feed.download_url != null) { @@ -798,18 +798,18 @@ import java.util.concurrent.TimeUnit fun setCompleteFeed(vararg feeds: Feed): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.setCompleteFeed(*feeds) - adapter?.close() + adapter.open() + adapter.setCompleteFeed(*feeds) + adapter.close() } } fun setItemList(items: List): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter?.open() - adapter?.storeFeedItemlist(items) - adapter?.close() + adapter.open() + adapter.storeFeedItemlist(items) + adapter.close() EventBus.getDefault().post(updated(items)) } } @@ -823,7 +823,7 @@ import java.util.concurrent.TimeUnit fun setFeedMedia(media: FeedMedia?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setMedia(media) adapter.close() } @@ -838,7 +838,7 @@ import java.util.concurrent.TimeUnit fun setFeedMediaPlaybackInformation(media: FeedMedia?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedMediaPlaybackInformation(media!!) adapter.close() } @@ -854,7 +854,7 @@ import java.util.concurrent.TimeUnit fun setFeedItem(item: FeedItem?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setSingleFeedItem(item!!) adapter.close() EventBus.getDefault().post(updated(item)) @@ -868,7 +868,7 @@ import java.util.concurrent.TimeUnit Log.d(TAG, "updateFeedDownloadURL(original: $original, updated: $updated)") return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedDownloadUrl(original, updated) adapter.close() } @@ -882,7 +882,7 @@ import java.util.concurrent.TimeUnit fun setFeedPreferences(preferences: FeedPreferences): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedPreferences(preferences) adapter.close() EventBus.getDefault().post(FeedListUpdateEvent(preferences.feedID)) @@ -913,7 +913,7 @@ import java.util.concurrent.TimeUnit ): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedLastUpdateFailed(feedId, lastUpdateFailed) adapter.close() EventBus.getDefault().post(FeedListUpdateEvent(feedId)) @@ -923,7 +923,7 @@ import java.util.concurrent.TimeUnit fun setFeedCustomTitle(feed: Feed): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedCustomTitle(feed.id, feed.getCustomTitle()) adapter.close() EventBus.getDefault().post(FeedListUpdateEvent(feed)) @@ -945,7 +945,7 @@ import java.util.concurrent.TimeUnit val permutor = getPermutor(sortOrder) return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() val queue = getQueue(adapter).toMutableList() permutor.reorder(queue) @@ -969,7 +969,7 @@ import java.util.concurrent.TimeUnit Log.d(TAG, "setFeedItemsFilter() called with: feedId = [$feedId], filterValues = [$filterValues]") return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedItemFilter(feedId, filterValues) adapter.close() EventBus.getDefault().post(FeedEvent(FeedEvent.Action.FILTER_CHANGED, feedId)) @@ -983,7 +983,7 @@ import java.util.concurrent.TimeUnit fun setFeedItemSortOrder(feedId: Long, sortOrder: SortOrder?): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setFeedItemSortOrder(feedId, sortOrder) adapter.close() EventBus.getDefault().post(FeedEvent(FeedEvent.Action.SORT_ORDER_CHANGED, feedId)) @@ -996,7 +996,7 @@ import java.util.concurrent.TimeUnit fun resetStatistics(): Future<*> { return runOnDbThread { val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.resetAllMediaPlayedDuration() adapter.close() } diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/ChapterUtils.kt b/core/src/main/java/ac/mdiq/podcini/core/util/ChapterUtils.kt index 785af6f2..aeaf4263 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/ChapterUtils.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/ChapterUtils.kt @@ -46,7 +46,7 @@ object ChapterUtils { @JvmStatic fun loadChapters(playable: Playable, context: Context, forceRefresh: Boolean) { - if (playable.getChapters().isNotEmpty() && !forceRefresh) { + if (playable.chaptersLoaded() && !forceRefresh) { // Already loaded return } @@ -72,6 +72,7 @@ object ChapterUtils { val chaptersFromMediaFile = loadChaptersFromMediaFile(playable, context) val chaptersMergePhase1 = merge(chaptersFromDatabase, chaptersFromMediaFile) val chapters = merge(chaptersMergePhase1, chaptersFromPodcastIndex) + Log.d(TAG, "loadChapters chapters size: ${chapters?.size?:0} ${playable.getEpisodeTitle()}") if (chapters == null) { // Do not try loading again. There are no chapters. playable.setChapters(listOf()) @@ -135,19 +136,19 @@ object ChapterUtils { } } - fun loadChaptersFromUrl(url: String, forceRefresh: Boolean): List? { + fun loadChaptersFromUrl(url: String, forceRefresh: Boolean): List { if (forceRefresh) { return loadChaptersFromUrl(url, CacheControl.FORCE_NETWORK) } val cachedChapters = loadChaptersFromUrl(url, CacheControl.FORCE_CACHE) - if (cachedChapters == null || cachedChapters.size <= 1) { + if (cachedChapters.size <= 1) { // Some publishers use one dummy chapter before actual chapters are available return loadChaptersFromUrl(url, CacheControl.FORCE_NETWORK) } return cachedChapters } - private fun loadChaptersFromUrl(url: String, cacheControl: CacheControl): List? { + private fun loadChaptersFromUrl(url: String, cacheControl: CacheControl): List { var response: Response? = null try { val request: Request = Builder().url(url).cacheControl(cacheControl).build() @@ -160,7 +161,7 @@ object ChapterUtils { } finally { response?.close() } - return null + return listOf() } @Throws(IOException::class, ID3ReaderException::class) diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/LongList.kt b/core/src/main/java/ac/mdiq/podcini/core/util/LongList.kt index 914d7e1b..d09ddc23 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/LongList.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/LongList.kt @@ -249,7 +249,7 @@ class LongList @JvmOverloads constructor(initialCapacity: Int = 4) { companion object { fun of(vararg values: Long): LongList { - if (values == null || values.size == 0) { + if (values == null || values.isEmpty()) { return LongList(0) } val result = LongList(values.size) diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/NetworkUtils.kt b/core/src/main/java/ac/mdiq/podcini/core/util/NetworkUtils.kt index 37288dd8..c68b4bad 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/NetworkUtils.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/NetworkUtils.kt @@ -111,7 +111,7 @@ object NetworkUtils { private val isInAllowedWifiNetwork: Boolean get() { val wm = context!!.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager - val selectedNetworks = Arrays.asList(*UserPreferences.autodownloadSelectedNetworks) + val selectedNetworks = listOf(*UserPreferences.autodownloadSelectedNetworks) return selectedNetworks.contains(wm.connectionInfo.networkId.toString()) } diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/ShareUtils.kt b/core/src/main/java/ac/mdiq/podcini/core/util/ShareUtils.kt index 387017db..f610a2e5 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/ShareUtils.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/ShareUtils.kt @@ -87,8 +87,11 @@ object ShareUtils { @JvmStatic fun shareFeedItemFile(context: Context, media: FeedMedia) { + val lurl = media.getLocalMediaUrl() + if (lurl.isNullOrEmpty()) return + val fileUri = FileProvider.getUriForFile(context, context.getString(R.string.provider_authority), - File(media.getLocalMediaUrl())) + File(lurl)) IntentBuilder(context) .setType(media.mime_type) diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/comparator/ChapterStartTimeComparator.kt b/core/src/main/java/ac/mdiq/podcini/core/util/comparator/ChapterStartTimeComparator.kt index d80ed968..4ce95c34 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/comparator/ChapterStartTimeComparator.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/comparator/ChapterStartTimeComparator.kt @@ -4,6 +4,6 @@ import ac.mdiq.podcini.model.feed.Chapter class ChapterStartTimeComparator : Comparator { override fun compare(lhs: Chapter, rhs: Chapter): Int { - return java.lang.Long.compare(lhs.start, rhs.start) + return lhs.start.compareTo(rhs.start) } } diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/gui/ShownotesCleaner.kt b/core/src/main/java/ac/mdiq/podcini/core/util/gui/ShownotesCleaner.kt index 1bc2f82d..5497c675 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/gui/ShownotesCleaner.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/gui/ShownotesCleaner.kt @@ -175,11 +175,11 @@ class ShownotesCleaner(context: Context, private val rawShownotes: String, priva @JvmStatic fun getTimecodeLinkTime(link: String?): Int { if (isTimecodeLink(link)) { - val m = TIMECODE_LINK_REGEX.matcher(link) + val m = TIMECODE_LINK_REGEX.matcher(link!!) try { if (m.find()) { - return m.group(1).toInt() + return m.group(1)?.toInt()?:0 } } catch (e: NumberFormatException) { e.printStackTrace() diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/playback/MediaPlayerError.kt b/core/src/main/java/ac/mdiq/podcini/core/util/playback/MediaPlayerError.kt deleted file mode 100644 index b0808c6e..00000000 --- a/core/src/main/java/ac/mdiq/podcini/core/util/playback/MediaPlayerError.kt +++ /dev/null @@ -1,24 +0,0 @@ -package ac.mdiq.podcini.core.util.playback - -import android.content.Context -import android.media.MediaPlayer -import androidx.media3.common.util.UnstableApi -import androidx.media3.exoplayer.ExoPlaybackException -import ac.mdiq.podcini.core.R -import ac.mdiq.podcini.core.service.playback.ExoPlayerWrapper - -/** Utility class for MediaPlayer errors. */ -@UnstableApi -object MediaPlayerError { - /** Get a human-readable string for a specific error code. */ - fun getErrorString(context: Context, code: Int): String { - val resId = when (code) { - MediaPlayer.MEDIA_ERROR_SERVER_DIED -> R.string.playback_error_server_died - MediaPlayer.MEDIA_ERROR_UNSUPPORTED, ExoPlayerWrapper.ERROR_CODE_OFFSET + ExoPlaybackException.TYPE_RENDERER -> R.string.playback_error_unsupported - MediaPlayer.MEDIA_ERROR_TIMED_OUT -> R.string.playback_error_timeout - ExoPlayerWrapper.ERROR_CODE_OFFSET + ExoPlaybackException.TYPE_SOURCE -> R.string.playback_error_source - else -> R.string.playback_error_unknown - } - return context.getString(resId) + " (" + code + ")" - } -} diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackController.kt b/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackController.kt index 4ec895bb..d499653a 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackController.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackController.kt @@ -30,9 +30,9 @@ import org.greenrobot.eventbus.ThreadMode * control playback instead of communicating with the PlaybackService directly. */ @UnstableApi -abstract class PlaybackController(private val activity: FragmentActivity?) { +abstract class PlaybackController(private val activity: FragmentActivity) { private var playbackService: PlaybackService? = null - private var media: Playable? = null + var status: PlayerStatus = PlayerStatus.STOPPED private set @@ -73,16 +73,16 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { initialized = true if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - activity?.registerReceiver(statusUpdate, IntentFilter( + activity.registerReceiver(statusUpdate, IntentFilter( PlaybackService.ACTION_PLAYER_STATUS_CHANGED), Context.RECEIVER_NOT_EXPORTED) - activity?.registerReceiver(notificationReceiver, IntentFilter( + activity.registerReceiver(notificationReceiver, IntentFilter( PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION), Context.RECEIVER_NOT_EXPORTED) } else { - activity?.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED)) - activity?.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION)) + activity.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED)) + activity.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION)) } -// activity?.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED)) -// activity?.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION)) +// activity.registerReceiver(statusUpdate, IntentFilter(PlaybackService.ACTION_PLAYER_STATUS_CHANGED)) +// activity.registerReceiver(notificationReceiver, IntentFilter(PlaybackServiceInterface.ACTION_PLAYER_NOTIFICATION)) if (!released) { bindToService() @@ -100,13 +100,13 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { Log.d(TAG, "Releasing PlaybackController") try { - activity?.unregisterReceiver(statusUpdate) + activity.unregisterReceiver(statusUpdate) } catch (e: IllegalArgumentException) { // ignore } try { - activity?.unregisterReceiver(notificationReceiver) + activity.unregisterReceiver(notificationReceiver) } catch (e: IllegalArgumentException) { // ignore } @@ -122,7 +122,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { private fun unbind() { try { - activity?.unbindService(mConnection) + activity.unbindService(mConnection) } catch (e: IllegalArgumentException) { // ignore } @@ -144,7 +144,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { private fun bindToService() { Log.d(TAG, "Trying to connect to service") check(PlaybackService.isRunning) { "Trying to bind but service is not running" } - val bound = activity?.bindService(Intent(activity, PlaybackService::class.java), mConnection, 0) + val bound = activity.bindService(Intent(activity, PlaybackService::class.java), mConnection, 0) Log.d(TAG, "Result for service binding: $bound") } @@ -171,7 +171,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { private val statusUpdate: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - Log.d(TAG, "Received statusUpdate Intent.") +// Log.d(TAG, "Received statusUpdate Intent.") if (playbackService != null) { val info = playbackService!!.pSMPInfo status = info.playerStatus @@ -218,7 +218,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { * should be used to update the GUI or start/cancel background threads. */ private fun handleStatus() { - Log.d(TAG, "status: $status") + Log.d(TAG, "handleStatus() called status: $status") checkMediaInfoLoaded() when (status) { PlayerStatus.PLAYING -> updatePlayButtonShowsPlay(false) @@ -267,7 +267,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { fun playPause() { if (media == null) return if (playbackService == null) { - if (activity != null) PlaybackServiceStarter(activity, media!!).start() + PlaybackServiceStarter(activity, media!!).start() Log.w(TAG, "Play/Pause button was pressed, but playbackservice was null!") return } @@ -280,7 +280,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { playbackService!!.prepare() } else -> { - if (activity != null) PlaybackServiceStarter(activity, media!!) + PlaybackServiceStarter(activity, media!!) .callEvenIfRunning(true) .start() Log.w(TAG, "Play/Pause button was pressed and PlaybackService state was unknown") @@ -289,46 +289,28 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { } val position: Int - get() = if (playbackService != null) { - playbackService!!.currentPosition - } else if (getMedia() != null) { - getMedia()!!.getPosition() - } else { - Playable.INVALID_TIME - } + get() = playbackService?.currentPosition ?: getMedia()?.getPosition()?:Playable.INVALID_TIME val duration: Int - get() = if (playbackService != null) { - playbackService!!.duration - } else if (getMedia() != null) { - getMedia()!!.getDuration() - } else { - Playable.INVALID_TIME - } + get() = playbackService?.duration ?: getMedia()?.getDuration()?:Playable.INVALID_TIME fun getMedia(): Playable? { - if (media == null && activity != null) { - media = PlaybackPreferences.createInstanceFromPreferences(activity) - } + if (media == null && playbackService != null) media = playbackService!!.pSMPInfo.playable + if (media == null) media = PlaybackPreferences.createInstanceFromPreferences(activity) + return media } fun sleepTimerActive(): Boolean { - return playbackService != null && playbackService!!.sleepTimerActive() + return playbackService?.sleepTimerActive() ?: false } fun disableSleepTimer() { - if (playbackService != null) { - playbackService!!.disableSleepTimer() - } + playbackService?.disableSleepTimer() } val sleepTimerTimeLeft: Long - get() = if (playbackService != null) { - playbackService!!.sleepTimerTimeLeft - } else { - Playable.INVALID_TIME.toLong() - } + get() = playbackService?.sleepTimerTimeLeft ?: Playable.INVALID_TIME.toLong() fun extendSleepTimer(extendTime: Long) { val timeLeft = sleepTimerTimeLeft @@ -338,26 +320,24 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { } fun setSleepTimer(time: Long) { - if (playbackService != null) { - playbackService!!.setSleepTimer(time) - } + playbackService?.setSleepTimer(time) } fun seekTo(time: Int) { if (playbackService != null) { playbackService!!.seekTo(time) - } else if (getMedia() is FeedMedia) { - val media = getMedia() as FeedMedia? - media!!.setPosition(time) - DBWriter.setFeedItem(media.getItem()) - EventBus.getDefault().post(PlaybackPositionEvent(time, getMedia()!!.getDuration())) + } else { + val media = getMedia() + if (media is FeedMedia) { + media.setPosition(time) + DBWriter.setFeedItem(media.getItem()) + EventBus.getDefault().post(PlaybackPositionEvent(time, media.getDuration())) + } } } fun setVideoSurface(holder: SurfaceHolder?) { - if (playbackService != null) { - playbackService!!.setVideoSurface(holder) - } + playbackService?.setVideoSurface(holder) } fun setPlaybackSpeed(speed: Float) { @@ -369,21 +349,15 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { } fun setSkipSilence(skipSilence: Boolean) { - if (playbackService != null) { - playbackService!!.skipSilence(skipSilence) - } + playbackService?.skipSilence(skipSilence) } val currentPlaybackSpeedMultiplier: Float - get() = if (playbackService != null) { - playbackService!!.currentPlaybackSpeed - } else { - getCurrentPlaybackSpeed(getMedia()) - } + get() = playbackService?.currentPlaybackSpeed ?: getCurrentPlaybackSpeed(getMedia()) val audioTracks: List get() { - if (playbackService == null || playbackService!!.audioTracks.isNullOrEmpty()) { + if (playbackService == null || playbackService!!.audioTracks.isEmpty()) { return emptyList() } return playbackService!!.audioTracks.filterNotNull().map { it } @@ -391,16 +365,11 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { val selectedAudioTrack: Int get() { - if (playbackService == null) { - return -1 - } - return playbackService!!.selectedAudioTrack + return playbackService?.selectedAudioTrack?: -1 } fun setAudioTrack(track: Int) { - if (playbackService != null) { - playbackService!!.setAudioTrack(track) - } + playbackService?.setAudioTrack(track) } val isPlayingVideoLocally: Boolean @@ -409,20 +378,14 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { } else if (playbackService != null) { PlaybackService.currentMediaType == MediaType.VIDEO } else { - getMedia() != null && getMedia()!!.getMediaType() == MediaType.VIDEO + getMedia()?.getMediaType() == MediaType.VIDEO } val videoSize: Pair? - get() = if (playbackService != null) { - playbackService!!.videoSize - } else { - null - } + get() = playbackService?.videoSize fun notifyVideoSurfaceAbandoned() { - if (playbackService != null) { - playbackService!!.notifyVideoSurfaceAbandoned() - } + playbackService?.notifyVideoSurfaceAbandoned() } val isStreaming: Boolean @@ -430,5 +393,7 @@ abstract class PlaybackController(private val activity: FragmentActivity?) { companion object { private const val TAG = "PlaybackController" + + private var media: Playable? = null } } diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackServiceStarter.kt b/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackServiceStarter.kt index dd453771..c0fa0a8c 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackServiceStarter.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/playback/PlaybackServiceStarter.kt @@ -11,6 +11,7 @@ import ac.mdiq.podcini.model.playback.Playable @UnstableApi class PlaybackServiceStarter(private val context: Context, private val media: Playable) { + private var shouldStreamThisTime = false private var callEvenIfRunning = false diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/syndication/FeedDiscoverer.kt b/core/src/main/java/ac/mdiq/podcini/core/util/syndication/FeedDiscoverer.kt index 0e146a46..d0d4a0f4 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/syndication/FeedDiscoverer.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/syndication/FeedDiscoverer.kt @@ -62,7 +62,7 @@ class FeedDiscoverer { val uri = Uri.parse(strUrl) if (uri.isRelative) { val res = Uri.parse(baseUrl).buildUpon().path(strUrl).build() - return if ((res != null)) res.toString() else null + return res?.toString() } else { return strUrl } diff --git a/core/src/main/java/ac/mdiq/podcini/core/util/syndication/HtmlToPlainText.kt b/core/src/main/java/ac/mdiq/podcini/core/util/syndication/HtmlToPlainText.kt index fd65de44..a82715de 100644 --- a/core/src/main/java/ac/mdiq/podcini/core/util/syndication/HtmlToPlainText.kt +++ b/core/src/main/java/ac/mdiq/podcini/core/util/syndication/HtmlToPlainText.kt @@ -1,6 +1,5 @@ package ac.mdiq.podcini.core.util.syndication -import android.text.TextUtils import org.apache.commons.lang3.StringUtils import org.jsoup.Jsoup import org.jsoup.internal.StringUtil @@ -37,7 +36,7 @@ class HtmlToPlainText { * @param element the root element to format * @return formatted text */ - fun getPlainText(element: Element?): String { + fun getPlainText(element: Element): String { val formatter = FormattingVisitor() // walk the DOM, and call .head() and .tail() for each node NodeTraversor.traverse(formatter, element) @@ -52,14 +51,19 @@ class HtmlToPlainText { // hit when the node is first seen override fun head(node: Node, depth: Int) { val name = node.nodeName() - if (node is TextNode) { - append(node.text()) // TextNodes carry all user-readable text in the DOM. - } else if (name == "li") { - append("\n * ") - } else if (name == "dt") { - append(" ") - } else if (StringUtil.`in`(name, "p", "h1", "h2", "h3", "h4", "h5", "tr")) { - append("\n") + when { + node is TextNode -> { + append(node.text()) // TextNodes carry all user-readable text in the DOM. + } + name == "li" -> { + append("\n * ") + } + name == "dt" -> { + append(" ") + } + StringUtil.`in`(name, "p", "h1", "h2", "h3", "h4", "h5", "tr") -> { + append("\n") + } } } @@ -95,13 +99,13 @@ class HtmlToPlainText { * @param str String with any encoding * @return Human readable text with minimal HTML formatting */ - fun getPlainText(str: String?): String? { + fun getPlainText(str: String): String { var str = str - if (!TextUtils.isEmpty(str) && isHtml(str)) { + if (str.isNotEmpty() && isHtml(str)) { val formatter = HtmlToPlainText() val feedDescription = Jsoup.parse(str) str = StringUtils.trim(formatter.getPlainText(feedDescription)) - } else if (TextUtils.isEmpty(str)) { + } else if (str.isEmpty()) { str = "" } @@ -116,7 +120,7 @@ class HtmlToPlainText { */ private fun isHtml(str: String?): Boolean { val htmlTagPattern = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>" - return Pattern.compile(htmlTagPattern).matcher(str).find() + return Pattern.compile(htmlTagPattern).matcher(str.toString()).find() } } } diff --git a/core/src/test/java/ac/mdiq/podcini/core/feed/LocalFeedUpdaterTest.kt b/core/src/test/java/ac/mdiq/podcini/core/feed/LocalFeedUpdaterTest.kt index d2b5a75a..61537b69 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/feed/LocalFeedUpdaterTest.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/feed/LocalFeedUpdaterTest.kt @@ -65,7 +65,7 @@ class LocalFeedUpdaterTest { PodDBAdapter.init(context!!) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() mapDummyMetadata(LOCAL_FEED_DIR1) diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbCleanupTests.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbCleanupTests.kt index c2e086f4..8404fac9 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbCleanupTests.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbCleanupTests.kt @@ -60,7 +60,7 @@ open class DbCleanupTests { PodDBAdapter.init(context!!) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() val prefEdit = PreferenceManager @@ -136,7 +136,7 @@ open class DbCleanupTests { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) if (addToQueue) { adapter.setQueue(items) @@ -200,11 +200,11 @@ open class DbCleanupTests { // add candidate for performAutoCleanup val feeds = DbTestUtils.saveFeedlist(1, 1, true) - val m: FeedMedia = feeds[0].items!!.get(0).media!! + val m: FeedMedia = feeds[0].items[0].media!! m.setDownloaded(true) m.setFile_url("file") val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setMedia(m) adapter.close() diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbNullCleanupAlgorithmTest.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbNullCleanupAlgorithmTest.kt index fe1ccd04..65100852 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbNullCleanupAlgorithmTest.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbNullCleanupAlgorithmTest.kt @@ -43,7 +43,7 @@ class DbNullCleanupAlgorithmTest { PodDBAdapter.init(context!!) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() val prefEdit = PreferenceManager.getDefaultSharedPreferences(context!!.applicationContext).edit() @@ -95,7 +95,7 @@ class DbNullCleanupAlgorithmTest { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbReaderTest.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbReaderTest.kt index 5b484da1..b9b440a2 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbReaderTest.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbReaderTest.kt @@ -46,7 +46,7 @@ class DbReaderTest { PodDBAdapter.init(context) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() } @@ -73,7 +73,7 @@ class DbReaderTest { @Test fun testGetFeedListSortOrder() { val adapter = getInstance() - adapter!!.open() + adapter.open() val feed1 = Feed(0, null, "A", "link", "d", null, null, null, "rss", "A", null, "", "", true) val feed2 = Feed(0, null, "b", "link", "d", null, null, null, "rss", "b", null, "", "", true) @@ -167,7 +167,7 @@ class DbReaderTest { } } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setQueue(queue) adapter.close() return queue @@ -219,7 +219,7 @@ class DbReaderTest { } } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.storeFeedItemlist(downloaded) adapter.close() return downloaded @@ -258,7 +258,7 @@ class DbReaderTest { } } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.storeFeedItemlist(newItems) adapter.close() return newItems @@ -298,7 +298,7 @@ class DbReaderTest { val adapter = getInstance() for (playedItems in mutableListOf(0, 1, 20, 100)) { - adapter!!.open() + adapter.open() for (i in 0 until playedItems) { val m: FeedMedia = feed.items[i].media!! m.setPlaybackCompletionDate(Date((i + 1).toLong())) @@ -331,7 +331,7 @@ class DbReaderTest { val numNew = 2 val feeds = DbTestUtils.saveFeedlist(numFeeds, numItems, true) val adapter = getInstance() - adapter!!.open() + adapter.open() for (i in 0 until numNew) { val item: FeedItem = feeds[0].items[i] item.setNew() @@ -445,7 +445,7 @@ class DbReaderTest { val ids = LongArray(playedItems) val adapter = getInstance() - adapter!!.open() + adapter.open() for (i in 0 until playedItems) { val m: FeedMedia = feed.items[i].media!! m.setPlaybackCompletionDate(Date((i + 1).toLong())) diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbTasksTest.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbTasksTest.kt index d8a50fe6..6645a219 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbTasksTest.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbTasksTest.kt @@ -46,7 +46,7 @@ class DbTasksTest { PodDBAdapter.init(context!!) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() } @@ -63,14 +63,14 @@ class DbTasksTest { val feed = Feed("url", null, "title") feed.items = mutableListOf() for (i in 0 until numItems) { - feed.items?.add(FeedItem(0, "item $i", "id $i", "link $i", + feed.items.add(FeedItem(0, "item $i", "id $i", "link $i", Date(), FeedItem.UNPLAYED, feed)) } val newFeed = updateFeed(context!!, feed, false) Assert.assertEquals(feed.id, newFeed!!.id) Assert.assertTrue(feed.id != 0L) - for (item in feed.items!!) { + for (item in feed.items) { Assert.assertFalse(item.isPlayed()) Assert.assertTrue(item.id != 0L) } @@ -99,11 +99,11 @@ class DbTasksTest { val feed = Feed("url", null, "title") feed.items = mutableListOf() for (i in 0 until numItemsOld) { - feed.items?.add(FeedItem(0, "item $i", "id $i", "link $i", + feed.items.add(FeedItem(0, "item $i", "id $i", "link $i", Date(i.toLong()), FeedItem.PLAYED, feed)) } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -112,14 +112,14 @@ class DbTasksTest { val feedID = feed.id feed.id = 0 val itemIDs: MutableList = ArrayList() - for (item in feed.items!!) { + for (item in feed.items) { Assert.assertTrue(item.id != 0L) itemIDs.add(item.id) item.id = 0 } for (i in numItemsOld until numItemsNew + numItemsOld) { - feed.items?.add(0, FeedItem(0, "item $i", "id $i", "link $i", + feed.items.add(0, FeedItem(0, "item $i", "id $i", "link $i", Date(i.toLong()), FeedItem.UNPLAYED, feed)) } @@ -141,7 +141,7 @@ class DbTasksTest { feed.items = (mutableListOf(item)) val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -159,7 +159,7 @@ class DbTasksTest { Assert.assertNotSame(newFeed, feed) val feedFromDB = getFeed(newFeed!!.id) - val feedItemFromDB: FeedItem = feedFromDB!!.items!![0] + val feedItemFromDB: FeedItem = feedFromDB!!.items[0] Assert.assertTrue(feedItemFromDB.isNew) } @@ -168,16 +168,16 @@ class DbTasksTest { val feed = Feed("url", null, "title") feed.items = mutableListOf() for (i in 0..9) { - feed.items?.add( + feed.items.add( FeedItem(0, "item $i", "id $i", "link $i", Date(i.toLong()), FeedItem.PLAYED, feed)) } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() // delete some items - feed.items?.subList(0, 2)?.clear() + feed.items.subList(0, 2).clear() val newFeed = updateFeed(context!!, feed, true) assertEquals(8, newFeed?.items?.size) // 10 - 2 = 8 items @@ -194,10 +194,10 @@ class DbTasksTest { FeedItem(0, "item $i", "id $i", "link $i", Date(i.toLong()), FeedItem.PLAYED, feed) val media = FeedMedia(item, "download url $i", 123, "media/mp3") item.setMedia(media) - feed.items?.add(item) + feed.items.add(item) } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -219,11 +219,11 @@ class DbTasksTest { private fun updatedFeedTest(newFeed: Feed?, feedID: Long, itemIDs: List, numItemsOld: Int, numItemsNew: Int) { Assert.assertEquals(feedID, newFeed!!.id) - assertEquals(numItemsNew + numItemsOld, newFeed.items?.size) - newFeed.items?.reverse() + assertEquals(numItemsNew + numItemsOld, newFeed.items.size) + newFeed.items.reverse() var lastDate = Date(0) for (i in 0 until numItemsOld) { - val item: FeedItem = newFeed.items!![i] + val item: FeedItem = newFeed.items[i] Assert.assertSame(newFeed, item.feed) Assert.assertEquals(itemIDs[i], item.id) Assert.assertTrue(item.isPlayed()) @@ -231,7 +231,7 @@ class DbTasksTest { lastDate = item.pubDate!! } for (i in numItemsOld until numItemsNew + numItemsOld) { - val item: FeedItem = newFeed.items!![i] + val item: FeedItem = newFeed.items[i] Assert.assertSame(newFeed, item.feed) Assert.assertTrue(item.id != 0L) Assert.assertFalse(item.isPlayed()) @@ -254,7 +254,7 @@ class DbTasksTest { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() return feed diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbTestUtils.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbTestUtils.kt index 16c15794..a06ed13e 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbTestUtils.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbTestUtils.kt @@ -28,7 +28,7 @@ internal object DbTestUtils { val feeds: MutableList = ArrayList() val adapter = getInstance() - adapter!!.open() + adapter.open() for (i in 0 until numFeeds) { val f = Feed(0, null, "feed $i", "link$i", "descr", null, null, null, null, "id$i", null, null, "url$i", false) @@ -53,7 +53,7 @@ internal object DbTestUtils { f.items.sortWith(FeedItemPubdateComparator()) adapter.setCompleteFeed(f) Assert.assertTrue(f.id != 0L) - for (item in f.items!!) { + for (item in f.items) { Assert.assertTrue(item.id != 0L) } feeds.add(f) diff --git a/core/src/test/java/ac/mdiq/podcini/core/storage/DbWriterTest.kt b/core/src/test/java/ac/mdiq/podcini/core/storage/DbWriterTest.kt index eaeb7c60..3a4a4076 100644 --- a/core/src/test/java/ac/mdiq/podcini/core/storage/DbWriterTest.kt +++ b/core/src/test/java/ac/mdiq/podcini/core/storage/DbWriterTest.kt @@ -71,7 +71,7 @@ class DbWriterTest { PodDBAdapter.init(context!!) deleteDatabase() val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.close() val prefEdit = PreferenceManager.getDefaultSharedPreferences( @@ -144,7 +144,7 @@ class DbWriterTest { items.add(item) val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() Assert.assertTrue(media!!.id != 0L) @@ -181,7 +181,7 @@ class DbWriterTest { queue.add(item) val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.setQueue(queue) adapter.close() @@ -225,7 +225,7 @@ class DbWriterTest { } var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -243,7 +243,7 @@ class DbWriterTest { } adapter = getInstance() - adapter!!.open() + adapter.open() var c = adapter.getFeedCursor(feed.id) Assert.assertEquals(0, c.count.toLong()) c.close() @@ -269,7 +269,7 @@ class DbWriterTest { feed.imageUrl = ("url") var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -278,7 +278,7 @@ class DbWriterTest { deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() val c = adapter.getFeedCursor(feed.id) Assert.assertEquals(0, c.count.toLong()) c.close() @@ -303,7 +303,7 @@ class DbWriterTest { } var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -315,7 +315,7 @@ class DbWriterTest { deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() var c = adapter.getFeedCursor(feed.id) Assert.assertEquals(0, c.count.toLong()) c.close() @@ -349,7 +349,7 @@ class DbWriterTest { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -410,7 +410,7 @@ class DbWriterTest { } var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -423,7 +423,7 @@ class DbWriterTest { deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() var c = adapter.getFeedCursor(feed.id) Assert.assertEquals(0, c.count.toLong()) c.close() @@ -453,7 +453,7 @@ class DbWriterTest { } var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -461,7 +461,7 @@ class DbWriterTest { deleteFeedItems(context!!, itemsToDelete)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() for (i in 0 until feed.items.size) { val feedItem: FeedItem = feed.items[i] val c = adapter.getFeedItemCursor(feedItem.id.toString()) @@ -484,7 +484,7 @@ class DbWriterTest { feed.items.add(item) item.setMedia(media) val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() Assert.assertTrue(media.id != 0L) @@ -497,7 +497,7 @@ class DbWriterTest { var media: FeedMedia? = playbackHistorySetup(null) addItemToPlaybackHistory(media)[TIMEOUT, TimeUnit.SECONDS] val adapter = getInstance() - adapter!!.open() + adapter.open() media = getFeedMedia(media!!.id) adapter.close() @@ -513,7 +513,7 @@ class DbWriterTest { var media: FeedMedia? = playbackHistorySetup(Date(oldDate)) addItemToPlaybackHistory(media)[TIMEOUT, TimeUnit.SECONDS] val adapter = getInstance() - adapter!!.open() + adapter.open() media = getFeedMedia(media!!.id) adapter.close() @@ -534,7 +534,7 @@ class DbWriterTest { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -561,7 +561,7 @@ class DbWriterTest { feed.items.add(item) var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -569,7 +569,7 @@ class DbWriterTest { addQueueItem(context, item)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() val cursor = adapter.queueIDCursor Assert.assertTrue(cursor.moveToFirst()) Assert.assertEquals(item.id, cursor.getLong(0)) @@ -587,7 +587,7 @@ class DbWriterTest { feed.items.add(item) var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -595,7 +595,7 @@ class DbWriterTest { addQueueItem(context, item)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() var cursor = adapter.queueIDCursor Assert.assertTrue(cursor.moveToFirst()) Assert.assertEquals(item.id, cursor.getLong(0)) @@ -604,7 +604,7 @@ class DbWriterTest { addQueueItem(context, item)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() cursor = adapter.queueIDCursor Assert.assertTrue(cursor.moveToFirst()) Assert.assertEquals(item.id, cursor.getLong(0)) @@ -619,7 +619,7 @@ class DbWriterTest { val numItems = 10 val feed = queueTestSetupMultipleItems(numItems) val adapter = getInstance() - adapter!!.open() + adapter.open() val cursor = adapter.queueIDCursor Assert.assertTrue(cursor.moveToFirst()) Assert.assertEquals(numItems.toLong(), cursor.count.toLong()) @@ -643,7 +643,7 @@ class DbWriterTest { queueTestSetupMultipleItems(numItems) clearQueue()[TIMEOUT, TimeUnit.SECONDS] val adapter = getInstance() - adapter!!.open() + adapter.open() val cursor = adapter.queueIDCursor Assert.assertFalse(cursor.moveToFirst()) cursor.close() @@ -659,13 +659,13 @@ class DbWriterTest { for (removeIndex in 0 until numItems) { val item: FeedItem = feed.items[removeIndex] var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setQueue(feed.items.toList()) adapter.close() removeQueueItem(context!!, false, item)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() val queue = adapter.queueIDCursor Assert.assertEquals((numItems - 1).toLong(), queue.count.toLong()) for (i in 0 until queue.count) { @@ -732,7 +732,7 @@ class DbWriterTest { } var adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -748,13 +748,13 @@ class DbWriterTest { val fromID: Long = feed.items[from].id adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setQueue(feed.items) adapter.close() moveQueueItem(from, to, false)[TIMEOUT, TimeUnit.SECONDS] adapter = getInstance() - adapter!!.open() + adapter.open() val queue = adapter.queueIDCursor Assert.assertEquals(numItems.toLong(), queue.count.toLong()) Assert.assertTrue(queue.moveToPosition(from)) @@ -782,7 +782,7 @@ class DbWriterTest { } val adapter = getInstance() - adapter!!.open() + adapter.open() adapter.setCompleteFeed(feed) adapter.close() @@ -824,10 +824,10 @@ class DbWriterTest { private fun withPodDB(action: Consumer) { val adapter = getInstance() try { - adapter!!.open() + adapter.open() action.accept(adapter) } finally { - adapter!!.close() + adapter.close() } } diff --git a/event/src/main/java/ac/mdiq/podcini/event/QueueEvent.kt b/event/src/main/java/ac/mdiq/podcini/event/QueueEvent.kt index b8d3902a..a3f7688d 100644 --- a/event/src/main/java/ac/mdiq/podcini/event/QueueEvent.kt +++ b/event/src/main/java/ac/mdiq/podcini/event/QueueEvent.kt @@ -4,7 +4,7 @@ import ac.mdiq.podcini.model.feed.FeedItem class QueueEvent private constructor(@JvmField val action: Action, @JvmField val item: FeedItem?, - @JvmField val items: List?, + @JvmField val items: List, @JvmField val position: Int ) { enum class Action { @@ -14,38 +14,38 @@ class QueueEvent private constructor(@JvmField val action: Action, companion object { @JvmStatic - fun added(item: FeedItem?, position: Int): QueueEvent { - return QueueEvent(Action.ADDED, item, null, position) + fun added(item: FeedItem, position: Int): QueueEvent { + return QueueEvent(Action.ADDED, item, listOf(), position) } @JvmStatic - fun setQueue(queue: List?): QueueEvent { + fun setQueue(queue: List): QueueEvent { return QueueEvent(Action.SET_QUEUE, null, queue, -1) } @JvmStatic - fun removed(item: FeedItem?): QueueEvent { - return QueueEvent(Action.REMOVED, item, null, -1) + fun removed(item: FeedItem): QueueEvent { + return QueueEvent(Action.REMOVED, item, listOf(), -1) } @JvmStatic - fun irreversibleRemoved(item: FeedItem?): QueueEvent { - return QueueEvent(Action.IRREVERSIBLE_REMOVED, item, null, -1) + fun irreversibleRemoved(item: FeedItem): QueueEvent { + return QueueEvent(Action.IRREVERSIBLE_REMOVED, item, listOf(), -1) } @JvmStatic fun cleared(): QueueEvent { - return QueueEvent(Action.CLEARED, null, null, -1) + return QueueEvent(Action.CLEARED, null, listOf(), -1) } @JvmStatic - fun sorted(sortedQueue: List?): QueueEvent { + fun sorted(sortedQueue: List): QueueEvent { return QueueEvent(Action.SORTED, null, sortedQueue, -1) } @JvmStatic - fun moved(item: FeedItem?, newPosition: Int): QueueEvent { - return QueueEvent(Action.MOVED, item, null, newPosition) + fun moved(item: FeedItem, newPosition: Int): QueueEvent { + return QueueEvent(Action.MOVED, item, listOf(), newPosition) } } } diff --git a/model/src/main/java/ac/mdiq/podcini/model/feed/FeedItem.kt b/model/src/main/java/ac/mdiq/podcini/model/feed/FeedItem.kt index fe2cb127..5da8b549 100644 --- a/model/src/main/java/ac/mdiq/podcini/model/feed/FeedItem.kt +++ b/model/src/main/java/ac/mdiq/podcini/model/feed/FeedItem.kt @@ -123,7 +123,7 @@ class FeedItem : FeedComponent, Serializable { this.title = title this.itemIdentifier = itemIdentifier this.link = link - this.pubDate = if ((pubDate != null)) pubDate.clone() as Date else null + this.pubDate = if (pubDate != null) pubDate.clone() as Date else null this.playState = state this.feed = feed this.hasChapters = false @@ -145,7 +145,7 @@ class FeedItem : FeedComponent, Serializable { this.title = title this.itemIdentifier = itemIdentifier this.link = link - this.pubDate = if ((pubDate != null)) pubDate.clone() as Date else null + this.pubDate = if (pubDate != null) pubDate.clone() as Date else null this.playState = state this.feed = feed this.hasChapters = hasChapters @@ -246,7 +246,7 @@ class FeedItem : FeedComponent, Serializable { } fun isPlayed(): Boolean { - return playState === PLAYED + return playState == PLAYED } fun setPlayed(played: Boolean) { @@ -299,7 +299,7 @@ class FeedItem : FeedComponent, Serializable { } fun hasChapters(): Boolean { - return hasChapters + return chapters?.isNotEmpty() ?: hasChapters } fun disableAutoDownload() { diff --git a/model/src/main/java/ac/mdiq/podcini/model/feed/FeedMedia.kt b/model/src/main/java/ac/mdiq/podcini/model/feed/FeedMedia.kt index eb48776a..80c2fb4a 100644 --- a/model/src/main/java/ac/mdiq/podcini/model/feed/FeedMedia.kt +++ b/model/src/main/java/ac/mdiq/podcini/model/feed/FeedMedia.kt @@ -274,6 +274,10 @@ class FeedMedia : FeedFile, Playable { return item!!.chapters!! } + override fun chaptersLoaded(): Boolean { + return item?.chapters != null + } + override fun getWebsiteLink(): String? { if (item == null) { return null diff --git a/model/src/main/java/ac/mdiq/podcini/model/playback/Playable.kt b/model/src/main/java/ac/mdiq/podcini/model/playback/Playable.kt index d15fd3a7..8e57057d 100644 --- a/model/src/main/java/ac/mdiq/podcini/model/playback/Playable.kt +++ b/model/src/main/java/ac/mdiq/podcini/model/playback/Playable.kt @@ -29,6 +29,8 @@ interface Playable : Parcelable, Serializable { */ fun getChapters(): List + fun chaptersLoaded(): Boolean + /** * Returns a link to a website that is meant to be shown in a browser */ diff --git a/model/src/main/java/ac/mdiq/podcini/model/playback/RemoteMedia.kt b/model/src/main/java/ac/mdiq/podcini/model/playback/RemoteMedia.kt index 0b48c3b0..f1b4e739 100644 --- a/model/src/main/java/ac/mdiq/podcini/model/playback/RemoteMedia.kt +++ b/model/src/main/java/ac/mdiq/podcini/model/playback/RemoteMedia.kt @@ -124,6 +124,10 @@ class RemoteMedia : Playable { return chapters ?: listOf() } + override fun chaptersLoaded(): Boolean { + return chapters != null + } + override fun getEpisodeTitle(): String { return episodeTitle!! } diff --git a/net/common/src/main/java/ac/mdiq/podcini/net/common/UrlChecker.kt b/net/common/src/main/java/ac/mdiq/podcini/net/common/UrlChecker.kt index ce569026..4d6bb238 100644 --- a/net/common/src/main/java/ac/mdiq/podcini/net/common/UrlChecker.kt +++ b/net/common/src/main/java/ac/mdiq/podcini/net/common/UrlChecker.kt @@ -30,34 +30,43 @@ object UrlChecker { var url = url url = url.trim { it <= ' ' } val lowerCaseUrl = url.lowercase() // protocol names are case insensitive - if (lowerCaseUrl.startsWith("feed://")) { - Log.d(TAG, "Replacing feed:// with http://") - return prepareUrl(url.substring("feed://".length)) - } else if (lowerCaseUrl.startsWith("pcast://")) { - Log.d(TAG, "Removing pcast://") - return prepareUrl(url.substring("pcast://".length)) - } else if (lowerCaseUrl.startsWith("pcast:")) { - Log.d(TAG, "Removing pcast:") - return prepareUrl(url.substring("pcast:".length)) - } else if (lowerCaseUrl.startsWith("itpc")) { - Log.d(TAG, "Replacing itpc:// with http://") - return prepareUrl(url.substring("itpc://".length)) - } else if (lowerCaseUrl.startsWith(AP_SUBSCRIBE)) { - Log.d(TAG, "Removing podcini-subscribe://") - return prepareUrl(url.substring(AP_SUBSCRIBE.length)) - } else if (lowerCaseUrl.contains(AP_SUBSCRIBE_DEEPLINK)) { - Log.d(TAG, "Removing $AP_SUBSCRIBE_DEEPLINK") - val removedWebsite = url.substring(url.indexOf("?url=") + "?url=".length) - return try { - prepareUrl(URLDecoder.decode(removedWebsite, "UTF-8")) - } catch (e: UnsupportedEncodingException) { - prepareUrl(removedWebsite) + when { + lowerCaseUrl.startsWith("feed://") -> { + Log.d(TAG, "Replacing feed:// with http://") + return prepareUrl(url.substring("feed://".length)) + } + lowerCaseUrl.startsWith("pcast://") -> { + Log.d(TAG, "Removing pcast://") + return prepareUrl(url.substring("pcast://".length)) + } + lowerCaseUrl.startsWith("pcast:") -> { + Log.d(TAG, "Removing pcast:") + return prepareUrl(url.substring("pcast:".length)) + } + lowerCaseUrl.startsWith("itpc") -> { + Log.d(TAG, "Replacing itpc:// with http://") + return prepareUrl(url.substring("itpc://".length)) + } + lowerCaseUrl.startsWith(AP_SUBSCRIBE) -> { + Log.d(TAG, "Removing podcini-subscribe://") + return prepareUrl(url.substring(AP_SUBSCRIBE.length)) + } + lowerCaseUrl.contains(AP_SUBSCRIBE_DEEPLINK) -> { + Log.d(TAG, "Removing $AP_SUBSCRIBE_DEEPLINK") + val removedWebsite = url.substring(url.indexOf("?url=") + "?url=".length) + return try { + prepareUrl(URLDecoder.decode(removedWebsite, "UTF-8")) + } catch (e: UnsupportedEncodingException) { + prepareUrl(removedWebsite) + } + } + !(lowerCaseUrl.startsWith("http://") || lowerCaseUrl.startsWith("https://")) -> { + Log.d(TAG, "Adding http:// at the beginning of the URL") + return "http://$url" + } + else -> { + return url } - } else if (!(lowerCaseUrl.startsWith("http://") || lowerCaseUrl.startsWith("https://"))) { - Log.d(TAG, "Adding http:// at the beginning of the URL") - return "http://$url" - } else { - return url } } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/CombinedSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/CombinedSearcher.kt index 83646104..397b1887 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/CombinedSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/CombinedSearcher.kt @@ -11,7 +11,7 @@ import java.util.* import java.util.concurrent.CountDownLatch class CombinedSearcher : PodcastSearcher { - override fun search(query: String): Single?>? { + override fun search(query: String): Single?> { val disposables = ArrayList() val singleResults: MutableList?> = ArrayList( Collections.nCopies?>(PodcastSearcherRegistry.searchProviders.size, null)) @@ -23,9 +23,8 @@ class CombinedSearcher : PodcastSearcher { latch.countDown() continue } - val index = i - disposables.add(searcher.search(query)!!.subscribe({ e: List? -> - singleResults[index] = e + disposables.add(searcher.search(query).subscribe({ e: List? -> + singleResults[i] = e latch.countDown() }, { throwable: Throwable? -> Log.d(TAG, Log.getStackTraceString(throwable)) @@ -79,7 +78,7 @@ class CombinedSearcher : PodcastSearcher { return results } - override fun lookupUrl(url: String): Single? { + override fun lookupUrl(url: String): Single { return PodcastSearcherRegistry.lookupUrl(url) } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/FyydPodcastSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/FyydPodcastSearcher.kt index 6c1b55a3..4cf1c238 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/FyydPodcastSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/FyydPodcastSearcher.kt @@ -10,7 +10,7 @@ import io.reactivex.schedulers.Schedulers class FyydPodcastSearcher : PodcastSearcher { private val client = FyydClient(getHttpClient()) - override fun search(query: String): Single?>? { + override fun search(query: String): Single?> { return Single.create { subscriber: SingleEmitter?> -> val response = client.searchPodcasts( query, 10) @@ -30,7 +30,7 @@ class FyydPodcastSearcher : PodcastSearcher { .observeOn(AndroidSchedulers.mainThread()) } - override fun lookupUrl(url: String): Single? { + override fun lookupUrl(url: String): Single { return Single.just(url) } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/GpodnetPodcastSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/GpodnetPodcastSearcher.kt index 84178c2c..32a6a01e 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/GpodnetPodcastSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/GpodnetPodcastSearcher.kt @@ -10,7 +10,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers class GpodnetPodcastSearcher : PodcastSearcher { - override fun search(query: String): Single?>? { + override fun search(query: String): Single?> { return Single.create { subscriber: SingleEmitter?> -> try { val service = GpodnetService(getHttpClient(), @@ -31,7 +31,7 @@ class GpodnetPodcastSearcher : PodcastSearcher { .observeOn(AndroidSchedulers.mainThread()) } - override fun lookupUrl(url: String): Single? { + override fun lookupUrl(url: String): Single { return Single.just(url) } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesPodcastSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesPodcastSearcher.kt index dfdfb99d..a57bf2b0 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesPodcastSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesPodcastSearcher.kt @@ -15,7 +15,7 @@ import java.net.URLEncoder import java.util.regex.Pattern class ItunesPodcastSearcher : PodcastSearcher { - override fun search(query: String): Single?>? { + override fun search(query: String): Single?> { return Single.create?> { subscriber: SingleEmitter?> -> val encodedQuery = try { URLEncoder.encode(query, "UTF-8") @@ -58,7 +58,7 @@ class ItunesPodcastSearcher : PodcastSearcher { .observeOn(AndroidSchedulers.mainThread()) } - override fun lookupUrl(url: String): Single? { + override fun lookupUrl(url: String): Single { val pattern = Pattern.compile(PATTERN_BY_ID) val matcher = pattern.matcher(url) val lookupUrl = if (matcher.find()) ("https://itunes.apple.com/lookup?id=" + matcher.group(1)) else url diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesTopListLoader.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesTopListLoader.kt index 11500b9c..d471ae31 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesTopListLoader.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/ItunesTopListLoader.kt @@ -18,7 +18,7 @@ class ItunesTopListLoader(private val context: Context) { @Throws(JSONException::class, IOException::class) fun loadToplist(country: String, limit: Int, subscribed: List): List { val client = getHttpClient() - var feedString: String + val feedString: String var loadCountry = country if (COUNTRY_CODE_UNSET == country) { loadCountry = Locale.getDefault().country diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastIndexPodcastSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastIndexPodcastSearcher.kt index 67d012f4..f124d889 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastIndexPodcastSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastIndexPodcastSearcher.kt @@ -17,9 +17,9 @@ import java.security.MessageDigest import java.util.* class PodcastIndexPodcastSearcher : PodcastSearcher { - override fun search(query: String): Single?>? { + override fun search(query: String): Single?> { return Single.create { subscriber: SingleEmitter?> -> - var encodedQuery = try { + val encodedQuery = try { URLEncoder.encode(query, "UTF-8") } catch (e: UnsupportedEncodingException) { // this won't ever be thrown @@ -57,7 +57,7 @@ class PodcastIndexPodcastSearcher : PodcastSearcher { .observeOn(AndroidSchedulers.mainThread()) } - override fun lookupUrl(url: String): Single? { + override fun lookupUrl(url: String): Single { return Single.just(url) } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearchResult.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearchResult.kt index f2284c24..0ea216e7 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearchResult.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearchResult.kt @@ -36,9 +36,9 @@ class PodcastSearchResult private constructor( */ fun fromItunes(json: JSONObject): PodcastSearchResult { val title = json.optString("collectionName", "") - val imageUrl = json.optString("artworkUrl100", null) - val feedUrl = json.optString("feedUrl", null) - val author = json.optString("artistName", null) + val imageUrl: String? = json.optString("artworkUrl100").takeIf { it.isNotEmpty() } + val feedUrl: String? = json.optString("feedUrl").takeIf { it.isNotEmpty() } + val author: String? = json.optString("artistName").takeIf { it.isNotEmpty() } return PodcastSearchResult(title, imageUrl, feedUrl, author) } @@ -90,9 +90,9 @@ class PodcastSearchResult private constructor( fun fromPodcastIndex(json: JSONObject): PodcastSearchResult { val title = json.optString("title", "") - val imageUrl = json.optString("image", null) - val feedUrl = json.optString("url", null) - val author = json.optString("author", null) + val imageUrl: String? = json.optString("image").takeIf { it.isNotEmpty() } + val feedUrl: String? = json.optString("url").takeIf { it.isNotEmpty() } + val author: String? = json.optString("author").takeIf { it.isNotEmpty() } return PodcastSearchResult(title, imageUrl, feedUrl, author) } } diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcher.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcher.kt index 66dc6015..af845f38 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcher.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcher.kt @@ -3,9 +3,9 @@ package ac.mdiq.podcini.net.discovery import io.reactivex.Single interface PodcastSearcher { - fun search(query: String): Single?>? + fun search(query: String): Single?> - fun lookupUrl(resultUrl: String): Single? + fun lookupUrl(resultUrl: String): Single fun urlNeedsLookup(resultUrl: String): Boolean diff --git a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcherRegistry.kt b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcherRegistry.kt index 7eca45d5..23c081d6 100644 --- a/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcherRegistry.kt +++ b/net/discovery/src/main/java/ac/mdiq/podcini/net/discovery/PodcastSearcherRegistry.kt @@ -19,7 +19,7 @@ object PodcastSearcherRegistry { } private set - fun lookupUrl(url: String): Single? { + fun lookupUrl(url: String): Single { for (searchProviderInfo in searchProviders) { if (searchProviderInfo.searcher.javaClass != CombinedSearcher::class.java && searchProviderInfo.searcher.urlNeedsLookup(url)) { diff --git a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/AntennaPodSslSocketFactory.kt b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/AntennaPodSslSocketFactory.kt index c4f46aed..1aa791b9 100644 --- a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/AntennaPodSslSocketFactory.kt +++ b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/AntennaPodSslSocketFactory.kt @@ -15,7 +15,7 @@ import javax.net.ssl.TrustManager * This fixes issues with old Android versions that abort if the server does not know TLS 1.0 */ class PodciniSslSocketFactory(trustManager: TrustManager) : SSLSocketFactory() { - private var factory: SSLSocketFactory? = null + private lateinit var factory: SSLSocketFactory init { try { @@ -37,51 +37,51 @@ class PodciniSslSocketFactory(trustManager: TrustManager) : SSLSocketFactory() { } override fun getDefaultCipherSuites(): Array { - return factory!!.defaultCipherSuites + return factory.defaultCipherSuites } override fun getSupportedCipherSuites(): Array { - return factory!!.supportedCipherSuites + return factory.supportedCipherSuites } @Throws(IOException::class) override fun createSocket(): Socket { - val result = factory!!.createSocket() as SSLSocket + val result = factory.createSocket() as SSLSocket configureSocket(result) return result } @Throws(IOException::class) override fun createSocket(var1: String, var2: Int): Socket { - val result = factory!!.createSocket(var1, var2) as SSLSocket + val result = factory.createSocket(var1, var2) as SSLSocket configureSocket(result) return result } @Throws(IOException::class) override fun createSocket(var1: Socket, var2: String, var3: Int, var4: Boolean): Socket { - val result = factory!!.createSocket(var1, var2, var3, var4) as SSLSocket + val result = factory.createSocket(var1, var2, var3, var4) as SSLSocket configureSocket(result) return result } @Throws(IOException::class) override fun createSocket(var1: InetAddress, var2: Int): Socket { - val result = factory!!.createSocket(var1, var2) as SSLSocket + val result = factory.createSocket(var1, var2) as SSLSocket configureSocket(result) return result } @Throws(IOException::class) override fun createSocket(var1: String, var2: Int, var3: InetAddress, var4: Int): Socket { - val result = factory!!.createSocket(var1, var2, var3, var4) as SSLSocket + val result = factory.createSocket(var1, var2, var3, var4) as SSLSocket configureSocket(result) return result } @Throws(IOException::class) override fun createSocket(var1: InetAddress, var2: Int, var3: InetAddress, var4: Int): Socket { - val result = factory!!.createSocket(var1, var2, var3, var4) as SSLSocket + val result = factory.createSocket(var1, var2, var3, var4) as SSLSocket configureSocket(result) return result } diff --git a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/CompositeX509TrustManager.kt b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/CompositeX509TrustManager.kt index 2326b62f..7f4a51ad 100644 --- a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/CompositeX509TrustManager.kt +++ b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/CompositeX509TrustManager.kt @@ -46,7 +46,7 @@ class CompositeX509TrustManager(private val trustManagers: List { val certificates: MutableList = ArrayList() for (trustManager in trustManagers) { - certificates.addAll(Arrays.asList(*trustManager.acceptedIssuers)) + certificates.addAll(listOf(*trustManager.acceptedIssuers)) } return certificates.toTypedArray() } diff --git a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/SslClientSetup.kt b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/SslClientSetup.kt index fba4d51c..3241538b 100644 --- a/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/SslClientSetup.kt +++ b/net/ssl/src/main/java/ac/mdiq/podcini/net/ssl/SslClientSetup.kt @@ -3,7 +3,6 @@ package ac.mdiq.podcini.net.ssl import ac.mdiq.podcini.net.ssl.BackportTrustManager.create import okhttp3.ConnectionSpec import okhttp3.OkHttpClient.Builder -import java.util.* object SslClientSetup { fun installCertificates(builder: Builder) { diff --git a/net/sync/model/src/main/java/ac/mdiq/podcini/net/sync/model/EpisodeAction.kt b/net/sync/model/src/main/java/ac/mdiq/podcini/net/sync/model/EpisodeAction.kt index 404e2624..e9ed166f 100644 --- a/net/sync/model/src/main/java/ac/mdiq/podcini/net/sync/model/EpisodeAction.kt +++ b/net/sync/model/src/main/java/ac/mdiq/podcini/net/sync/model/EpisodeAction.kt @@ -1,8 +1,7 @@ package ac.mdiq.podcini.net.sync.model -import android.text.TextUtils -import android.util.Log import ac.mdiq.podcini.model.feed.FeedItem +import android.util.Log import org.json.JSONException import org.json.JSONObject import java.text.ParseException @@ -87,7 +86,7 @@ class EpisodeAction private constructor(builder: Builder) { obj.put("action", this.actionString) val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US) formatter.timeZone = TimeZone.getTimeZone("UTC") - obj.put("timestamp", formatter.format(this.timestamp)) + if (this.timestamp != null) obj.put("timestamp", formatter.format(this.timestamp)) if (this.action == Action.PLAY) { obj.put("started", this.started) obj.put("position", this.position) @@ -190,10 +189,10 @@ class EpisodeAction private constructor(builder: Builder) { */ @JvmStatic fun readFromJsonObject(`object`: JSONObject): EpisodeAction? { - val podcast = `object`.optString("podcast", null) - val episode = `object`.optString("episode", null) - val actionString = `object`.optString("action", null) - if (TextUtils.isEmpty(podcast) || TextUtils.isEmpty(episode) || TextUtils.isEmpty(actionString)) { + val podcast = `object`.optString("podcast") + val episode = `object`.optString("episode") + val actionString = `object`.optString("action") + if (podcast.isNullOrEmpty() || episode.isNullOrEmpty() || actionString.isNullOrEmpty()) { return null } val action: Action @@ -203,8 +202,8 @@ class EpisodeAction private constructor(builder: Builder) { return null } val builder = Builder(podcast, episode, action) - val utcTimestamp = `object`.optString("timestamp", null) - if (!TextUtils.isEmpty(utcTimestamp)) { + val utcTimestamp = `object`.optString("timestamp") + if (utcTimestamp.isNotEmpty()) { try { val parser = SimpleDateFormat(PATTERN_ISO_DATEFORMAT, Locale.US) parser.timeZone = TimeZone.getTimeZone("UTC") @@ -213,8 +212,8 @@ class EpisodeAction private constructor(builder: Builder) { e.printStackTrace() } } - val guid = `object`.optString("guid", null) - if (!TextUtils.isEmpty(guid)) { + val guid = `object`.optString("guid") + if (guid.isNotEmpty()) { builder.guid(guid) } if (action == Action.PLAY) { diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/FeedHandler.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/FeedHandler.kt index 0c10886e..cc19c134 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/FeedHandler.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/FeedHandler.kt @@ -1,9 +1,9 @@ package ac.mdiq.podcini.parser.feed -import android.util.Log import ac.mdiq.podcini.model.feed.Feed import ac.mdiq.podcini.parser.feed.UnsupportedFeedtypeException import ac.mdiq.podcini.parser.feed.util.TypeGetter +import android.util.Log import org.apache.commons.io.input.XmlStreamReader import org.xml.sax.InputSource import org.xml.sax.SAXException diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/PodcastIndexChapterParser.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/PodcastIndexChapterParser.kt index 2dcd18df..5dc51072 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/PodcastIndexChapterParser.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/PodcastIndexChapterParser.kt @@ -5,7 +5,7 @@ import org.json.JSONException import org.json.JSONObject object PodcastIndexChapterParser { - fun parse(jsonStr: String?): List? { + fun parse(jsonStr: String): List { try { val chapters: MutableList = ArrayList() val obj = JSONObject(jsonStr) @@ -13,15 +13,15 @@ object PodcastIndexChapterParser { for (i in 0 until objChapters.length()) { val jsonObject = objChapters.getJSONObject(i) val startTime = jsonObject.optInt("startTime", 0) - val title = jsonObject.optString("title") - val link = jsonObject.optString("url") - val img = jsonObject.optString("img") + val title = jsonObject.optString("title").takeIf { it.isNotEmpty() } + val link = jsonObject.optString("url").takeIf { it.isNotEmpty() } + val img = jsonObject.optString("img").takeIf { it.isNotEmpty() } chapters.add(Chapter(startTime * 1000L, title, link, img)) } return chapters } catch (e: JSONException) { e.printStackTrace() } - return null + return listOf() } } diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/element/AtomText.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/element/AtomText.kt index 115d7370..2491c2a2 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/element/AtomText.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/element/AtomText.kt @@ -4,20 +4,25 @@ import androidx.core.text.HtmlCompat import ac.mdiq.podcini.parser.feed.namespace.Namespace /** Represents Atom Element which contains text (content, title, summary). */ -class AtomText(name: String?, namespace: Namespace?, private val type: String?) : SyndElement( - name!!, namespace!!) { +class AtomText(name: String?, namespace: Namespace?, private val type: String?) : SyndElement(name!!, namespace!!) { + private var content: String? = null val processedContent: String? /** Processes the content according to the type and returns it. */ - get() = if (type == null) { - content - } else if (type == TYPE_HTML) { - HtmlCompat.fromHtml(content!!, HtmlCompat.FROM_HTML_MODE_LEGACY).toString() - } else if (type == TYPE_XHTML) { - content - } else { // Handle as text by default - content + get() = when (type) { + null -> { + content + } + TYPE_HTML -> { + HtmlCompat.fromHtml(content!!, HtmlCompat.FROM_HTML_MODE_LEGACY).toString() + } + TYPE_XHTML -> { + content + } + else -> { // Handle as text by default + content + } } fun setContent(content: String?) { diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/namespace/Atom.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/namespace/Atom.kt index 905c2336..33c309f8 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/namespace/Atom.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/namespace/Atom.kt @@ -205,7 +205,7 @@ class Atom : Namespace() { /** * Regexp to test whether an Element is a Text Element. */ - private const val isText = (TITLE + "|" + CONTENT + "|" + SUBTITLE + "|" + SUMMARY) + private const val isText = ("$TITLE|$CONTENT|$SUBTITLE|$SUMMARY") private const val isFeed = FEED + "|" + Rss20.CHANNEL private const val isFeedItem = ENTRY + "|" + Rss20.ITEM diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/DurationParser.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/DurationParser.kt index 3305d154..47e40cf1 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/DurationParser.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/DurationParser.kt @@ -8,14 +8,19 @@ object DurationParser { fun inMillis(durationStr: String): Long { val parts = durationStr.trim { it <= ' ' }.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - return if (parts.size == 1) { - toMillis(parts[0]) - } else if (parts.size == 2) { - toMillis("0", parts[0], parts[1]) - } else if (parts.size == 3) { - toMillis(parts[0], parts[1], parts[2]) - } else { - throw NumberFormatException() + return when (parts.size) { + 1 -> { + toMillis(parts[0]) + } + 2 -> { + toMillis("0", parts[0], parts[1]) + } + 3 -> { + toMillis(parts[0], parts[1], parts[2]) + } + else -> { + throw NumberFormatException() + } } } diff --git a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/TypeGetter.kt b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/TypeGetter.kt index 18df1031..902dbc11 100644 --- a/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/TypeGetter.kt +++ b/parser/feed/src/main/java/ac/mdiq/podcini/parser/feed/util/TypeGetter.kt @@ -100,7 +100,7 @@ class TypeGetter { try { reader.close() } catch (e: IOException) { - Log.d(TAG, "IOException: " + reader.toString()) + Log.d(TAG, "IOException: $reader") e.printStackTrace() } } @@ -111,9 +111,11 @@ class TypeGetter { } private fun createReader(feed: Feed): Reader? { + if (feed.file_url == null) return null + val reader: Reader try { - reader = XmlStreamReader(File(feed.file_url)) + reader = XmlStreamReader(File(feed.file_url!!)) } catch (e: FileNotFoundException) { Log.d(TAG, "FileNotFoundException: " + feed.file_url) e.printStackTrace() diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/ID3Reader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/ID3Reader.kt index da3e8ad2..837ce080 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/ID3Reader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/ID3Reader.kt @@ -147,12 +147,16 @@ open class ID3Reader(private val inputStream: CountingInputStream) { @Throws(IOException::class) fun readEncodedString(encoding: Int, max: Int): String { - return if (encoding == ENCODING_UTF16_WITH_BOM.toInt() || encoding == ENCODING_UTF16_WITHOUT_BOM.toInt()) { - readEncodedString2(Charset.forName("UTF-16"), max) - } else if (encoding == ENCODING_UTF8.toInt()) { - readEncodedString2(Charset.forName("UTF-8"), max) - } else { - readEncodedString1(Charset.forName("ISO-8859-1"), max) + return when (encoding) { + ENCODING_UTF16_WITH_BOM.toInt(), ENCODING_UTF16_WITHOUT_BOM.toInt() -> { + readEncodedString2(Charset.forName("UTF-16"), max) + } + ENCODING_UTF8.toInt() -> { + readEncodedString2(Charset.forName("UTF-8"), max) + } + else -> { + readEncodedString1(Charset.forName("ISO-8859-1"), max) + } } } diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/FrameHeader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/FrameHeader.kt index 6fb8075c..18d4d8d9 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/FrameHeader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/FrameHeader.kt @@ -1,4 +1,3 @@ package ac.mdiq.podcini.parser.media.id3.model -class FrameHeader(id: String?, size: Int, flags: Short) : Header( - id!!, size) +class FrameHeader(id: String?, size: Int, flags: Short) : Header(id!!, size) diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/TagHeader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/TagHeader.kt index eb9ac192..f20f3179 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/TagHeader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/id3/model/TagHeader.kt @@ -1,9 +1,7 @@ package ac.mdiq.podcini.parser.media.id3.model -class TagHeader(id: String?, size: Int, @JvmField val version: Short, private val flags: Byte) : Header( - id!!, size) { +class TagHeader(id: String?, size: Int, @JvmField val version: Short, private val flags: Byte) : Header(id!!, size) { override fun toString(): String { - return ("TagHeader [version=" + version + ", flags=" + flags + ", id=" - + id + ", size=" + size + "]") + return ("TagHeader [version=" + version + ", flags=" + flags + ", id=" + id + ", size=" + size + "]") } } diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentChapterReader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentChapterReader.kt index 6508ec1d..8676f7e1 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentChapterReader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentChapterReader.kt @@ -1,9 +1,8 @@ package ac.mdiq.podcini.parser.media.vorbis -import android.util.Log import ac.mdiq.podcini.model.feed.Chapter import ac.mdiq.podcini.parser.media.BuildConfig -import ac.mdiq.podcini.parser.media.vorbis.VorbisCommentReaderException +import android.util.Log import java.io.InputStream import java.util.concurrent.TimeUnit @@ -22,24 +21,24 @@ class VorbisCommentChapterReader(input: InputStream?) : VorbisCommentReader(inpu val attribute = getAttributeTypeFromKey(key) val id = getIdFromKey(key) var chapter = getChapterById(id.toLong()) - if (attribute == null) { - if (getChapterById(id.toLong()) == null) { - // new chapter - val start = getStartTimeFromValue(value) - chapter = Chapter() - chapter.chapterId = "" + id - chapter.start = start - chapters.add(chapter) - } else { - throw VorbisCommentReaderException("Found chapter with duplicate ID ($key, $value)") + when (attribute) { + null -> { + if (getChapterById(id.toLong()) == null) { + // new chapter + val start = getStartTimeFromValue(value) + chapter = Chapter() + chapter.chapterId = "" + id + chapter.start = start + chapters.add(chapter) + } else { + throw VorbisCommentReaderException("Found chapter with duplicate ID ($key, $value)") + } } - } else if (attribute == CHAPTER_ATTRIBUTE_TITLE) { - if (chapter != null) { - chapter.title = value + CHAPTER_ATTRIBUTE_TITLE -> { + if (chapter != null) chapter.title = value } - } else if (attribute == CHAPTER_ATTRIBUTE_LINK) { - if (chapter != null) { - chapter.link = value + CHAPTER_ATTRIBUTE_LINK -> { + if (chapter != null) chapter.link = value } } } diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentHeader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentHeader.kt index 3acb22a9..b16d157b 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentHeader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentHeader.kt @@ -2,7 +2,6 @@ package ac.mdiq.podcini.parser.media.vorbis internal class VorbisCommentHeader(val vendorString: String, val userCommentLength: Long) { override fun toString(): String { - return ("VorbisCommentHeader [vendorString=" + vendorString - + ", userCommentLength=" + userCommentLength + "]") + return ("VorbisCommentHeader [vendorString=" + vendorString + ", userCommentLength=" + userCommentLength + "]") } } diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentMetadataReader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentMetadataReader.kt index 5125792a..69398d4c 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentMetadataReader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentMetadataReader.kt @@ -12,7 +12,7 @@ class VorbisCommentMetadataReader(input: InputStream?) : VorbisCommentReader(inp public override fun onContentVectorValue(key: String?, value: String?) { if (KEY_DESCRIPTION == key || KEY_COMMENT == key) { - if (description == null || value!!.length > description!!.length) { + if (description == null || (value != null && value.length > description!!.length)) { description = value } } diff --git a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentReader.kt b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentReader.kt index 3a1b9df6..23ef5d2e 100644 --- a/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentReader.kt +++ b/parser/media/src/main/java/ac/mdiq/podcini/parser/media/vorbis/VorbisCommentReader.kt @@ -1,7 +1,6 @@ package ac.mdiq.podcini.parser.media.vorbis import android.util.Log -import ac.mdiq.podcini.parser.media.vorbis.VorbisCommentReaderException import org.apache.commons.io.EndianUtils import org.apache.commons.io.IOUtils import java.io.IOException @@ -136,7 +135,7 @@ abstract class VorbisCommentReader internal constructor(private val input: Input while (posInHaystack < 0) { posInHaystack += haystack.size } - posInHaystack = posInHaystack % haystack.size + posInHaystack %= haystack.size if (haystack[posInHaystack] != needle[needle.size - 1 - i]) { return false } diff --git a/storage/database/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt b/storage/database/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt index 7e25da8e..f9f96e8f 100644 --- a/storage/database/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt +++ b/storage/database/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt @@ -217,8 +217,8 @@ class PodDBAdapter private constructor() { db.beginTransactionNonExclusive() for (feed in feeds) { setFeed(feed) - if (feed.items != null) { - for (item in feed.items!!) { + if (feed.items.isNotEmpty()) { + for (item in feed.items) { updateOrInsertFeedItem(item, false) } } @@ -546,8 +546,8 @@ class PodDBAdapter private constructor() { fun removeFeed(feed: Feed) { try { db.beginTransactionNonExclusive() - if (feed.items != null) { - removeFeedItems(feed.items!!) + if (feed.items.isNotEmpty()) { + removeFeedItems(feed.items) } // delete download log entries for feed db.delete(TABLE_NAME_DOWNLOAD_LOG, "$KEY_FEEDFILE=? AND $KEY_FEEDFILETYPE=?", @@ -1427,11 +1427,11 @@ class PodDBAdapter private constructor() { @JvmStatic @Synchronized - fun getInstance(): PodDBAdapter? { + fun getInstance(): PodDBAdapter { if (instance == null) { instance = PodDBAdapter() } - return instance + return instance!! } /** @@ -1449,14 +1449,14 @@ class PodDBAdapter private constructor() { @JvmStatic @VisibleForTesting(otherwise = VisibleForTesting.NONE) fun tearDownTests() { - getInstance()!!.dbHelper.close() + getInstance().dbHelper.close() instance = null } @JvmStatic fun deleteDatabase(): Boolean { val adapter = getInstance() - adapter!!.open() + adapter.open() try { for (tableName in ALL_TABLES) { adapter.db.delete(tableName, "1", null) diff --git a/storage/preferences/src/main/java/ac/mdiq/podcini/storage/preferences/UserPreferences.kt b/storage/preferences/src/main/java/ac/mdiq/podcini/storage/preferences/UserPreferences.kt index a6ec98aa..bdc4d070 100644 --- a/storage/preferences/src/main/java/ac/mdiq/podcini/storage/preferences/UserPreferences.kt +++ b/storage/preferences/src/main/java/ac/mdiq/podcini/storage/preferences/UserPreferences.kt @@ -172,7 +172,7 @@ object UserPreferences { var hiddenDrawerItems: List? get() { val hiddenItems = prefs!!.getString(PREF_HIDDEN_DRAWER_ITEMS, "") - return ArrayList(Arrays.asList(*TextUtils.split(hiddenItems, ","))) + return ArrayList(listOf(*TextUtils.split(hiddenItems, ","))) } set(items) { val str = TextUtils.join(",", items!!) @@ -186,7 +186,7 @@ object UserPreferences { get() { val buttons = TextUtils.split( prefs!!.getString(PREF_FULL_NOTIFICATION_BUTTONS, - NOTIFICATION_BUTTON_SKIP.toString() + "," + NOTIFICATION_BUTTON_PLAYBACK_SPEED), ",") + "$NOTIFICATION_BUTTON_SKIP,$NOTIFICATION_BUTTON_PLAYBACK_SPEED"), ",") val notificationButtons: MutableList = ArrayList() for (button in buttons) {