From d5b5734712d962dc9f881875deeda9e2e42fe43b Mon Sep 17 00:00:00 2001
From: Xilin Jia <6257601+XilinJia@users.noreply.github.com>
Date: Wed, 20 Mar 2024 13:59:05 +0000
Subject: [PATCH] notes share and faster episode open
---
app/build.gradle | 10 +-
.../ui/activity/VideoplayerActivity.kt | 255 +++++++++---------
.../ui/adapter/EpisodeItemListAdapter.kt | 3 +-
.../ui/adapter/HorizontalItemListAdapter.kt | 3 +-
.../ui/adapter/QueueRecyclerAdapter.kt | 6 +-
.../podcini/ui/fragment/FeedInfoFragment.kt | 39 ++-
.../ui/fragment/FeedItemlistFragment.kt | 129 +++++----
.../ui/fragment/ItemDescriptionFragment.kt | 1 -
.../mdiq/podcini/ui/fragment/ItemFragment.kt | 44 +--
.../podcini/ui/fragment/ItemPageFragment.kt | 177 ++++++++++++
.../podcini/ui/fragment/ItemPagerFragment.kt | 41 ++-
.../ui/fragment/swipeactions/SwipeActions.kt | 8 +-
.../ui/menuhandler/FeedItemMenuHandler.kt | 33 ++-
.../res/layout/feeditem_page_fragment.xml | 27 ++
.../main/res/layout/feeditemlist_header.xml | 13 -
app/src/main/res/menu/feeditem_options.xml | 6 +-
app/src/main/res/values/strings.xml | 3 +-
changelog.md | 10 +-
.../android/en-US/changelogs/3020110.txt | 8 +
19 files changed, 530 insertions(+), 286 deletions(-)
create mode 100644 app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPageFragment.kt
create mode 100644 app/src/main/res/layout/feeditem_page_fragment.xml
create mode 100644 fastlane/metadata/android/en-US/changelogs/3020110.txt
diff --git a/app/build.gradle b/app/build.gradle
index 4d55a4a7..e833e22e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -149,8 +149,8 @@ android {
// Version code schema (not used):
// "1.2.3-beta4" -> 1020304
// "1.2.3" -> 1020395
- versionCode 3020109
- versionName "4.2.6"
+ versionCode 3020110
+ versionName "4.2.7"
def commit = ""
try {
@@ -168,10 +168,9 @@ android {
buildConfigField "String", "PODCASTINDEX_API_KEY", '"' + podcastindexApiKey + '"'
buildConfigField "String", "PODCASTINDEX_API_SECRET", '"' + podcastindexApiSecret + '"'
} else {
- buildConfigField "String", "PODCASTINDEX_API_KEY", '"XTMMQGA2YZ4WJUBYY4HK"'
- buildConfigField "String", "PODCASTINDEX_API_SECRET", '"XAaAhk4^2YBsTE33vdbwbZNj82ZRLABDDqFdKe7x"'
+ buildConfigField "String", "PODCASTINDEX_API_KEY", '"QT2RYHSUZ3UC9GDJ5MFY"'
+ buildConfigField "String", "PODCASTINDEX_API_SECRET", '"Zw2NL74ht5aCtx5zFL$#MY$##qdVCX7x37jq95Sz"'
}
-
}
signingConfigs {
releaseConfig {
@@ -295,7 +294,6 @@ dependencies {
testImplementation "org.robolectric:robolectric:4.11.1"
testImplementation 'javax.inject:javax.inject:1'
-
playImplementation 'com.google.android.gms:play-services-base:18.3.0'
freeImplementation 'org.conscrypt:conscrypt-android:2.5.2'
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt b/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
index b6526351..ea9b382a 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt
@@ -64,7 +64,7 @@ import org.greenrobot.eventbus.ThreadMode
@UnstableApi
class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
- private lateinit var viewBinding: VideoplayerActivityBinding
+ private lateinit var binding: VideoplayerActivityBinding
/**
* True if video controls are currently visible.
@@ -89,14 +89,17 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
setTheme(R.style.Theme_Podcini_VideoPlayer)
super.onCreate(savedInstanceState)
- Log.d(TAG, "onCreate()")
-
window.setFormat(PixelFormat.TRANSPARENT)
- viewBinding = VideoplayerActivityBinding.inflate(LayoutInflater.from(this))
- setContentView(viewBinding.root)
+ binding = VideoplayerActivityBinding.inflate(LayoutInflater.from(this))
+ setContentView(binding.root)
setupView()
supportActionBar?.setBackgroundDrawable(ColorDrawable(-0x80000000))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
+
+ controller = newPlaybackController()
+ controller!!.init()
+ loadMediaInfo()
+// EventBus.getDefault().register(this)
}
@UnstableApi
@@ -105,7 +108,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
switchToAudioOnly = false
if (isCasting) {
val intent = getPlayerActivityIntent(this)
- if (intent.component!!.className != VideoplayerActivity::class.java.name) {
+ if (intent.component?.className != VideoplayerActivity::class.java.name) {
destroyingDueToReload = true
finish()
startActivity(intent)
@@ -113,19 +116,28 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
}
- @UnstableApi
- override fun onStop() {
+ override fun onDestroy() {
+ super.onDestroy()
controller?.release()
controller = null // prevent leak
disposable?.dispose()
+// EventBus.getDefault().unregister(this)
+ }
+
+ @UnstableApi
+ override fun onStop() {
+// controller?.release()
+// controller = null // prevent leak
+// disposable?.dispose()
+
EventBus.getDefault().unregister(this)
super.onStop()
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
videoControlsHider.removeCallbacks(hideVideoControls)
}
// Controller released; we will not receive buffering updates
- viewBinding.progressBar.visibility = View.GONE
+ binding.progressBar.visibility = View.GONE
}
public override fun onUserLeaveHint() {
@@ -137,9 +149,6 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
override fun onStart() {
super.onStart()
- controller = newPlaybackController()
- controller!!.init()
- loadMediaInfo()
onPositionObserverUpdate()
EventBus.getDefault().register(this)
}
@@ -147,7 +156,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
override fun onPause() {
if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
- if (controller != null && controller!!.status == PlayerStatus.PLAYING) {
+ if (controller?.status == PlayerStatus.PLAYING) {
controller!!.pause()
}
}
@@ -168,7 +177,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun newPlaybackController(): PlaybackController {
return object : PlaybackController(this@VideoplayerActivity) {
override fun updatePlayButtonShowsPlay(showPlay: Boolean) {
- viewBinding.playButton.setIsShowPlay(showPlay)
+ binding.playButton.setIsShowPlay(showPlay)
if (showPlay) {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
@@ -176,7 +185,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
setupVideoAspectRatio()
if (videoSurfaceCreated && controller != null) {
Log.d(TAG, "Videosurface already created, setting videosurface now")
- controller!!.setVideoSurface(viewBinding.videoView.holder)
+ controller!!.setVideoSurface(binding.videoView.holder)
}
}
}
@@ -195,11 +204,11 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@Suppress("unused")
fun bufferUpdate(event: BufferUpdateEvent) {
if (event.hasStarted()) {
- viewBinding.progressBar.visibility = View.VISIBLE
+ binding.progressBar.visibility = View.VISIBLE
} else if (event.hasEnded()) {
- viewBinding.progressBar.visibility = View.INVISIBLE
+ binding.progressBar.visibility = View.INVISIBLE
} else {
- viewBinding.sbPosition.secondaryProgress = (event.progress * viewBinding.sbPosition.max).toInt()
+ binding.sbPosition.secondaryProgress = (event.progress * binding.sbPosition.max).toInt()
}
}
@@ -214,9 +223,8 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
private fun loadMediaInfo() {
Log.d(TAG, "loadMediaInfo()")
- if (controller?.getMedia() == null) {
- return
- }
+ if (controller?.getMedia() == null) return
+
if (controller!!.status == PlayerStatus.PLAYING && !controller!!.isPlayingVideoLocally) {
Log.d(TAG, "Closing, no longer video")
destroyingDueToReload = true
@@ -238,7 +246,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun setupView() {
showTimeLeft = shouldShowRemainingTime()
Log.d("timeleft", if (showTimeLeft) "true" else "false")
- viewBinding.durationLabel.setOnClickListener {
+ binding.durationLabel.setOnClickListener {
showTimeLeft = !showTimeLeft
val media = controller?.getMedia() ?: return@setOnClickListener
@@ -251,41 +259,41 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
val duration = converter.convert(media.getDuration())
length = getDurationStringLong(duration)
}
- viewBinding.durationLabel.text = length
+ binding.durationLabel.text = length
setShowRemainTimeSetting(showTimeLeft)
Log.d("timeleft on click", if (showTimeLeft) "true" else "false")
}
- viewBinding.sbPosition.setOnSeekBarChangeListener(this)
- viewBinding.rewindButton.setOnClickListener { onRewind() }
- viewBinding.rewindButton.setOnLongClickListener {
+ binding.sbPosition.setOnSeekBarChangeListener(this)
+ binding.rewindButton.setOnClickListener { onRewind() }
+ binding.rewindButton.setOnLongClickListener {
SkipPreferenceDialog.showSkipPreference(this@VideoplayerActivity,
SkipPreferenceDialog.SkipDirection.SKIP_REWIND, null)
true
}
- viewBinding.playButton.setIsVideoScreen(true)
- viewBinding.playButton.setOnClickListener { onPlayPause() }
- viewBinding.fastForwardButton.setOnClickListener { onFastForward() }
- viewBinding.fastForwardButton.setOnLongClickListener {
+ binding.playButton.setIsVideoScreen(true)
+ binding.playButton.setOnClickListener { onPlayPause() }
+ binding.fastForwardButton.setOnClickListener { onFastForward() }
+ binding.fastForwardButton.setOnLongClickListener {
SkipPreferenceDialog.showSkipPreference(this@VideoplayerActivity,
SkipPreferenceDialog.SkipDirection.SKIP_FORWARD, null)
false
}
// To suppress touches directly below the slider
- viewBinding.bottomControlsContainer.setOnTouchListener { _: View?, _: MotionEvent? -> true }
- viewBinding.bottomControlsContainer.fitsSystemWindows = true
- viewBinding.videoView.holder.addCallback(surfaceHolderCallback)
- viewBinding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ binding.bottomControlsContainer.setOnTouchListener { _: View?, _: MotionEvent? -> true }
+ binding.bottomControlsContainer.fitsSystemWindows = true
+ binding.videoView.holder.addCallback(surfaceHolderCallback)
+ binding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
setupVideoControlsToggler()
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN)
- viewBinding.videoPlayerContainer.setOnTouchListener(onVideoviewTouched)
- viewBinding.videoPlayerContainer.viewTreeObserver.addOnGlobalLayoutListener {
- viewBinding.videoView.setAvailableSize(
- viewBinding.videoPlayerContainer.width.toFloat(), viewBinding.videoPlayerContainer.height.toFloat())
+ binding.videoPlayerContainer.setOnTouchListener(onVideoviewTouched)
+ binding.videoPlayerContainer.viewTreeObserver.addOnGlobalLayoutListener {
+ binding.videoView.setAvailableSize(
+ binding.videoPlayerContainer.width.toFloat(), binding.videoPlayerContainer.height.toFloat())
}
}
@@ -340,24 +348,24 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
skipAnimation.fillAfter = false
skipAnimation.duration = 800
- val params = viewBinding.skipAnimationImage.layoutParams as FrameLayout.LayoutParams
+ val params = binding.skipAnimationImage.layoutParams as FrameLayout.LayoutParams
if (isForward) {
- viewBinding.skipAnimationImage.setImageResource(R.drawable.ic_fast_forward_video_white)
+ binding.skipAnimationImage.setImageResource(R.drawable.ic_fast_forward_video_white)
params.gravity = Gravity.RIGHT or Gravity.CENTER_VERTICAL
} else {
- viewBinding.skipAnimationImage.setImageResource(R.drawable.ic_fast_rewind_video_white)
+ binding.skipAnimationImage.setImageResource(R.drawable.ic_fast_rewind_video_white)
params.gravity = Gravity.LEFT or Gravity.CENTER_VERTICAL
}
- viewBinding.skipAnimationImage.visibility = View.VISIBLE
- viewBinding.skipAnimationImage.layoutParams = params
- viewBinding.skipAnimationImage.startAnimation(skipAnimation)
+ binding.skipAnimationImage.visibility = View.VISIBLE
+ binding.skipAnimationImage.layoutParams = params
+ binding.skipAnimationImage.startAnimation(skipAnimation)
skipAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
- viewBinding.skipAnimationImage.visibility = View.GONE
+ binding.skipAnimationImage.visibility = View.GONE
}
override fun onAnimationRepeat(animation: Animation) {
@@ -376,7 +384,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
val videoSize = controller!!.videoSize
if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second)
- viewBinding.videoView.setVideoSize(videoSize.first, videoSize.second)
+ binding.videoView.setVideoSize(videoSize.first, videoSize.second)
} else {
Log.e(TAG, "Could not determine video size")
}
@@ -396,9 +404,8 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
fun onRewind() {
- if (controller == null) {
- return
- }
+ if (controller == null) return
+
val curr = controller!!.position
controller!!.seekTo(curr - rewindSecs * 1000)
setupVideoControlsToggler()
@@ -406,18 +413,16 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
fun onPlayPause() {
- if (controller == null) {
- return
- }
+ if (controller == null) return
+
controller!!.playPause()
setupVideoControlsToggler()
}
@UnstableApi
fun onFastForward() {
- if (controller == null) {
- return
- }
+ if (controller == null) return
+
val curr = controller!!.position
controller!!.seekTo(curr + fastForwardSecs * 1000)
setupVideoControlsToggler()
@@ -448,31 +453,31 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
private fun showVideoControls() {
- viewBinding.bottomControlsContainer.visibility = View.VISIBLE
- viewBinding.controlsContainer.visibility = View.VISIBLE
+ binding.bottomControlsContainer.visibility = View.VISIBLE
+ binding.controlsContainer.visibility = View.VISIBLE
val animation = AnimationUtils.loadAnimation(this, R.anim.fade_in)
if (animation != null) {
- viewBinding.bottomControlsContainer.startAnimation(animation)
- viewBinding.controlsContainer.startAnimation(animation)
+ binding.bottomControlsContainer.startAnimation(animation)
+ binding.controlsContainer.startAnimation(animation)
}
- viewBinding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
+ binding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
}
private fun hideVideoControls(showAnimation: Boolean) {
if (showAnimation) {
val animation = AnimationUtils.loadAnimation(this, R.anim.fade_out)
if (animation != null) {
- viewBinding.bottomControlsContainer.startAnimation(animation)
- viewBinding.controlsContainer.startAnimation(animation)
+ binding.bottomControlsContainer.startAnimation(animation)
+ binding.controlsContainer.startAnimation(animation)
}
}
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
- viewBinding.bottomControlsContainer.fitsSystemWindows = true
+ binding.bottomControlsContainer.fitsSystemWindows = true
- viewBinding.bottomControlsContainer.visibility = View.GONE
- viewBinding.controlsContainer.visibility = View.GONE
+ binding.bottomControlsContainer.visibility = View.GONE
+ binding.controlsContainer.visibility = View.GONE
}
@Subscribe(threadMode = ThreadMode.MAIN)
@@ -515,9 +520,8 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
@UnstableApi
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
super.onPrepareOptionsMenu(menu)
- if (controller == null) {
- return false
- }
+ if (controller == null) return false
+
val media = controller!!.getMedia()
val isFeedMedia = (media is FeedMedia)
@@ -573,33 +577,42 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
else -> {
val media = controller?.getMedia() ?: return false
val feedItem = getFeedItem(media) // some options option requires FeedItem
- if (item.itemId == R.id.add_to_favorites_item && feedItem != null) {
- DBWriter.addFavoriteItem(feedItem)
- isFavorite = true
- invalidateOptionsMenu()
- } else if (item.itemId == R.id.remove_from_favorites_item && feedItem != null) {
- DBWriter.removeFavoriteItem(feedItem)
- isFavorite = false
- invalidateOptionsMenu()
- } else if (item.itemId == R.id.disable_sleeptimer_item
- || item.itemId == R.id.set_sleeptimer_item) {
- SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
- } else if (item.itemId == R.id.audio_controls) {
- val dialog = PlaybackControlsDialog.newInstance()
- dialog.show(supportFragmentManager, "playback_controls")
- } else if (item.itemId == R.id.open_feed_item && feedItem != null) {
- val intent = MainActivity.getIntentToOpenFeed(this, feedItem.feedId)
- startActivity(intent)
- } else if (item.itemId == R.id.visit_website_item) {
- val url = getWebsiteLinkWithFallback(media)
- if (url != null) openInBrowser(this@VideoplayerActivity, url)
- } else if (item.itemId == R.id.share_item && feedItem != null) {
- val shareDialog = ShareDialog.newInstance(feedItem)
- shareDialog.show(supportFragmentManager, "ShareEpisodeDialog")
- } else if (item.itemId == R.id.playback_speed) {
- VariableSpeedDialog().show(supportFragmentManager, null)
- } else {
- return false
+ when {
+ item.itemId == R.id.add_to_favorites_item && feedItem != null -> {
+ DBWriter.addFavoriteItem(feedItem)
+ isFavorite = true
+ invalidateOptionsMenu()
+ }
+ item.itemId == R.id.remove_from_favorites_item && feedItem != null -> {
+ DBWriter.removeFavoriteItem(feedItem)
+ isFavorite = false
+ invalidateOptionsMenu()
+ }
+ item.itemId == R.id.disable_sleeptimer_item || item.itemId == R.id.set_sleeptimer_item -> {
+ SleepTimerDialog().show(supportFragmentManager, "SleepTimerDialog")
+ }
+ item.itemId == R.id.audio_controls -> {
+ val dialog = PlaybackControlsDialog.newInstance()
+ dialog.show(supportFragmentManager, "playback_controls")
+ }
+ item.itemId == R.id.open_feed_item && feedItem != null -> {
+ val intent = MainActivity.getIntentToOpenFeed(this, feedItem.feedId)
+ startActivity(intent)
+ }
+ item.itemId == R.id.visit_website_item -> {
+ val url = getWebsiteLinkWithFallback(media)
+ if (url != null) openInBrowser(this@VideoplayerActivity, url)
+ }
+ item.itemId == R.id.share_item && feedItem != null -> {
+ val shareDialog = ShareDialog.newInstance(feedItem)
+ shareDialog.show(supportFragmentManager, "ShareEpisodeDialog")
+ }
+ item.itemId == R.id.playback_speed -> {
+ VariableSpeedDialog().show(supportFragmentManager, null)
+ }
+ else -> {
+ return false
+ }
}
return true
}
@@ -607,9 +620,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
}
fun onPositionObserverUpdate() {
- if (controller == null) {
- return
- }
+ if (controller == null) return
val converter = TimeSpeedConverter(controller!!.currentPlaybackSpeedMultiplier)
val currentPosition = converter.convert(controller!!.position)
@@ -617,16 +628,15 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
val remainingTime = converter.convert(
controller!!.duration - controller!!.position)
// Log.d(TAG, "currentPosition " + Converter.getDurationStringLong(currentPosition));
- if (currentPosition == Playable.INVALID_TIME
- || duration == Playable.INVALID_TIME) {
+ if (currentPosition == Playable.INVALID_TIME || duration == Playable.INVALID_TIME) {
Log.w(TAG, "Could not react to position observer update because of invalid time")
return
}
- viewBinding.positionLabel.text = getDurationStringLong(currentPosition)
+ binding.positionLabel.text = getDurationStringLong(currentPosition)
if (showTimeLeft) {
- viewBinding.durationLabel.text = "-" + getDurationStringLong(remainingTime)
+ binding.durationLabel.text = "-" + getDurationStringLong(remainingTime)
} else {
- viewBinding.durationLabel.text = getDurationStringLong(duration)
+ binding.durationLabel.text = getDurationStringLong(duration)
}
updateProgressbarPosition(currentPosition, duration)
}
@@ -634,25 +644,24 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private fun updateProgressbarPosition(position: Int, duration: Int) {
Log.d(TAG, "updateProgressbarPosition($position, $duration)")
val progress = (position.toFloat()) / duration
- viewBinding.sbPosition.progress = (progress * viewBinding.sbPosition.max).toInt()
+ binding.sbPosition.progress = (progress * binding.sbPosition.max).toInt()
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- if (controller == null) {
- return
- }
+ if (controller == null) return
+
if (fromUser) {
prog = progress / (seekBar.max.toFloat())
val converter = TimeSpeedConverter(controller!!.currentPlaybackSpeedMultiplier)
val position = converter.convert((prog * controller!!.duration).toInt())
- viewBinding.seekPositionLabel.text = getDurationStringLong(position)
+ binding.seekPositionLabel.text = getDurationStringLong(position)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
- viewBinding.seekCardView.scaleX = .8f
- viewBinding.seekCardView.scaleY = .8f
- viewBinding.seekCardView.animate()
+ binding.seekCardView.scaleX = .8f
+ binding.seekCardView.scaleY = .8f
+ binding.seekCardView.animate()
.setInterpolator(FastOutSlowInInterpolator())
.alpha(1f).scaleX(1f).scaleY(1f)
.setDuration(200)
@@ -664,9 +673,9 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
if (controller != null) {
controller!!.seekTo((prog * controller!!.duration).toInt())
}
- viewBinding.seekCardView.scaleX = 1f
- viewBinding.seekCardView.scaleY = 1f
- viewBinding.seekCardView.animate()
+ binding.seekCardView.scaleX = 1f
+ binding.seekCardView.scaleY = 1f
+ binding.seekCardView.animate()
.setInterpolator(FastOutSlowInInterpolator())
.alpha(0f).scaleX(.8f).scaleY(.8f)
.setDuration(200)
@@ -763,14 +772,18 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
private const val TAG = "VideoplayerActivity"
private fun getWebsiteLinkWithFallback(media: Playable?): String? {
- if (media == null) {
- return null
- } else if (!media.getWebsiteLink().isNullOrBlank()) {
- return media.getWebsiteLink()
- } else if (media is FeedMedia) {
- return getLinkWithFallback(media.getItem())
+ when {
+ media == null -> {
+ return null
+ }
+ !media.getWebsiteLink().isNullOrBlank() -> {
+ return media.getWebsiteLink()
+ }
+ media is FeedMedia -> {
+ return getLinkWithFallback(media.getItem())
+ }
+ else -> return null
}
- return null
}
private fun getFeedItem(playable: Playable?): FeedItem? {
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/adapter/EpisodeItemListAdapter.kt b/app/src/main/java/ac/mdiq/podcini/ui/adapter/EpisodeItemListAdapter.kt
index 6136d816..0849996e 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/adapter/EpisodeItemListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/adapter/EpisodeItemListAdapter.kt
@@ -7,6 +7,7 @@ import ac.mdiq.podcini.ui.fragment.ItemPagerFragment
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
import ac.mdiq.podcini.storage.model.feed.FeedItem
import ac.mdiq.podcini.ui.common.ThemeUtils
+import ac.mdiq.podcini.ui.fragment.ItemPageFragment
import ac.mdiq.podcini.ui.view.viewholder.EpisodeItemViewHolder
import android.R.color
import android.app.Activity
@@ -83,7 +84,7 @@ open class EpisodeItemListAdapter(mainActivity: MainActivity) :
if (!inActionMode()) {
val ids: LongArray = FeedItemUtil.getIds(episodes)
val position = ArrayUtils.indexOf(ids, item.id)
- activity?.loadChildFragment(ItemPagerFragment.newInstance(ids, position))
+ activity?.loadChildFragment(ItemPageFragment.newInstance(ids, position))
} else {
toggleSelection(holder.bindingAdapterPosition)
}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/adapter/HorizontalItemListAdapter.kt b/app/src/main/java/ac/mdiq/podcini/ui/adapter/HorizontalItemListAdapter.kt
index 183c80d8..d534aacb 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/adapter/HorizontalItemListAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/adapter/HorizontalItemListAdapter.kt
@@ -12,6 +12,7 @@ import ac.mdiq.podcini.util.FeedItemUtil
import ac.mdiq.podcini.ui.fragment.ItemPagerFragment
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
import ac.mdiq.podcini.storage.model.feed.FeedItem
+import ac.mdiq.podcini.ui.fragment.ItemPageFragment
import ac.mdiq.podcini.ui.view.viewholder.HorizontalItemViewHolder
import org.apache.commons.lang3.ArrayUtils
import java.lang.ref.WeakReference
@@ -65,7 +66,7 @@ open class HorizontalItemListAdapter(mainActivity: MainActivity) : RecyclerView.
if (activity != null) {
val ids: LongArray = FeedItemUtil.getIds(data)
val clickPosition = ArrayUtils.indexOf(ids, item.id)
- activity.loadChildFragment(ItemPagerFragment.newInstance(ids, clickPosition))
+ activity.loadChildFragment(ItemPageFragment.newInstance(ids, clickPosition))
}
}
}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/adapter/QueueRecyclerAdapter.kt b/app/src/main/java/ac/mdiq/podcini/ui/adapter/QueueRecyclerAdapter.kt
index c99c5852..eb473a7d 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/adapter/QueueRecyclerAdapter.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/adapter/QueueRecyclerAdapter.kt
@@ -30,7 +30,7 @@ open class QueueRecyclerAdapter(mainActivity: MainActivity, private val swipeAct
@UnstableApi @SuppressLint("ClickableViewAccessibility")
override fun afterBindViewHolder(holder: EpisodeItemViewHolder, pos: Int) {
- if (!dragDropEnabled) {
+ if (inActionMode() || !dragDropEnabled) {
holder.dragHandle.setVisibility(View.GONE)
holder.dragHandle.setOnTouchListener(null)
// holder.coverHolder.setOnTouchListener(null)
@@ -38,17 +38,15 @@ open class QueueRecyclerAdapter(mainActivity: MainActivity, private val swipeAct
holder.dragHandle.setVisibility(View.VISIBLE)
holder.dragHandle.setOnTouchListener { _: View?, event: MotionEvent ->
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
- Log.d(TAG, "startDrag()")
swipeActions.startDrag(holder)
}
false
}
holder.coverHolder.setOnTouchListener { v1, event ->
- if (event.actionMasked == MotionEvent.ACTION_DOWN) {
+ if (!inActionMode() && event.actionMasked == MotionEvent.ACTION_DOWN) {
val isLtr = holder.itemView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
val factor = (if (isLtr) 1 else -1).toFloat()
if (factor * event.x < factor * 0.5 * v1.width) {
- Log.d(TAG, "startDrag()")
swipeActions.startDrag(holder)
} else {
Log.d(TAG, "Ignoring drag in right half of the image")
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
index 5871a084..5541ce6d 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedInfoFragment.kt
@@ -90,19 +90,18 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
- val viewBinding = FeedinfoBinding.inflate(inflater)
-// val root: View = inflater.inflate(R.layout.feedinfo, null)
+ val binding = FeedinfoBinding.inflate(inflater)
Log.d(TAG, "fragment onCreateView")
- toolbar = viewBinding.toolbar
+ toolbar = binding.toolbar
toolbar.title = ""
toolbar.inflateMenu(R.menu.feedinfo)
toolbar.setNavigationOnClickListener { parentFragmentManager.popBackStack() }
toolbar.setOnMenuItemClickListener(this)
refreshToolbarState()
- val appBar: AppBarLayout = viewBinding.appBar
- val collapsingToolbar: CollapsingToolbarLayout = viewBinding.collapsingToolbar
+ val appBar: AppBarLayout = binding.appBar
+ val collapsingToolbar: CollapsingToolbarLayout = binding.collapsingToolbar
val iconTintManager: ToolbarIconTintManager =
object : ToolbarIconTintManager(requireContext(), toolbar, collapsingToolbar) {
override fun doTint(themedContext: Context) {
@@ -115,22 +114,22 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
iconTintManager.updateTint()
appBar.addOnOffsetChangedListener(iconTintManager)
- imgvCover = viewBinding.header.imgvCover
- txtvTitle = viewBinding.header.txtvTitle
- txtvAuthorHeader = viewBinding.header.txtvAuthor
- imgvBackground = viewBinding.imgvBackground
- header = viewBinding.header.root
- infoContainer = viewBinding.infoContainer
-// viewBinding.header.butShowInfo.visibility = View.INVISIBLE
- viewBinding.header.butShowSettings.visibility = View.INVISIBLE
- viewBinding.header.butFilter.visibility = View.INVISIBLE
+ imgvCover = binding.header.imgvCover
+ txtvTitle = binding.header.txtvTitle
+ txtvAuthorHeader = binding.header.txtvAuthor
+ imgvBackground = binding.imgvBackground
+ header = binding.header.root
+ infoContainer = binding.infoContainer
+// binding.header.butShowInfo.visibility = View.INVISIBLE
+ binding.header.butShowSettings.visibility = View.INVISIBLE
+ binding.header.butFilter.visibility = View.INVISIBLE
// https://github.com/bumptech/glide/issues/529
imgvBackground.colorFilter = LightingColorFilter(-0x7d7d7e, 0x000000)
- txtvDescription = viewBinding.txtvDescription
- txtvUrl = viewBinding.txtvUrl
- lblSupport = viewBinding.lblSupport
- txtvFundingUrl = viewBinding.txtvFundingUrl
+ txtvDescription = binding.txtvDescription
+ txtvUrl = binding.txtvUrl
+ lblSupport = binding.lblSupport
+ txtvFundingUrl = binding.txtvFundingUrl
txtvUrl.setOnClickListener(copyUrlToClipboard)
@@ -139,12 +138,12 @@ class FeedInfoFragment : Fragment(), Toolbar.OnMenuItemClickListener {
FeedStatisticsFragment.newInstance(feedId, false), "feed_statistics_fragment")
.commitAllowingStateLoss()
- viewBinding.btnvOpenStatistics.setOnClickListener {
+ binding.btnvOpenStatistics.setOnClickListener {
val fragment = StatisticsFragment()
(activity as MainActivity).loadChildFragment(fragment, TransitionEffect.SLIDE)
}
- return viewBinding.root
+ return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedItemlistFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedItemlistFragment.kt
index 6a5ab024..430cf898 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedItemlistFragment.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedItemlistFragment.kt
@@ -63,7 +63,6 @@ import org.greenrobot.eventbus.ThreadMode
import java.util.concurrent.Callable
import java.util.concurrent.ExecutionException
-
/**
* Displays a list of FeedItems.
*/
@@ -72,7 +71,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
private lateinit var adapter: FeedItemListAdapter
private lateinit var swipeActions: SwipeActions
- private lateinit var viewBinding: FeedItemListFragmentBinding
+ private lateinit var binding: FeedItemListFragmentBinding
private lateinit var speedDialBinding: MultiSelectSpeedDialBinding
private lateinit var nextPageLoader: MoreContentListFooterUtil
@@ -94,43 +93,44 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
): View {
Log.d(TAG, "fragment onCreateView")
- viewBinding = FeedItemListFragmentBinding.inflate(inflater)
- speedDialBinding = MultiSelectSpeedDialBinding.bind(viewBinding.root)
- viewBinding.toolbar.inflateMenu(R.menu.feedlist)
- viewBinding.toolbar.setOnMenuItemClickListener(this)
- viewBinding.toolbar.setOnLongClickListener {
- viewBinding.recyclerView.scrollToPosition(5)
- viewBinding.recyclerView.post { viewBinding.recyclerView.smoothScrollToPosition(0) }
- viewBinding.appBar.setExpanded(true)
+ binding = FeedItemListFragmentBinding.inflate(inflater)
+ speedDialBinding = MultiSelectSpeedDialBinding.bind(binding.root)
+
+ binding.toolbar.inflateMenu(R.menu.feedlist)
+ binding.toolbar.setOnMenuItemClickListener(this)
+ binding.toolbar.setOnLongClickListener {
+ binding.recyclerView.scrollToPosition(5)
+ binding.recyclerView.post { binding.recyclerView.smoothScrollToPosition(0) }
+ binding.appBar.setExpanded(true)
false
}
displayUpArrow = parentFragmentManager.backStackEntryCount != 0
if (savedInstanceState != null) {
displayUpArrow = savedInstanceState.getBoolean(KEY_UP_ARROW)
}
- (activity as MainActivity).setupToolbarToggle(viewBinding.toolbar, displayUpArrow)
+ (activity as MainActivity).setupToolbarToggle(binding.toolbar, displayUpArrow)
updateToolbar()
- viewBinding.recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
+ binding.recyclerView.setRecycledViewPool((activity as MainActivity).recycledViewPool)
adapter = FeedItemListAdapter(activity as MainActivity)
adapter.setOnSelectModeListener(this)
- viewBinding.recyclerView.adapter = adapter
- swipeActions = SwipeActions(this, TAG).attachTo(viewBinding.recyclerView)
- viewBinding.progressBar.visibility = View.VISIBLE
+ binding.recyclerView.adapter = adapter
+ swipeActions = SwipeActions(this, TAG).attachTo(binding.recyclerView)
+ binding.progressBar.visibility = View.VISIBLE
val iconTintManager: ToolbarIconTintManager = object : ToolbarIconTintManager(
- requireContext(), viewBinding.toolbar, viewBinding.collapsingToolbar) {
+ requireContext(), binding.toolbar, binding.collapsingToolbar) {
override fun doTint(themedContext: Context) {
- viewBinding.toolbar.menu.findItem(R.id.refresh_item)
+ binding.toolbar.menu.findItem(R.id.refresh_item)
.setIcon(AppCompatResources.getDrawable(themedContext, R.drawable.ic_refresh))
- viewBinding.toolbar.menu.findItem(R.id.action_search)
+ binding.toolbar.menu.findItem(R.id.action_search)
.setIcon(AppCompatResources.getDrawable(themedContext, R.drawable.ic_search))
}
}
iconTintManager.updateTint()
- viewBinding.appBar.addOnOffsetChangedListener(iconTintManager)
+ binding.appBar.addOnOffsetChangedListener(iconTintManager)
- nextPageLoader = MoreContentListFooterUtil(viewBinding.moreContent.moreContentListFooter)
+ nextPageLoader = MoreContentListFooterUtil(binding.moreContent.moreContentListFooter)
nextPageLoader.setClickListener(object : MoreContentListFooterUtil.Listener {
override fun onClick() {
if (feed != null) {
@@ -138,22 +138,22 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
}
}
})
- viewBinding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(view: RecyclerView, deltaX: Int, deltaY: Int) {
super.onScrolled(view, deltaX, deltaY)
val hasMorePages = feed != null && feed!!.isPaged && feed!!.nextPageLink != null
- val pageLoaderVisible = viewBinding.recyclerView.isScrolledToBottom && hasMorePages
+ val pageLoaderVisible = binding.recyclerView.isScrolledToBottom && hasMorePages
nextPageLoader.root.visibility = if (pageLoaderVisible) View.VISIBLE else View.GONE
- viewBinding.recyclerView.setPadding(
- viewBinding.recyclerView.paddingLeft, 0, viewBinding.recyclerView.paddingRight,
+ binding.recyclerView.setPadding(
+ binding.recyclerView.paddingLeft, 0, binding.recyclerView.paddingRight,
if (pageLoaderVisible) nextPageLoader.root.measuredHeight else 0)
}
})
EventBus.getDefault().register(this)
- viewBinding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
- viewBinding.swipeRefresh.setOnRefreshListener {
+ binding.swipeRefresh.setDistanceToTriggerSync(resources.getInteger(R.integer.swipe_refresh_distance))
+ binding.swipeRefresh.setOnRefreshListener {
FeedUpdateManager.runOnceOrAsk(requireContext(), feed)
}
@@ -181,7 +181,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
adapter.endSelectMode()
true
}
- return viewBinding.root
+ return binding.root
}
override fun onDestroyView() {
@@ -201,22 +201,22 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (feed == null) {
return
}
- viewBinding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(feed!!.link != null)
- viewBinding.toolbar.menu.findItem(R.id.refresh_complete_item).setVisible(feed!!.isPaged)
+ binding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(feed!!.link != null)
+ binding.toolbar.menu.findItem(R.id.refresh_complete_item).setVisible(feed!!.isPaged)
if (StringUtils.isBlank(feed!!.link)) {
- viewBinding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(false)
+ binding.toolbar.menu.findItem(R.id.visit_website_item).setVisible(false)
}
if (feed!!.isLocalFeed) {
- viewBinding.toolbar.menu.findItem(R.id.share_item).setVisible(false)
+ binding.toolbar.menu.findItem(R.id.share_item).setVisible(false)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val horizontalSpacing = resources.getDimension(R.dimen.additional_horizontal_spacing).toInt()
- viewBinding.header.headerContainer.setPadding(
- horizontalSpacing, viewBinding.header.headerContainer.paddingTop,
- horizontalSpacing, viewBinding.header.headerContainer.paddingBottom)
+ binding.header.headerContainer.setPadding(
+ horizontalSpacing, binding.header.headerContainer.paddingTop,
+ horizontalSpacing, binding.header.headerContainer.paddingBottom)
}
@UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -288,7 +288,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
val activity: MainActivity = activity as MainActivity
if (feed != null) {
val ids: LongArray = FeedItemUtil.getIds(feed!!.items)
- activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position))
+ activity.loadChildFragment(ItemPageFragment.newInstance(ids, position))
}
}
@@ -339,7 +339,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
Log.d(TAG, "onEventMainThread() called with: event = [$event]")
for (i in 0 until adapter.itemCount) {
val holder: EpisodeItemViewHolder? =
- viewBinding.recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
+ binding.recyclerView.findViewHolderForAdapterPosition(i) as? EpisodeItemViewHolder
if (holder != null && holder.isCurrentlyPlayingItem) {
holder.notifyPlaybackPositionUpdated(event)
break
@@ -372,7 +372,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
override fun onEndSelectMode() {
speedDialBinding.fabSD.close()
speedDialBinding.fabSD.visibility = View.GONE
- swipeActions.attachTo(viewBinding.recyclerView)
+ swipeActions.attachTo(binding.recyclerView)
}
@UnstableApi private fun updateUi() {
@@ -405,7 +405,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (!event.isFeedUpdateRunning) {
nextPageLoader.root.visibility = View.GONE
}
- viewBinding.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
+ binding.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
}
@UnstableApi private fun refreshHeaderView() {
@@ -416,34 +416,34 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
}
loadFeedImage()
if (feed!!.hasLastUpdateFailed()) {
- viewBinding.header.txtvFailure.visibility = View.VISIBLE
+ binding.header.txtvFailure.visibility = View.VISIBLE
} else {
- viewBinding.header.txtvFailure.visibility = View.GONE
+ binding.header.txtvFailure.visibility = View.GONE
}
if (feed!!.preferences != null && !feed!!.preferences!!.keepUpdated) {
- viewBinding.header.txtvUpdatesDisabled.text = ("{md-pause-circle-outline} "
+ binding.header.txtvUpdatesDisabled.text = ("{md-pause-circle-outline} "
+ this.getString(R.string.updates_disabled_label))
- Iconify.addIcons(viewBinding.header.txtvUpdatesDisabled)
- viewBinding.header.txtvUpdatesDisabled.visibility = View.VISIBLE
+ Iconify.addIcons(binding.header.txtvUpdatesDisabled)
+ binding.header.txtvUpdatesDisabled.visibility = View.VISIBLE
} else {
- viewBinding.header.txtvUpdatesDisabled.visibility = View.GONE
+ binding.header.txtvUpdatesDisabled.visibility = View.GONE
}
- viewBinding.header.txtvTitle.text = feed!!.title
- viewBinding.header.txtvAuthor.text = feed!!.author
+ binding.header.txtvTitle.text = feed!!.title
+ binding.header.txtvAuthor.text = feed!!.author
if (feed != null && feed!!.itemFilter != null) {
val filter: FeedItemFilter? = feed!!.itemFilter
if (filter != null && filter.values.isNotEmpty()) {
- viewBinding.header.txtvInformation.text = ("{md-info-outline} " + this.getString(R.string.filtered_label))
- Iconify.addIcons(viewBinding.header.txtvInformation)
- viewBinding.header.txtvInformation.setOnClickListener {
+ binding.header.txtvInformation.text = ("{md-info-outline} " + this.getString(R.string.filtered_label))
+ Iconify.addIcons(binding.header.txtvInformation)
+ binding.header.txtvInformation.setOnClickListener {
FeedItemFilterDialog.newInstance(feed!!).show(childFragmentManager, null)
}
- viewBinding.header.txtvInformation.visibility = View.VISIBLE
+ binding.header.txtvInformation.visibility = View.VISIBLE
} else {
- viewBinding.header.txtvInformation.visibility = View.GONE
+ binding.header.txtvInformation.visibility = View.GONE
}
} else {
- viewBinding.header.txtvInformation.visibility = View.GONE
+ binding.header.txtvInformation.visibility = View.GONE
}
}
@@ -451,20 +451,19 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
if (feed == null || headerCreated) return
// https://github.com/bumptech/glide/issues/529
- viewBinding.imgvBackground.colorFilter = LightingColorFilter(-0x99999a, 0x000000)
-// viewBinding.header.butShowInfo.setOnClickListener { showFeedInfo() }
- viewBinding.header.imgvCover.setOnClickListener { showFeedInfo() }
- viewBinding.header.butShowSettings.setOnClickListener {
+ binding.imgvBackground.colorFilter = LightingColorFilter(-0x99999a, 0x000000)
+ binding.header.imgvCover.setOnClickListener { showFeedInfo() }
+ binding.header.butShowSettings.setOnClickListener {
if (feed != null) {
val fragment = FeedSettingsFragment.newInstance(feed!!)
(activity as MainActivity).loadChildFragment(fragment, TransitionEffect.SLIDE)
}
}
- viewBinding.header.butFilter.setOnClickListener {
+ binding.header.butFilter.setOnClickListener {
if (feed != null) FeedItemFilterDialog.newInstance(feed!!).show(childFragmentManager, null)
}
- viewBinding.header.txtvFailure.setOnClickListener { showErrorDetails() }
- viewBinding.header.counts.text = adapter.itemCount.toString()
+ binding.header.txtvFailure.setOnClickListener { showErrorDetails() }
+ binding.header.counts.text = adapter.itemCount.toString()
headerCreated = true
}
@@ -504,7 +503,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
.error(R.color.image_readability_tint)
.transform(FastBlurTransformation())
.dontAnimate())
- .into(viewBinding.imgvBackground)
+ .into(binding.imgvBackground)
Glide.with(this)
.load(feed!!.imageUrl)
@@ -513,7 +512,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
.error(R.color.light_gray)
.fitCenter()
.dontAnimate())
- .into(viewBinding.header.imgvCover)
+ .into(binding.header.imgvCover)
}
@UnstableApi private fun loadItems() {
@@ -528,10 +527,10 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
Log.d(TAG, "loadItems subscribe called ${feed?.title}")
swipeActions.setFilter(feed?.itemFilter)
refreshHeaderView()
- viewBinding.progressBar.visibility = View.GONE
+ binding.progressBar.visibility = View.GONE
adapter.setDummyViews(0)
if (feed != null) adapter.updateItems(feed!!.items)
- viewBinding.header.counts.text = (feed?.items?.size?:0).toString()
+ binding.header.counts.text = (feed?.items?.size?:0).toString()
updateToolbar()
}, { error: Throwable? ->
feed = null
@@ -563,8 +562,8 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
return
}
when (event.keyCode) {
- KeyEvent.KEYCODE_T -> viewBinding.recyclerView.smoothScrollToPosition(0)
- KeyEvent.KEYCODE_B -> viewBinding.recyclerView.smoothScrollToPosition(adapter.itemCount - 1)
+ KeyEvent.KEYCODE_T -> binding.recyclerView.smoothScrollToPosition(0)
+ KeyEvent.KEYCODE_B -> binding.recyclerView.smoothScrollToPosition(adapter.itemCount - 1)
else -> {}
}
}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemDescriptionFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemDescriptionFragment.kt
index 514a1f16..a3362364 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemDescriptionFragment.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemDescriptionFragment.kt
@@ -35,7 +35,6 @@ class ItemDescriptionFragment : Fragment() {
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
Log.d(TAG, "Creating view")
val binding = ItemDescriptionFragmentBinding.inflate(inflater)
-// val root = inflater.inflate(R.layout.item_description_fragment, container, false)
Log.d(TAG, "fragment onCreateView")
webvDescription = binding.webview
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemFragment.kt
index ead2cdd4..e5bfd60f 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemFragment.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemFragment.kt
@@ -16,6 +16,7 @@ import ac.mdiq.podcini.ui.adapter.actionbutton.*
import ac.mdiq.podcini.ui.common.CircularProgressBar
import ac.mdiq.podcini.ui.common.ThemeUtils
import ac.mdiq.podcini.ui.gui.ShownotesCleaner
+import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
import ac.mdiq.podcini.ui.view.ShownotesWebView
import ac.mdiq.podcini.util.Converter
import ac.mdiq.podcini.util.DateFormatter
@@ -25,6 +26,7 @@ import ac.mdiq.podcini.util.event.FeedItemEvent
import ac.mdiq.podcini.util.event.UnreadItemsUpdateEvent
import android.os.Build
import android.os.Bundle
+import android.text.Html
import android.text.Layout
import android.text.TextUtils
import android.util.Log
@@ -32,11 +34,12 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.annotation.OptIn
+import androidx.appcompat.widget.Toolbar
+import androidx.core.app.ShareCompat
import androidx.fragment.app.Fragment
import androidx.media3.common.util.UnstableApi
import com.bumptech.glide.Glide
@@ -98,20 +101,20 @@ class ItemFragment : Fragment() {
@UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
- val viewBinding = FeeditemFragmentBinding.inflate(inflater)
- root = viewBinding.root
+ val binding = FeeditemFragmentBinding.inflate(inflater)
+ root = binding.root
Log.d(TAG, "fragment onCreateView")
- txtvPodcast = viewBinding.txtvPodcast
+ txtvPodcast = binding.txtvPodcast
txtvPodcast.setOnClickListener { openPodcast() }
- txtvTitle = viewBinding.txtvTitle
+ txtvTitle = binding.txtvTitle
if (Build.VERSION.SDK_INT >= 23) {
txtvTitle.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
}
- txtvDuration = viewBinding.txtvDuration
- txtvPublished = viewBinding.txtvPublished
+ txtvDuration = binding.txtvDuration
+ txtvPublished = binding.txtvPublished
txtvTitle.ellipsize = TextUtils.TruncateAt.END
- webvDescription = viewBinding.webvDescription
+ webvDescription = binding.webvDescription
webvDescription.setTimecodeSelectedListener { time: Int? ->
val cMedia = controller?.getMedia()
if (item?.media?.getIdentifier() == cMedia?.getIdentifier()) {
@@ -123,17 +126,17 @@ class ItemFragment : Fragment() {
}
registerForContextMenu(webvDescription)
- imgvCover = viewBinding.imgvCover
+ imgvCover = binding.imgvCover
imgvCover.setOnClickListener { openPodcast() }
- progbarDownload = viewBinding.circularProgressBar
- progbarLoading = viewBinding.progbarLoading
- butAction1 = viewBinding.butAction1
- butAction2 = viewBinding.butAction2
- butAction1Icon = viewBinding.butAction1Icon
- butAction2Icon = viewBinding.butAction2Icon
- butAction1Text = viewBinding.butAction1Text
- butAction2Text = viewBinding.butAction2Text
- noMediaLabel = viewBinding.noMediaLabel
+ progbarDownload = binding.circularProgressBar
+ progbarLoading = binding.progbarLoading
+ butAction1 = binding.butAction1
+ butAction2 = binding.butAction2
+ butAction1Icon = binding.butAction1Icon
+ butAction2Icon = binding.butAction2Icon
+ butAction1Text = binding.butAction1Text
+ butAction2Text = binding.butAction2Text
+ noMediaLabel = binding.noMediaLabel
butAction1.setOnClickListener(View.OnClickListener {
if (actionButton1 is StreamActionButton && !UserPreferences.isStreamOverDownload
@@ -165,7 +168,7 @@ class ItemFragment : Fragment() {
controller?.init()
load()
- return viewBinding.root
+ return binding.root
}
@OptIn(UnstableApi::class) private fun showOnDemandConfigBalloon(offerStreaming: Boolean) {
@@ -393,6 +396,9 @@ class ItemFragment : Fragment() {
DBReader.loadDescriptionOfFeedItem(feedItem)
val t = ShownotesCleaner(context, feedItem.description?:"", duration)
webviewData = t.processShownotes()
+ val bundle = Bundle()
+ bundle.putString("description", feedItem.description?:"")
+ this.arguments = bundle
}
return feedItem
}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPageFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPageFragment.kt
new file mode 100644
index 00000000..e2732c24
--- /dev/null
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPageFragment.kt
@@ -0,0 +1,177 @@
+package ac.mdiq.podcini.ui.fragment
+
+import ac.mdiq.podcini.R
+import ac.mdiq.podcini.databinding.FeeditemPageFragmentBinding
+import ac.mdiq.podcini.storage.DBReader
+import ac.mdiq.podcini.storage.model.feed.FeedItem
+import ac.mdiq.podcini.ui.activity.MainActivity
+import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
+import ac.mdiq.podcini.util.event.FeedItemEvent
+import android.os.Build
+import android.os.Bundle
+import android.text.Html
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.widget.Toolbar
+import androidx.core.app.ShareCompat
+import androidx.fragment.app.Fragment
+import androidx.media3.common.util.UnstableApi
+import com.google.android.material.appbar.MaterialToolbar
+import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import kotlin.math.max
+
+/**
+ * Displays information about a list of FeedItems.
+ */
+class ItemPageFragment : Fragment(), Toolbar.OnMenuItemClickListener {
+ private lateinit var page: View
+ private lateinit var toolbar: MaterialToolbar
+
+ private lateinit var itemFragment: ItemFragment
+
+ private var feedItems: LongArray? = null
+ private var item: FeedItem? = null
+ private var disposable: Disposable? = null
+
+ @UnstableApi override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ super.onCreateView(inflater, container, savedInstanceState)
+ val binding = FeeditemPageFragmentBinding.inflate(inflater)
+
+ Log.d(TAG, "fragment onCreateView")
+ toolbar = binding.toolbar
+ toolbar.title = ""
+ toolbar.inflateMenu(R.menu.feeditem_options)
+ toolbar.setNavigationOnClickListener { parentFragmentManager.popBackStack() }
+ toolbar.setOnMenuItemClickListener(this)
+
+ feedItems = requireArguments().getLongArray(ARG_FEEDITEMS)
+ val feedItemPos = max(0.0, requireArguments().getInt(ARG_FEEDITEM_POS).toDouble()).toInt()
+
+ page = binding.fragmentView
+ loadItem(feedItems!![feedItemPos])
+ val transaction = requireActivity().supportFragmentManager.beginTransaction()
+ itemFragment = ItemFragment.newInstance(if (feedItems!= null) feedItems!![feedItemPos] else 0L)
+ transaction.replace(R.id.fragment_view, itemFragment)
+ transaction.commit()
+
+ EventBus.getDefault().register(this)
+ return binding.root
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putInt(KEY_PAGER_ID, page.id)
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ EventBus.getDefault().unregister(this)
+ disposable?.dispose()
+ }
+
+ @UnstableApi private fun loadItem(itemId: Long) {
+ disposable?.dispose()
+
+ disposable = Observable.fromCallable { DBReader.getFeedItem(itemId) }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({ result: FeedItem? ->
+ item = result
+ refreshToolbarState()
+ }, { obj: Throwable -> obj.printStackTrace() })
+ }
+
+ @UnstableApi fun refreshToolbarState() {
+ if (item == null) return
+
+ if (item!!.hasMedia()) {
+ FeedItemMenuHandler.onPrepareMenu(toolbar.menu, item)
+ } else {
+ // these are already available via button1 and button2
+ FeedItemMenuHandler.onPrepareMenu(toolbar.menu, item,
+ R.id.mark_read_item, R.id.visit_website_item)
+ }
+ }
+
+ @UnstableApi override fun onMenuItemClick(menuItem: MenuItem): Boolean {
+ when (menuItem.itemId) {
+ R.id.open_podcast -> {
+ openPodcast()
+ return true
+ }
+ R.id.share_notes -> {
+ if (item == null) return false
+ val bundle = itemFragment.arguments
+ val notes = bundle?.getString("description", "")
+ if (!notes.isNullOrEmpty()) {
+ val shareText = if (Build.VERSION.SDK_INT >= 24) Html.fromHtml(notes, Html.FROM_HTML_MODE_LEGACY).toString()
+ else Html.fromHtml(notes).toString()
+ val context = requireContext()
+ val intent = ShareCompat.IntentBuilder(context)
+ .setType("text/plain")
+ .setText(shareText)
+ .setChooserTitle(R.string.share_notes_label)
+ .createChooserIntent()
+ context.startActivity(intent)
+ }
+ return true
+ }
+ else -> {
+ if (item == null) return false
+ return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.itemId, item!!)
+ }
+ }
+ }
+
+ @UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
+ fun onEventMainThread(event: FeedItemEvent) {
+ for (item in event.items) {
+ if (this.item != null && this.item!!.id == item.id) {
+ this.item = item
+ refreshToolbarState()
+ return
+ }
+ }
+ }
+
+ @UnstableApi private fun openPodcast() {
+ if (item == null) {
+ return
+ }
+ val fragment: Fragment = FeedItemlistFragment.newInstance(item!!.feedId)
+ (activity as MainActivity).loadChildFragment(fragment)
+ }
+
+ companion object {
+ const val TAG: String = "ItemPageFragment"
+ private const val ARG_FEEDITEMS = "feeditems"
+ private const val ARG_FEEDITEM_POS = "feeditem_pos"
+ private const val KEY_PAGER_ID = "pager_id"
+
+ /**
+ * Creates a new instance of an ItemPageFragment.
+ *
+ * @param feeditems The IDs of the FeedItems that belong to the same list
+ * @param feedItemPos The position of the FeedItem that is currently shown
+ * @return The ItemFragment instance
+ */
+ fun newInstance(feeditems: LongArray?, feedItemPos: Int): ItemPageFragment {
+ val fragment = ItemPageFragment()
+ val args = Bundle()
+ if (feeditems != null) args.putLongArray(ARG_FEEDITEMS, feeditems)
+ args.putInt(ARG_FEEDITEM_POS, max(0.0, feedItemPos.toDouble()).toInt())
+ fragment.arguments = args
+ return fragment
+ }
+ }
+}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPagerFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPagerFragment.kt
index f6cd8f99..a8c1104c 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPagerFragment.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/ItemPagerFragment.kt
@@ -7,13 +7,16 @@ import ac.mdiq.podcini.storage.model.feed.FeedItem
import ac.mdiq.podcini.ui.activity.MainActivity
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
import ac.mdiq.podcini.util.event.FeedItemEvent
+import android.os.Build
import android.os.Bundle
+import android.text.Html
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
+import androidx.core.app.ShareCompat
import androidx.fragment.app.Fragment
import androidx.media3.common.util.UnstableApi
import androidx.viewpager2.adapter.FragmentStateAdapter
@@ -43,7 +46,6 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
): View {
super.onCreateView(inflater, container, savedInstanceState)
val binding = FeeditemPagerFragmentBinding.inflate(inflater)
-// val layout: View = inflater.inflate(R.layout.feeditem_pager_fragment, container, false)
Log.d(TAG, "fragment onCreateView")
toolbar = binding.toolbar
@@ -107,9 +109,8 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
@UnstableApi fun refreshToolbarState() {
- if (item == null) {
- return
- }
+ if (item == null) return
+
if (item!!.hasMedia()) {
FeedItemMenuHandler.onPrepareMenu(toolbar.menu, item)
} else {
@@ -120,12 +121,33 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
}
@UnstableApi override fun onMenuItemClick(menuItem: MenuItem): Boolean {
- if (menuItem.itemId == R.id.open_podcast) {
- openPodcast()
- return true
+ when (menuItem.itemId) {
+ R.id.open_podcast -> {
+ openPodcast()
+ return true
+ }
+ R.id.share_notes -> {
+ if (item == null) return false
+ DBReader.loadDescriptionOfFeedItem(item!!)
+ if (!item!!.description.isNullOrEmpty()) {
+ val shareText = if (Build.VERSION.SDK_INT >= 24) Html.fromHtml(item!!.description,
+ Html.FROM_HTML_MODE_LEGACY).toString()
+ else Html.fromHtml(item!!.description).toString()
+ val context = requireContext()
+ val intent = ShareCompat.IntentBuilder(context)
+ .setType("text/plain")
+ .setText(shareText)
+ .setChooserTitle(R.string.share_notes_label)
+ .createChooserIntent()
+ context.startActivity(intent)
+ }
+ return true
+ }
+ else -> {
+ if (item == null) return false
+ return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.itemId, item!!)
+ }
}
- if (item == null) return false
- return FeedItemMenuHandler.onMenuItemClicked(this, menuItem.itemId, item!!)
}
@UnstableApi @Subscribe(threadMode = ThreadMode.MAIN)
@@ -149,6 +171,7 @@ class ItemPagerFragment : Fragment(), Toolbar.OnMenuItemClickListener {
private inner class ItemPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun createFragment(position: Int): Fragment {
+ Log.d(TAG, "createFragment $position")
return ItemFragment.newInstance(if (feedItems!= null) feedItems!![position] else 0L)
}
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/swipeactions/SwipeActions.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/swipeactions/SwipeActions.kt
index 8294c45e..1c6af85c 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/swipeactions/SwipeActions.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/swipeactions/SwipeActions.kt
@@ -68,7 +68,7 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
}
@UnstableApi override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
- if (!actions!!.hasActions()) {
+ if (actions != null && !actions!!.hasActions()) {
//open settings dialog if no prefs are set
SwipeActionsDialog(fragment.requireContext(), tag).show(object : SwipeActionsDialog.Callback {
override fun onCall() {
@@ -80,7 +80,7 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
val item = (viewHolder as EpisodeItemViewHolder).feedItem
- if (item != null && filter != null)
+ if (actions != null && item != null && filter != null)
(if (swipeDir == ItemTouchHelper.RIGHT) actions!!.right else actions!!.left)?.performAction(item, fragment, filter!!)
}
@@ -91,7 +91,7 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
var dx = dx
val right: SwipeAction
val left: SwipeAction
- if (actions!!.hasActions()) {
+ if (actions != null && actions!!.hasActions()) {
right = actions!!.right!!
left = actions!!.left!!
} else {
@@ -182,7 +182,7 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
}
fun startDrag(holder: EpisodeItemViewHolder?) {
- itemTouchHelper.startDrag(holder!!)
+ if (holder != null) itemTouchHelper.startDrag(holder)
}
class Actions(prefs: String?) {
diff --git a/app/src/main/java/ac/mdiq/podcini/ui/menuhandler/FeedItemMenuHandler.kt b/app/src/main/java/ac/mdiq/podcini/ui/menuhandler/FeedItemMenuHandler.kt
index 68184f6c..2ba47bf3 100644
--- a/app/src/main/java/ac/mdiq/podcini/ui/menuhandler/FeedItemMenuHandler.kt
+++ b/app/src/main/java/ac/mdiq/podcini/ui/menuhandler/FeedItemMenuHandler.kt
@@ -1,29 +1,30 @@
package ac.mdiq.podcini.ui.menuhandler
-import ac.mdiq.podcini.ui.activity.MainActivity
-import android.os.Handler
-import android.util.Log
-import android.view.KeyEvent
-import android.view.Menu
-import androidx.fragment.app.Fragment
-import androidx.media3.common.util.UnstableApi
-import com.google.android.material.snackbar.Snackbar
import ac.mdiq.podcini.R
+import ac.mdiq.podcini.net.sync.SynchronizationSettings
+import ac.mdiq.podcini.net.sync.model.EpisodeAction
+import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
import ac.mdiq.podcini.preferences.PlaybackPreferences
import ac.mdiq.podcini.receiver.MediaButtonReceiver
import ac.mdiq.podcini.service.playback.PlaybackServiceInterface
import ac.mdiq.podcini.storage.DBWriter
-import ac.mdiq.podcini.net.sync.SynchronizationSettings
-import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
-import ac.mdiq.podcini.util.*
-import ac.mdiq.podcini.ui.dialog.ShareDialog
import ac.mdiq.podcini.storage.model.feed.FeedItem
import ac.mdiq.podcini.storage.model.feed.FeedMedia
-import ac.mdiq.podcini.net.sync.model.EpisodeAction
+import ac.mdiq.podcini.ui.activity.MainActivity
+import ac.mdiq.podcini.ui.dialog.ShareDialog
import ac.mdiq.podcini.ui.view.LocalDeleteModal
+import ac.mdiq.podcini.util.*
+import android.os.Handler
+import android.util.Log
+import android.view.KeyEvent
+import android.view.Menu
import androidx.annotation.OptIn
+import androidx.fragment.app.Fragment
+import androidx.media3.common.util.UnstableApi
+import com.google.android.material.snackbar.Snackbar
import kotlin.math.ceil
+
/**
* Handles interactions with the FeedItemMenu.
*/
@@ -57,7 +58,6 @@ object FeedItemMenuHandler {
setItemVisibility(menu, R.id.visit_website_item, !(selectedItem.feed?.isLocalFeed?:false)
&& ShareUtils.hasLinkToShare(selectedItem))
setItemVisibility(menu, R.id.share_item, !(selectedItem.feed?.isLocalFeed?:false))
-// setItemVisibility(menu, R.id.remove_inbox_item, selectedItem.isNew)
setItemVisibility(menu, R.id.mark_read_item, !selectedItem.isPlayed())
setItemVisibility(menu, R.id.mark_unread_item, selectedItem.isPlayed())
setItemVisibility(menu, R.id.reset_position, hasMedia && selectedItem.media?.getPosition() != 0)
@@ -144,9 +144,6 @@ object FeedItemMenuHandler {
selectedItem.media!!.id)
}
}
-// R.id.remove_inbox_item -> {
-// removeNewFlagWithUndo(fragment, selectedItem)
-// }
R.id.mark_read_item -> {
selectedItem.setPlayed(true)
DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, true)
@@ -258,7 +255,7 @@ object FeedItemMenuHandler {
if (showSnackbar) {
(fragment.activity as MainActivity).showSnackbarAbovePlayer(
playStateStringRes, duration)
- .setAction(fragment.getString(R.string.undo)) { v ->
+ .setAction(fragment.getString(R.string.undo)) {
DBWriter.markItemPlayed(item.playState, item.id)
// don't forget to cancel the thing that's going to remove the media
h.removeCallbacks(r)
diff --git a/app/src/main/res/layout/feeditem_page_fragment.xml b/app/src/main/res/layout/feeditem_page_fragment.xml
new file mode 100644
index 00000000..1a0c6c89
--- /dev/null
+++ b/app/src/main/res/layout/feeditem_page_fragment.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml
index 0ea8f388..01717b8e 100644
--- a/app/src/main/res/layout/feeditemlist_header.xml
+++ b/app/src/main/res/layout/feeditemlist_header.xml
@@ -28,19 +28,6 @@
android:layout_width="148dp"
android:layout_height="match_parent" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ -
+
-
-
-
Please confirm that you want to mark all selected items as played.
Please confirm that you want to mark all selected items as unplayed.
Show information
@@ -177,6 +175,7 @@
Remove podcast
Share
Share file
+ Share notes
Please confirm that you want to delete the podcast \"%1$s\", ALL its episodes (including downloaded episodes), and its statistics.
Please confirm that you want to remove the selected podcasts, ALL their episodes (including downloaded episodes), and its statistics.
Please confirm that you want to remove the podcast \"%1$s\" and its statistics. The files in the local source folder will not be deleted.
diff --git a/changelog.md b/changelog.md
index 2b5f55b9..7fddde42 100644
--- a/changelog.md
+++ b/changelog.md
@@ -85,4 +85,12 @@
* corrected action icons for themes
* revealed info bar in Downloads view
* revealed info bar in Subscriptions view
-* reset tags list in Subscriptions when new tag is added
\ No newline at end of file
+* reset tags list in Subscriptions when new tag is added
+
+## 4.2.7
+
+* disabled drag actions when in multi-select mode (fixed crash bug)
+* renewed PodcastIndex API keys
+* added share notes menu option in episode view
+* press on title area of an episode now opens the episode info faster and more economically - without horizontal swipe
+* press on the icon of an episode opens the episode info the original way - with horizontal swipe
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/3020110.txt b/fastlane/metadata/android/en-US/changelogs/3020110.txt
new file mode 100644
index 00000000..90007eda
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/3020110.txt
@@ -0,0 +1,8 @@
+
+Version 4.2.7 brings several changes:
+
+* disabled drag actions when in multi-select mode (fixed crash bug)
+* renewed PodcastIndex API keys
+* added share notes menu option in episode view
+* press on title area of an episode now opens the episode info faster and more economically - without horizontal swipe
+* press on the icon of an episode opens the episode info the original way - with horizontal swipe