play speed, played mark, swipe icon clicks
@ -149,8 +149,8 @@ android {
|
||||
// Version code schema (not used):
|
||||
// "1.2.3-beta4" -> 1020304
|
||||
// "1.2.3" -> 1020395
|
||||
versionCode 3020111
|
||||
versionName "4.3.0"
|
||||
versionCode 3020112
|
||||
versionName "4.3.1"
|
||||
|
||||
def commit = ""
|
||||
try {
|
||||
|
@ -36,7 +36,7 @@ object ImageResourceUtils {
|
||||
@JvmStatic
|
||||
fun getFallbackImageLocation(playable: Playable): String? {
|
||||
if (playable is FeedMedia) {
|
||||
val item = playable.getItem()
|
||||
val item = playable.item
|
||||
return if (item?.feed != null) {
|
||||
item.feed!!.imageUrl
|
||||
} else {
|
||||
|
@ -26,8 +26,9 @@ object PlaybackSpeedUtils {
|
||||
mediaType = media.getMediaType()
|
||||
playbackSpeed = PlaybackPreferences.currentlyPlayingTemporaryPlaybackSpeed
|
||||
|
||||
if (playbackSpeed == FeedPreferences.SPEED_USE_GLOBAL && media is FeedMedia) {
|
||||
val item = media.getItem()
|
||||
// if (playbackSpeed == FeedPreferences.SPEED_USE_GLOBAL && media is FeedMedia) {
|
||||
if (media is FeedMedia) {
|
||||
val item = media.item
|
||||
if (item != null) {
|
||||
val feed = item.feed
|
||||
if (feed?.preferences != null) {
|
||||
|
@ -65,13 +65,13 @@ object SynchronizationQueueSink {
|
||||
if (!SynchronizationSettings.isProviderConnected) {
|
||||
return
|
||||
}
|
||||
if (media.getItem()?.feed == null || media.getItem()!!.feed!!.isLocalFeed) {
|
||||
if (media.item?.feed == null || media.item!!.feed!!.isLocalFeed) {
|
||||
return
|
||||
}
|
||||
if (media.startPosition < 0 || (!completed && media.startPosition >= media.getPosition())) {
|
||||
return
|
||||
}
|
||||
val action = EpisodeAction.Builder(media.getItem()!!, EpisodeAction.PLAY)
|
||||
val action = EpisodeAction.Builder(media.item!!, EpisodeAction.PLAY)
|
||||
.currentTimestamp()
|
||||
.started(media.startPosition / 1000)
|
||||
.position((if (completed) media.getDuration() else media.getPosition()) / 1000)
|
||||
|
@ -22,7 +22,7 @@ object PlayableUtils {
|
||||
playable.setLastPlayedTime(timestamp)
|
||||
|
||||
if (playable is FeedMedia) {
|
||||
val item = playable.getItem()
|
||||
val item = playable.item
|
||||
if (item != null && item.isNew) {
|
||||
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.id)
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ abstract class PlaybackController(private val activity: FragmentActivity) {
|
||||
val media = getMedia()
|
||||
if (media is FeedMedia) {
|
||||
media.setPosition(time)
|
||||
DBWriter.setFeedItem(media.getItem())
|
||||
DBWriter.setFeedItem(media.item)
|
||||
EventBus.getDefault().post(PlaybackPositionEvent(time, media.getDuration()))
|
||||
}
|
||||
}
|
||||
|
@ -87,43 +87,43 @@ class PlaybackPreferences private constructor() : OnSharedPreferenceChangeListen
|
||||
const val PLAYER_STATUS_OTHER: Int = 3
|
||||
|
||||
private var instance: PlaybackPreferences? = null
|
||||
private var prefs: SharedPreferences? = null
|
||||
private lateinit var prefs: SharedPreferences
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context) {
|
||||
instance = PlaybackPreferences()
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
prefs?.registerOnSharedPreferenceChangeListener(instance)
|
||||
prefs.registerOnSharedPreferenceChangeListener(instance)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val currentlyPlayingMediaType: Long
|
||||
get() = prefs!!.getLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, NO_MEDIA_PLAYING)
|
||||
get() = prefs.getLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, NO_MEDIA_PLAYING)
|
||||
|
||||
@JvmStatic
|
||||
val currentlyPlayingFeedMediaId: Long
|
||||
get() = prefs!!.getLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING)
|
||||
get() = prefs.getLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING)
|
||||
|
||||
@JvmStatic
|
||||
val currentEpisodeIsVideo: Boolean
|
||||
get() = prefs!!.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false)
|
||||
get() = prefs.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false)
|
||||
|
||||
@JvmStatic
|
||||
val currentPlayerStatus: Int
|
||||
get() = prefs!!.getInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER)
|
||||
get() = prefs.getInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER)
|
||||
|
||||
@JvmStatic
|
||||
var currentlyPlayingTemporaryPlaybackSpeed: Float
|
||||
get() = prefs!!.getFloat(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED, FeedPreferences.SPEED_USE_GLOBAL)
|
||||
get() = prefs.getFloat(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED, FeedPreferences.SPEED_USE_GLOBAL)
|
||||
set(speed) {
|
||||
val editor = prefs!!.edit()
|
||||
val editor = prefs.edit()
|
||||
editor.putFloat(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED, speed)
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun writeNoMediaPlaying() {
|
||||
val editor = prefs!!.edit()
|
||||
val editor = prefs.edit()
|
||||
editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, NO_MEDIA_PLAYING)
|
||||
editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, NO_MEDIA_PLAYING)
|
||||
editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING)
|
||||
@ -134,7 +134,7 @@ class PlaybackPreferences private constructor() : OnSharedPreferenceChangeListen
|
||||
@JvmStatic
|
||||
fun writeMediaPlaying(playable: Playable?, playerStatus: PlayerStatus) {
|
||||
Log.d(TAG, "Writing playback preferences")
|
||||
val editor = prefs!!.edit()
|
||||
val editor = prefs.edit()
|
||||
|
||||
if (playable == null) {
|
||||
writeNoMediaPlaying()
|
||||
@ -142,7 +142,7 @@ class PlaybackPreferences private constructor() : OnSharedPreferenceChangeListen
|
||||
editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, playable.getPlayableType().toLong())
|
||||
editor.putBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, playable.getMediaType() == MediaType.VIDEO)
|
||||
if (playable is FeedMedia) {
|
||||
val itemId = playable.getItem()?.feed?.id
|
||||
val itemId = playable.item?.feed?.id
|
||||
if (itemId != null) editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, itemId)
|
||||
editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, playable.id)
|
||||
} else {
|
||||
@ -160,14 +160,14 @@ class PlaybackPreferences private constructor() : OnSharedPreferenceChangeListen
|
||||
fun writePlayerStatus(playerStatus: PlayerStatus) {
|
||||
Log.d(TAG, "Writing player status playback preferences")
|
||||
|
||||
val editor = prefs!!.edit()
|
||||
val editor = prefs.edit()
|
||||
editor.putInt(PREF_CURRENT_PLAYER_STATUS, getCurrentPlayerStatusAsInt(playerStatus))
|
||||
editor.apply()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clearCurrentlyPlayingTemporaryPlaybackSpeed() {
|
||||
val editor = prefs!!.edit()
|
||||
val editor = prefs.edit()
|
||||
editor.remove(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED)
|
||||
editor.apply()
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ object PreferenceUpgrader {
|
||||
private const val PREF_CONFIGURED_VERSION = "version_code"
|
||||
private const val PREF_NAME = "app_version"
|
||||
|
||||
private var prefs: SharedPreferences? = null
|
||||
private lateinit var prefs: SharedPreferences
|
||||
|
||||
fun checkUpgrades(context: Context) {
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
@ -60,15 +60,15 @@ object PreferenceUpgrader {
|
||||
} // else 0 or special negative values, no change needed
|
||||
}
|
||||
if (oldVersion < 1070197) {
|
||||
if (prefs!!.getBoolean("prefMobileUpdate", false)) {
|
||||
prefs!!.edit().putString("prefMobileUpdateAllowed", "everything").apply()
|
||||
if (prefs.getBoolean("prefMobileUpdate", false)) {
|
||||
prefs.edit().putString("prefMobileUpdateAllowed", "everything").apply()
|
||||
}
|
||||
}
|
||||
if (oldVersion < 1070300) {
|
||||
if (prefs!!.getBoolean("prefEnableAutoDownloadOnMobile", false)) {
|
||||
if (prefs.getBoolean("prefEnableAutoDownloadOnMobile", false)) {
|
||||
isAllowMobileAutoDownload = true
|
||||
}
|
||||
when (prefs!!.getString("prefMobileUpdateAllowed", "images")) {
|
||||
when (prefs.getString("prefMobileUpdateAllowed", "images")) {
|
||||
"everything" -> {
|
||||
isAllowMobileFeedRefresh = true
|
||||
isAllowMobileEpisodeDownload = true
|
||||
@ -81,27 +81,27 @@ object PreferenceUpgrader {
|
||||
if (oldVersion < 1070400) {
|
||||
val theme = theme
|
||||
if (theme == UserPreferences.ThemePreference.LIGHT) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_THEME, "system").apply()
|
||||
prefs.edit().putString(UserPreferences.PREF_THEME, "system").apply()
|
||||
}
|
||||
|
||||
isQueueLocked = false
|
||||
isStreamOverDownload = false
|
||||
|
||||
if (!prefs!!.contains(UserPreferences.PREF_ENQUEUE_LOCATION)) {
|
||||
if (!prefs.contains(UserPreferences.PREF_ENQUEUE_LOCATION)) {
|
||||
val keyOldPrefEnqueueFront = "prefQueueAddToFront"
|
||||
val enqueueAtFront = prefs!!.getBoolean(keyOldPrefEnqueueFront, false)
|
||||
val enqueueAtFront = prefs.getBoolean(keyOldPrefEnqueueFront, false)
|
||||
val enqueueLocation = if (enqueueAtFront) EnqueueLocation.FRONT else EnqueueLocation.BACK
|
||||
UserPreferences.enqueueLocation = enqueueLocation
|
||||
}
|
||||
}
|
||||
if (oldVersion < 2010300) {
|
||||
// Migrate hardware button preferences
|
||||
if (prefs!!.getBoolean("prefHardwareForwardButtonSkips", false)) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_HARDWARE_FORWARD_BUTTON,
|
||||
if (prefs.getBoolean("prefHardwareForwardButtonSkips", false)) {
|
||||
prefs.edit().putString(UserPreferences.PREF_HARDWARE_FORWARD_BUTTON,
|
||||
KeyEvent.KEYCODE_MEDIA_NEXT.toString()).apply()
|
||||
}
|
||||
if (prefs!!.getBoolean("prefHardwarePreviousButtonRestarts", false)) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_HARDWARE_PREVIOUS_BUTTON,
|
||||
if (prefs.getBoolean("prefHardwarePreviousButtonRestarts", false)) {
|
||||
prefs.edit().putString(UserPreferences.PREF_HARDWARE_PREVIOUS_BUTTON,
|
||||
KeyEvent.KEYCODE_MEDIA_PREVIOUS.toString()).apply()
|
||||
}
|
||||
}
|
||||
@ -111,14 +111,14 @@ object PreferenceUpgrader {
|
||||
SwipeAction.REMOVE_FROM_QUEUE + "," + SwipeAction.REMOVE_FROM_QUEUE).apply()
|
||||
}
|
||||
if (oldVersion < 2050000) {
|
||||
prefs!!.edit().putBoolean(UserPreferences.PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, true).apply()
|
||||
prefs.edit().putBoolean(UserPreferences.PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, true).apply()
|
||||
}
|
||||
if (oldVersion < 2080000) {
|
||||
// Migrate drawer feed counter setting to reflect removal of
|
||||
// "unplayed and in inbox" (0), by changing it to "unplayed" (2)
|
||||
val feedCounterSetting = prefs!!.getString(UserPreferences.PREF_DRAWER_FEED_COUNTER, "2")
|
||||
val feedCounterSetting = prefs.getString(UserPreferences.PREF_DRAWER_FEED_COUNTER, "2")
|
||||
if (feedCounterSetting == "0") {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_DRAWER_FEED_COUNTER, "2").apply()
|
||||
prefs.edit().putString(UserPreferences.PREF_DRAWER_FEED_COUNTER, "2").apply()
|
||||
}
|
||||
|
||||
val sleepTimerPreferences =
|
||||
@ -128,28 +128,28 @@ object PreferenceUpgrader {
|
||||
val unit = timeUnits[sleepTimerPreferences.getInt("LastTimeUnit", 1)]
|
||||
setLastTimer(unit.toMinutes(value).toString())
|
||||
|
||||
if (prefs!!.getString(UserPreferences.PREF_EPISODE_CACHE_SIZE, "20")
|
||||
if (prefs.getString(UserPreferences.PREF_EPISODE_CACHE_SIZE, "20")
|
||||
== context.getString(R.string.pref_episode_cache_unlimited)) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_EPISODE_CACHE_SIZE,
|
||||
prefs.edit().putString(UserPreferences.PREF_EPISODE_CACHE_SIZE,
|
||||
"" + UserPreferences.EPISODE_CACHE_SIZE_UNLIMITED).apply()
|
||||
}
|
||||
}
|
||||
if (oldVersion < 3000007) {
|
||||
if (prefs!!.getString("prefBackButtonBehavior", "") == "drawer") {
|
||||
prefs!!.edit().putBoolean(UserPreferences.PREF_BACK_OPENS_DRAWER, true).apply()
|
||||
if (prefs.getString("prefBackButtonBehavior", "") == "drawer") {
|
||||
prefs.edit().putBoolean(UserPreferences.PREF_BACK_OPENS_DRAWER, true).apply()
|
||||
}
|
||||
}
|
||||
if (oldVersion < 3010000) {
|
||||
if (prefs!!.getString(UserPreferences.PREF_THEME, "system") == "2") {
|
||||
prefs!!.edit()
|
||||
if (prefs.getString(UserPreferences.PREF_THEME, "system") == "2") {
|
||||
prefs.edit()
|
||||
.putString(UserPreferences.PREF_THEME, "1")
|
||||
.putBoolean(UserPreferences.PREF_THEME_BLACK, true)
|
||||
.apply()
|
||||
}
|
||||
isAllowMobileSync = true
|
||||
if (prefs!!.getString(UserPreferences.PREF_UPDATE_INTERVAL, ":")!!
|
||||
if (prefs.getString(UserPreferences.PREF_UPDATE_INTERVAL, ":")!!
|
||||
.contains(":")) { // Unset or "time of day"
|
||||
prefs!!.edit().putString(UserPreferences.PREF_UPDATE_INTERVAL, "12").apply()
|
||||
prefs.edit().putString(UserPreferences.PREF_UPDATE_INTERVAL, "12").apply()
|
||||
}
|
||||
}
|
||||
if (oldVersion < 3020000) {
|
||||
@ -161,12 +161,12 @@ object PreferenceUpgrader {
|
||||
context.getSharedPreferences(AllEpisodesFragment.PREF_NAME, Context.MODE_PRIVATE)
|
||||
val oldEpisodeSort = allEpisodesPreferences.getString(UserPreferences.PREF_SORT_ALL_EPISODES, "")
|
||||
if (!StringUtils.isAllEmpty(oldEpisodeSort)) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_SORT_ALL_EPISODES, oldEpisodeSort).apply()
|
||||
prefs.edit().putString(UserPreferences.PREF_SORT_ALL_EPISODES, oldEpisodeSort).apply()
|
||||
}
|
||||
|
||||
val oldEpisodeFilter = allEpisodesPreferences.getString("filter", "")
|
||||
if (!StringUtils.isAllEmpty(oldEpisodeFilter)) {
|
||||
prefs!!.edit().putString(UserPreferences.PREF_FILTER_ALL_EPISODES, oldEpisodeFilter).apply()
|
||||
prefs.edit().putString(UserPreferences.PREF_FILTER_ALL_EPISODES, oldEpisodeFilter).apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ object DownloadRequestCreator {
|
||||
}
|
||||
Log.d(TAG, "Requesting download media from url " + media.download_url)
|
||||
|
||||
val username = if ((media.getItem()?.feed?.preferences != null)) media.getItem()!!.feed!!.preferences!!.username else null
|
||||
val password = if ((media.getItem()?.feed?.preferences != null)) media.getItem()!!.feed!!.preferences!!.password else null
|
||||
val username = if ((media.item?.feed?.preferences != null)) media.item!!.feed!!.preferences!!.username else null
|
||||
val password = if ((media.item?.feed?.preferences != null)) media.item!!.feed!!.preferences!!.password else null
|
||||
|
||||
return DownloadRequest.Builder(dest.toString(), media).withAuthentication(username, password)
|
||||
}
|
||||
@ -87,7 +87,7 @@ object DownloadRequestCreator {
|
||||
}
|
||||
|
||||
private fun getMediafilePath(media: FeedMedia): String {
|
||||
val title = media.getItem()?.feed?.title?:return ""
|
||||
val title = media.item?.feed?.title?:return ""
|
||||
val mediaPath = (MEDIA_DOWNLOADPATH
|
||||
+ FileNameGenerator.generateFileName(title))
|
||||
return UserPreferences.getDataFolder(mediaPath).toString() + "/"
|
||||
@ -97,8 +97,8 @@ object DownloadRequestCreator {
|
||||
var titleBaseFilename = ""
|
||||
|
||||
// Try to generate the filename by the item title
|
||||
if (media.getItem()?.title != null) {
|
||||
val title = media.getItem()!!.title!!
|
||||
if (media.item?.title != null) {
|
||||
val title = media.item!!.title!!
|
||||
titleBaseFilename = FileNameGenerator.generateFileName(title)
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedMedia
|
||||
import ac.mdiq.podcini.net.download.serviceinterface.DownloadServiceInterface
|
||||
import ac.mdiq.podcini.preferences.UserPreferences
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.util.concurrent.Future
|
||||
@ -36,7 +38,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
|
||||
ExistingWorkPolicy.KEEP, workRequest.build())
|
||||
}
|
||||
|
||||
override fun cancel(context: Context, media: FeedMedia) {
|
||||
@OptIn(UnstableApi::class) override fun cancel(context: Context, media: FeedMedia) {
|
||||
// This needs to be done here, not in the worker. Reason: The worker might or might not be running.
|
||||
DBWriter.deleteFeedMediaOfItem(context, media.id) // Remove partially downloaded file
|
||||
val tag = WORK_TAG_EPISODE_URL + media.download_url
|
||||
@ -48,7 +50,7 @@ class DownloadServiceInterfaceImpl : DownloadServiceInterface() {
|
||||
{ workInfos: List<WorkInfo> ->
|
||||
for (info in workInfos) {
|
||||
if (info.tags.contains(WORK_DATA_WAS_QUEUED)) {
|
||||
if (media.getItem() != null) DBWriter.removeQueueItem(context, false, media.getItem()!!)
|
||||
if (media.item != null) DBWriter.removeQueueItem(context, false, media.item!!)
|
||||
}
|
||||
}
|
||||
WorkManager.getInstance(context).cancelAllWorkByTag(tag)
|
||||
|
@ -31,19 +31,19 @@ class MediaDownloadedHandler(private val context: Context, var updatedStatus: Do
|
||||
return
|
||||
}
|
||||
// media.setDownloaded modifies played state
|
||||
val broadcastUnreadStateUpdate = media.getItem() != null && media.getItem()!!.isNew
|
||||
val broadcastUnreadStateUpdate = media.item != null && media.item!!.isNew
|
||||
media.setDownloaded(true)
|
||||
media.file_url = request.destination
|
||||
if (request.destination != null) media.size = File(request.destination).length()
|
||||
media.checkEmbeddedPicture() // enforce check
|
||||
|
||||
// check if file has chapters
|
||||
if (media.getItem() != null && !media.getItem()!!.hasChapters()) {
|
||||
if (media.item != null && !media.item!!.hasChapters()) {
|
||||
media.setChapters(ChapterUtils.loadChaptersFromMediaFile(media, context))
|
||||
}
|
||||
|
||||
if (media.getItem()?.podcastIndexChapterUrl != null) {
|
||||
ChapterUtils.loadChaptersFromUrl(media.getItem()!!.podcastIndexChapterUrl!!, false)
|
||||
if (media.item?.podcastIndexChapterUrl != null) {
|
||||
ChapterUtils.loadChaptersFromUrl(media.item!!.podcastIndexChapterUrl!!, false)
|
||||
}
|
||||
// Get duration
|
||||
var durationStr: String? = null
|
||||
@ -60,7 +60,7 @@ class MediaDownloadedHandler(private val context: Context, var updatedStatus: Do
|
||||
Log.e(TAG, "Get duration failed", e)
|
||||
}
|
||||
|
||||
val item = media.getItem()
|
||||
val item = media.item
|
||||
|
||||
try {
|
||||
DBWriter.setFeedMedia(media).get()
|
||||
|
@ -166,8 +166,8 @@ class LocalPSMP(context: Context, callback: PSMPCallback) : PlaybackServiceMedia
|
||||
stream -> {
|
||||
val streamurl = media!!.getStreamUrl()
|
||||
if (streamurl != null) {
|
||||
if (playable is FeedMedia && playable.getItem()?.feed?.preferences != null) {
|
||||
val preferences = playable.getItem()!!.feed!!.preferences!!
|
||||
if (playable is FeedMedia && playable.item?.feed?.preferences != null) {
|
||||
val preferences = playable.item!!.feed!!.preferences!!
|
||||
mediaPlayer?.setDataSource(
|
||||
streamurl,
|
||||
preferences.username,
|
||||
@ -465,8 +465,8 @@ class LocalPSMP(context: Context, callback: PSMPCallback) : PlaybackServiceMedia
|
||||
var volumeLeft = volumeLeft
|
||||
var volumeRight = volumeRight
|
||||
val playable = getPlayable()
|
||||
if (playable is FeedMedia && playable.getItem()?.feed?.preferences != null) {
|
||||
val preferences = playable.getItem()!!.feed!!.preferences!!
|
||||
if (playable is FeedMedia && playable.item?.feed?.preferences != null) {
|
||||
val preferences = playable.item!!.feed!!.preferences!!
|
||||
val volumeAdaptionSetting = preferences.volumeAdaptionSetting
|
||||
if (volumeAdaptionSetting != null) {
|
||||
val adaptionFactor = volumeAdaptionSetting.adaptionFactor
|
||||
|
@ -70,6 +70,7 @@ import ac.mdiq.podcini.util.FeedItemUtil.hasAlmostEnded
|
||||
import ac.mdiq.podcini.util.FeedUtil.shouldAutoDeleteItemsOnThatFeed
|
||||
import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast
|
||||
import ac.mdiq.podcini.util.NetworkUtils.isStreamingAllowed
|
||||
import ac.mdiq.podcini.util.event.MessageEvent
|
||||
import ac.mdiq.podcini.util.event.settings.SpeedPresetChangedEvent
|
||||
import ac.mdiq.podcini.util.event.settings.VolumeAdaptionChangedEvent
|
||||
import android.Manifest
|
||||
@ -408,7 +409,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
parentId == getString(R.string.current_playing_episode) -> {
|
||||
val playable = createInstanceFromPreferences(this)
|
||||
if (playable is FeedMedia) {
|
||||
feedItems = listOf(playable.getItem())
|
||||
feedItems = listOf(playable.item)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
@ -516,7 +517,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
return
|
||||
}
|
||||
|
||||
val preferences = playable.getItem()?.feed?.preferences
|
||||
val preferences = playable.item?.feed?.preferences
|
||||
val skipIntro = preferences?.feedSkipIntro ?: 0
|
||||
|
||||
val context = applicationContext
|
||||
@ -536,8 +537,8 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
|
||||
@SuppressLint("LaunchActivityFromNotification")
|
||||
private fun displayStreamingNotAllowedNotification(originalIntent: Intent) {
|
||||
if (EventBus.getDefault().hasSubscriberForEvent(ac.mdiq.podcini.util.event.MessageEvent::class.java)) {
|
||||
EventBus.getDefault().post(ac.mdiq.podcini.util.event.MessageEvent(
|
||||
if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent::class.java)) {
|
||||
EventBus.getDefault().post(MessageEvent(
|
||||
getString(R.string.confirm_mobile_streaming_notification_message)))
|
||||
return
|
||||
}
|
||||
@ -836,7 +837,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING && autoEnable() && autoEnableByTime && !sleepTimerActive()) {
|
||||
setSleepTimer(timerMillis())
|
||||
EventBus.getDefault()
|
||||
.post(ac.mdiq.podcini.util.event.MessageEvent(getString(R.string.sleep_timer_enabled_label),
|
||||
.post(MessageEvent(getString(R.string.sleep_timer_enabled_label),
|
||||
{ disableSleepTimer() }, getString(R.string.undo)))
|
||||
}
|
||||
loadQueueForMediaSession()
|
||||
@ -915,7 +916,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
}
|
||||
|
||||
override fun ensureMediaInfoLoaded(media: Playable) {
|
||||
if (media is FeedMedia && media.getItem() == null) {
|
||||
if (media is FeedMedia && media.item == null) {
|
||||
media.setItem(DBReader.getFeedItem(media.itemId))
|
||||
}
|
||||
}
|
||||
@ -968,10 +969,10 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
return null
|
||||
}
|
||||
Log.d(TAG, "getNextInQueue()")
|
||||
if (currentMedia.getItem() == null) {
|
||||
if (currentMedia.item == null) {
|
||||
currentMedia.setItem(DBReader.getFeedItem(currentMedia.itemId))
|
||||
}
|
||||
val item = currentMedia.getItem()
|
||||
val item = currentMedia.item
|
||||
if (item == null) {
|
||||
Log.w(TAG, "getNextInQueue() with FeedMedia object whose FeedItem is null")
|
||||
writeNoMediaPlaying()
|
||||
@ -1061,7 +1062,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
return
|
||||
}
|
||||
val media = playable
|
||||
val item = media.getItem()
|
||||
val item = media.item
|
||||
val smartMarkAsPlayed = hasAlmostEnded(media)
|
||||
if (!ended && smartMarkAsPlayed) {
|
||||
Log.d(TAG, "smart mark as played")
|
||||
@ -1133,7 +1134,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
val remainingTime = duration - currentPosition
|
||||
|
||||
val feedMedia = playable
|
||||
val preferences = feedMedia.getItem()?.feed?.preferences
|
||||
val preferences = feedMedia.item?.feed?.preferences
|
||||
val skipEnd = preferences?.feedSkipEnding
|
||||
if (skipEnd != null && skipEnd > 0 && skipEnd * 1000 < this.duration && (remainingTime - (skipEnd * 1000) > 0)
|
||||
&& ((remainingTime - skipEnd * 1000) < (currentPlaybackSpeed * 1000))) {
|
||||
@ -1144,7 +1145,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
val toast = Toast.makeText(context, skipMesg, Toast.LENGTH_LONG)
|
||||
toast.show()
|
||||
|
||||
this.autoSkippedFeedMediaId = feedMedia.getItem()!!.identifyingValue
|
||||
this.autoSkippedFeedMediaId = feedMedia.item!!.identifyingValue
|
||||
mediaPlayer?.skip()
|
||||
}
|
||||
}
|
||||
@ -1260,11 +1261,11 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
var iconUri = p.getImageLocation()
|
||||
if (p is FeedMedia) { // Don't use embedded cover etc, which Android can't load
|
||||
val m = p
|
||||
if (m.getItem() != null) {
|
||||
val item = m.getItem()
|
||||
if (item?.imageUrl != null) {
|
||||
if (m.item != null) {
|
||||
val item = m.item!!
|
||||
if (item.imageUrl != null) {
|
||||
iconUri = item.imageUrl
|
||||
} else if (item?.feed != null) {
|
||||
} else if (item.feed != null) {
|
||||
iconUri = item.feed!!.imageUrl
|
||||
}
|
||||
}
|
||||
@ -1535,7 +1536,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
fun speedPresetChanged(event: SpeedPresetChangedEvent) {
|
||||
// TODO: speed
|
||||
if (playable is FeedMedia) {
|
||||
if ((playable as FeedMedia).getItem()?.feed?.id == event.feedId) {
|
||||
if ((playable as FeedMedia).item?.feed?.id == event.feedId) {
|
||||
if (event.speed == FeedPreferences.SPEED_USE_GLOBAL) {
|
||||
setSpeed(getPlaybackSpeed(playable!!.getMediaType()))
|
||||
} else {
|
||||
@ -1549,9 +1550,9 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
@Suppress("unused")
|
||||
fun skipIntroEndingPresetChanged(event: ac.mdiq.podcini.util.event.settings.SkipIntroEndingChangedEvent) {
|
||||
if (playable is FeedMedia) {
|
||||
if ((playable as FeedMedia).getItem()?.feed?.id == event.feedId) {
|
||||
if ((playable as FeedMedia).item?.feed?.id == event.feedId) {
|
||||
if (event.skipEnding != 0) {
|
||||
val feedPreferences = (playable as FeedMedia).getItem()?.feed?.preferences
|
||||
val feedPreferences = (playable as FeedMedia).item?.feed?.preferences
|
||||
if (feedPreferences != null) {
|
||||
feedPreferences.feedSkipIntro = event.skipIntro
|
||||
feedPreferences.feedSkipEnding = event.skipEnding
|
||||
@ -1682,7 +1683,7 @@ class PlaybackService : MediaBrowserServiceCompat() {
|
||||
|
||||
private fun addPlayableToQueue(playable: Playable?) {
|
||||
if (playable is FeedMedia) {
|
||||
val itemId = playable.getItem()?.id ?: return
|
||||
val itemId = playable.item?.id ?: return
|
||||
DBWriter.addQueueItem(this, false, true, itemId)
|
||||
notifyChildrenChanged(getString(R.string.queue_label))
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ internal class PlaybackVolumeUpdater {
|
||||
private fun updateFeedMediaVolumeIfNecessary(mediaPlayer: PlaybackServiceMediaPlayer, feedId: Long,
|
||||
volumeAdaptionSetting: VolumeAdaptionSetting, feedMedia: FeedMedia
|
||||
) {
|
||||
if (feedMedia.getItem()?.feed?.id == feedId) {
|
||||
val preferences = feedMedia.getItem()!!.feed!!.preferences
|
||||
if (feedMedia.item?.feed?.id == feedId) {
|
||||
val preferences = feedMedia.item!!.feed!!.preferences
|
||||
if (preferences != null) preferences.volumeAdaptionSetting = volumeAdaptionSetting
|
||||
|
||||
if (mediaPlayer.playerStatus == PlayerStatus.PLAYING) {
|
||||
|
@ -1,31 +1,30 @@
|
||||
package ac.mdiq.podcini.storage
|
||||
|
||||
import ac.mdiq.podcini.R
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
||||
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
|
||||
import ac.mdiq.podcini.storage.DBReader.extractItemlistFromCursor
|
||||
import ac.mdiq.podcini.storage.DBReader.getFeed
|
||||
import ac.mdiq.podcini.storage.DBReader.getFeedItemList
|
||||
import ac.mdiq.podcini.storage.DBReader.getFeedList
|
||||
import ac.mdiq.podcini.storage.DBReader.loadAdditionalFeedItemListData
|
||||
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
|
||||
import ac.mdiq.podcini.util.comparator.FeedItemPubdateComparator
|
||||
import ac.mdiq.podcini.util.event.FeedItemEvent.Companion.updated
|
||||
import ac.mdiq.podcini.storage.database.PodDBAdapter
|
||||
import ac.mdiq.podcini.storage.database.PodDBAdapter.Companion.getInstance
|
||||
import ac.mdiq.podcini.storage.database.mapper.FeedCursorMapper.convert
|
||||
import ac.mdiq.podcini.storage.model.download.DownloadError
|
||||
import ac.mdiq.podcini.storage.model.download.DownloadResult
|
||||
import ac.mdiq.podcini.storage.model.feed.Feed
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedMedia
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedPreferences.NewEpisodesAction
|
||||
import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
||||
import ac.mdiq.podcini.storage.database.PodDBAdapter
|
||||
import ac.mdiq.podcini.storage.database.PodDBAdapter.Companion.getInstance
|
||||
import ac.mdiq.podcini.storage.database.mapper.FeedCursorMapper.convert
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.newEpisodesAction
|
||||
import ac.mdiq.podcini.util.comparator.FeedItemPubdateComparator
|
||||
import ac.mdiq.podcini.util.event.FeedItemEvent.Companion.updated
|
||||
import ac.mdiq.podcini.util.event.FeedListUpdateEvent
|
||||
import ac.mdiq.podcini.util.event.MessageEvent
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
@ -92,8 +91,8 @@ import java.util.concurrent.*
|
||||
media.setDownloaded(false)
|
||||
media.setFile_url(null)
|
||||
DBWriter.setFeedMedia(media)
|
||||
if (media.getItem() != null) EventBus.getDefault().post(updated(media.getItem()!!))
|
||||
EventBus.getDefault().post(ac.mdiq.podcini.util.event.MessageEvent(context.getString(R.string.error_file_not_found)))
|
||||
if (media.item != null) EventBus.getDefault().post(updated(media.item!!))
|
||||
EventBus.getDefault().post(MessageEvent(context.getString(R.string.error_file_not_found)))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,6 +228,7 @@ import java.util.concurrent.*
|
||||
}
|
||||
|
||||
// get the most recent date now, before we start changing the list
|
||||
// only used to add to IN_Box???
|
||||
val priorMostRecent = savedFeed.mostRecentItem
|
||||
var priorMostRecentDate: Date? = Date()
|
||||
if (priorMostRecent != null) {
|
||||
@ -275,11 +275,12 @@ import java.util.concurrent.*
|
||||
oldItem.itemIdentifier = item.itemIdentifier
|
||||
|
||||
if (oldItem.isPlayed() && oldItem.media != null) {
|
||||
val durs = oldItem.media!!.getDuration() / 1000
|
||||
val action = EpisodeAction.Builder(oldItem, EpisodeAction.PLAY)
|
||||
.currentTimestamp()
|
||||
.started(oldItem.media!!.getDuration() / 1000)
|
||||
.position(oldItem.media!!.getDuration() / 1000)
|
||||
.total(oldItem.media!!.getDuration() / 1000)
|
||||
.started(durs)
|
||||
.position(durs)
|
||||
.total(durs)
|
||||
.build()
|
||||
SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action)
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ import java.util.concurrent.TimeUnit
|
||||
if (media != null) {
|
||||
val result = deleteFeedMediaSynchronous(context, media)
|
||||
|
||||
val item = media.getItem()
|
||||
val item = media.item
|
||||
if (result && item != null && shouldDeleteRemoveFromQueue()) {
|
||||
removeQueueItemSynchronous(context, false, item.id)
|
||||
}
|
||||
@ -140,7 +140,7 @@ import java.util.concurrent.TimeUnit
|
||||
nm.cancel(R.id.notification_playing)
|
||||
}
|
||||
|
||||
val item = media.getItem()
|
||||
val item = media.item
|
||||
if (item != null) {
|
||||
if (localDelete) {
|
||||
// Do full update of this feed to get rid of the item
|
||||
|
@ -65,7 +65,7 @@ class ItemEnqueuePositionCalculator(private val enqueueLocation: EnqueueLocation
|
||||
if (currentPlaying !is FeedMedia) {
|
||||
return -1
|
||||
}
|
||||
val curPlayingItemId = currentPlaying.getItem()!!.id
|
||||
val curPlayingItemId = currentPlaying.item!!.id
|
||||
for (i in curQueue.indices) {
|
||||
if (curPlayingItemId == curQueue[i].id) {
|
||||
return i
|
||||
|
@ -157,8 +157,8 @@ class PodDBAdapter private constructor() {
|
||||
} else {
|
||||
values.put(KEY_PLAYBACK_COMPLETION_DATE, 0)
|
||||
}
|
||||
if (media.getItem() != null) {
|
||||
values.put(KEY_FEEDITEM, media.getItem()!!.id)
|
||||
if (media.item != null) {
|
||||
values.put(KEY_FEEDITEM, media.item!!.id)
|
||||
}
|
||||
if (media.id == 0L) {
|
||||
media.id = db.insert(TABLE_NAME_FEED_MEDIA, null, values)
|
||||
|
@ -197,11 +197,11 @@ class FeedItem : FeedComponent, Serializable {
|
||||
* try to return the title. If the title is not given, it will use the link
|
||||
* of the entry.
|
||||
*/
|
||||
get() = if (itemIdentifier != null && itemIdentifier!!.isNotEmpty()) {
|
||||
get() = if (!itemIdentifier.isNullOrEmpty()) {
|
||||
itemIdentifier
|
||||
} else if (title != null && title!!.isNotEmpty()) {
|
||||
} else if (!title.isNullOrEmpty()) {
|
||||
title
|
||||
} else if (hasMedia() && media!!.download_url != null) {
|
||||
} else if (media?.download_url != null) {
|
||||
media!!.download_url
|
||||
} else {
|
||||
link
|
||||
@ -233,7 +233,7 @@ class FeedItem : FeedComponent, Serializable {
|
||||
@JvmName("setMediaFunction")
|
||||
fun setMedia(media: FeedMedia?) {
|
||||
this.media = media
|
||||
if (media != null && media.getItem() !== this) {
|
||||
if (media != null && media.item !== this) {
|
||||
media.setItem(this)
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,9 @@ class FeedMedia : FeedFile, Playable {
|
||||
private set
|
||||
|
||||
@Volatile
|
||||
private var item: FeedItem?
|
||||
var item: FeedItem?
|
||||
private set
|
||||
|
||||
private var playbackCompletionDate: Date? = null
|
||||
var startPosition: Int = -1
|
||||
private set
|
||||
@ -75,7 +77,7 @@ class FeedMedia : FeedFile, Playable {
|
||||
}
|
||||
|
||||
override fun getHumanReadableIdentifier(): String? {
|
||||
return if (item != null && item!!.title != null) {
|
||||
return if (item?.title != null) {
|
||||
item!!.title
|
||||
} else {
|
||||
download_url
|
||||
@ -98,7 +100,7 @@ class FeedMedia : FeedFile, Playable {
|
||||
// getImageLocation() also loads embedded images, which we can not send to external devices
|
||||
if (item!!.imageUrl != null) {
|
||||
builder.setIconUri(Uri.parse(item!!.imageUrl))
|
||||
} else if (item!!.feed != null && item!!.feed!!.imageUrl != null) {
|
||||
} else if (item!!.feed?.imageUrl != null) {
|
||||
builder.setIconUri(Uri.parse(item!!.feed!!.imageUrl))
|
||||
}
|
||||
}
|
||||
@ -109,7 +111,7 @@ class FeedMedia : FeedFile, Playable {
|
||||
* Uses mimetype to determine the type of media.
|
||||
*/
|
||||
override fun getMediaType(): MediaType {
|
||||
return MediaType.fromMimeType(mime_type!!)
|
||||
return MediaType.fromMimeType(mime_type)
|
||||
}
|
||||
|
||||
fun updateFromOther(other: FeedMedia) {
|
||||
@ -190,9 +192,9 @@ class FeedMedia : FeedFile, Playable {
|
||||
return (CHECKED_ON_SIZE_BUT_UNKNOWN.toLong() == this.size)
|
||||
}
|
||||
|
||||
fun getItem(): FeedItem? {
|
||||
return item
|
||||
}
|
||||
// fun getItem(): FeedItem? {
|
||||
// return item
|
||||
// }
|
||||
|
||||
/**
|
||||
* Sets the item object of this FeedMedia. If the given
|
||||
@ -241,24 +243,23 @@ class FeedMedia : FeedFile, Playable {
|
||||
dest.writeString(file_url)
|
||||
dest.writeString(download_url)
|
||||
dest.writeByte((if ((isDownloaded())) 1 else 0).toByte())
|
||||
dest.writeLong(if ((playbackCompletionDate != null)) playbackCompletionDate!!.time else 0)
|
||||
dest.writeLong(playbackCompletionDate?.time ?: 0)
|
||||
dest.writeInt(playedDuration)
|
||||
dest.writeLong(lastPlayedTime)
|
||||
}
|
||||
|
||||
override fun writeToPreferences(prefEditor: SharedPreferences.Editor?) {
|
||||
if (item != null && item!!.feed != null) {
|
||||
prefEditor!!.putLong(PREF_FEED_ID, item!!.feed!!.id)
|
||||
override fun writeToPreferences(prefEditor: SharedPreferences.Editor) {
|
||||
if (item?.feed != null) {
|
||||
prefEditor.putLong(PREF_FEED_ID, item!!.feed!!.id)
|
||||
} else {
|
||||
prefEditor!!.putLong(PREF_FEED_ID, 0L)
|
||||
prefEditor.putLong(PREF_FEED_ID, 0L)
|
||||
}
|
||||
prefEditor.putLong(PREF_MEDIA_ID, id)
|
||||
}
|
||||
|
||||
override fun getEpisodeTitle(): String {
|
||||
if (item == null) {
|
||||
return ""
|
||||
}
|
||||
if (item == null) return ""
|
||||
|
||||
return if (item!!.title != null) {
|
||||
item!!.title!!
|
||||
} else {
|
||||
@ -295,11 +296,7 @@ class FeedMedia : FeedFile, Playable {
|
||||
}
|
||||
|
||||
override fun getPubDate(): Date? {
|
||||
return if (item?.getPubDate() != null) {
|
||||
item!!.getPubDate()!!
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return item?.getPubDate()
|
||||
}
|
||||
|
||||
override fun localFileAvailable(): Boolean {
|
||||
@ -334,12 +331,16 @@ class FeedMedia : FeedFile, Playable {
|
||||
}
|
||||
|
||||
override fun getImageLocation(): String? {
|
||||
return if (item != null) {
|
||||
item!!.imageLocation
|
||||
} else if (hasEmbeddedPicture()) {
|
||||
FILENAME_PREFIX_EMBEDDED_COVER + getLocalMediaUrl()
|
||||
} else {
|
||||
null
|
||||
return when {
|
||||
item != null -> {
|
||||
item!!.imageLocation
|
||||
}
|
||||
hasEmbeddedPicture() -> {
|
||||
FILENAME_PREFIX_EMBEDDED_COVER + getLocalMediaUrl()
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,9 @@ enum class MediaType {
|
||||
"application/x-flac"
|
||||
))
|
||||
|
||||
fun fromMimeType(mimeType: String): MediaType {
|
||||
fun fromMimeType(mimeType: String?): MediaType {
|
||||
return when {
|
||||
mimeType.isEmpty() -> {
|
||||
mimeType.isNullOrEmpty() -> {
|
||||
UNKNOWN
|
||||
}
|
||||
mimeType.startsWith("audio") -> {
|
||||
|
@ -17,7 +17,7 @@ interface Playable : Parcelable, Serializable {
|
||||
* Implementations must NOT call commit() after they have written the values
|
||||
* to the preferences file.
|
||||
*/
|
||||
fun writeToPreferences(prefEditor: SharedPreferences.Editor?)
|
||||
fun writeToPreferences(prefEditor: SharedPreferences.Editor)
|
||||
|
||||
/**
|
||||
* Returns the title of the episode that this playable represents
|
||||
|
@ -118,7 +118,7 @@ class RemoteMedia : Playable {
|
||||
// return notes
|
||||
// }
|
||||
|
||||
override fun writeToPreferences(prefEditor: SharedPreferences.Editor?) {
|
||||
override fun writeToPreferences(prefEditor: SharedPreferences.Editor) {
|
||||
//it seems pointless to do it, since the session should be kept by the remote device.
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ class RemoteMedia : Playable {
|
||||
}
|
||||
|
||||
override fun getMediaType(): MediaType {
|
||||
return MediaType.fromMimeType(mimeType!!)
|
||||
return MediaType.fromMimeType(mimeType)
|
||||
}
|
||||
|
||||
override fun getStreamUrl(): String? {
|
||||
@ -243,7 +243,7 @@ class RemoteMedia : Playable {
|
||||
if (!TextUtils.equals(streamUrl, other.getStreamUrl())) {
|
||||
return false
|
||||
}
|
||||
val fi = other.getItem()
|
||||
val fi = other.item
|
||||
if (fi == null || !TextUtils.equals(itemIdentifier, fi.itemIdentifier)) {
|
||||
return false
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import ac.mdiq.podcini.ui.statistics.StatisticsFragment
|
||||
import ac.mdiq.podcini.ui.view.LockableBottomSheetBehavior
|
||||
import ac.mdiq.podcini.util.event.EpisodeDownloadEvent
|
||||
import ac.mdiq.podcini.util.event.FeedUpdateRunningEvent
|
||||
import ac.mdiq.podcini.util.event.MessageEvent
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@ -553,7 +554,7 @@ class MainActivity : CastEnabledActivity() {
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.MessageEvent) {
|
||||
fun onEventMainThread(event: MessageEvent) {
|
||||
Log.d(TAG, "onEvent($event)")
|
||||
|
||||
val snackbar = showSnackbarAbovePlayer(event.message, Snackbar.LENGTH_LONG)
|
||||
|
@ -60,6 +60,7 @@ import ac.mdiq.podcini.feed.parser.FeedHandler
|
||||
import ac.mdiq.podcini.feed.parser.FeedHandlerResult
|
||||
import ac.mdiq.podcini.feed.parser.UnsupportedFeedtypeException
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.isEnableAutodownload
|
||||
import ac.mdiq.podcini.service.download.Downloader
|
||||
import ac.mdiq.podcini.ui.common.ThemeUtils.getColorFromAttr
|
||||
import ac.mdiq.podcini.ui.glide.FastBlurTransformation
|
||||
import io.reactivex.Maybe
|
||||
@ -89,7 +90,7 @@ class OnlineFeedViewActivity : AppCompatActivity() {
|
||||
@Volatile
|
||||
private var feeds: List<Feed>? = null
|
||||
private var selectedDownloadUrl: String? = null
|
||||
private var downloader: ac.mdiq.podcini.service.download.Downloader? = null
|
||||
private var downloader: Downloader? = null
|
||||
private var username: String? = null
|
||||
private var password: String? = null
|
||||
|
||||
@ -468,7 +469,6 @@ class OnlineFeedViewActivity : AppCompatActivity() {
|
||||
if (feed.download_url != null) alternateUrlsList.add(feed.download_url!!)
|
||||
alternateUrlsTitleList.add(feed.title)
|
||||
|
||||
|
||||
alternateUrlsList.addAll(alternateFeedUrls.keys)
|
||||
for (url in alternateFeedUrls.keys) {
|
||||
alternateUrlsTitleList.add(alternateFeedUrls[url])
|
||||
@ -554,9 +554,8 @@ class OnlineFeedViewActivity : AppCompatActivity() {
|
||||
|
||||
private val feedId: Long
|
||||
get() {
|
||||
if (feeds == null) {
|
||||
return 0
|
||||
}
|
||||
if (feeds == null) return 0
|
||||
|
||||
for (f in feeds!!) {
|
||||
if (f.download_url == selectedDownloadUrl) {
|
||||
return f.id
|
||||
|
@ -29,6 +29,7 @@ import ac.mdiq.podcini.preferences.UserPreferences.rewindSecs
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.setShowRemainTimeSetting
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.shouldShowRemainingTime
|
||||
import ac.mdiq.podcini.ui.appstartintent.MainActivityStarter
|
||||
import ac.mdiq.podcini.util.event.MessageEvent
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.PixelFormat
|
||||
@ -498,7 +499,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onEventMainThread(event: ac.mdiq.podcini.util.event.MessageEvent) {
|
||||
fun onEventMainThread(event: MessageEvent) {
|
||||
Log.d(TAG, "onEvent($event)")
|
||||
val errorDialog = MaterialAlertDialogBuilder(this)
|
||||
errorDialog.setMessage(event.message)
|
||||
@ -530,7 +531,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
|
||||
val hasWebsiteLink = getWebsiteLinkWithFallback(media) != null
|
||||
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink)
|
||||
|
||||
val isItemAndHasLink = isFeedMedia && hasLinkToShare((media as FeedMedia).getItem())
|
||||
val isItemAndHasLink = isFeedMedia && hasLinkToShare((media as FeedMedia).item)
|
||||
val isItemHasDownloadLink = isFeedMedia && (media as FeedMedia?)?.download_url != null
|
||||
menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink)
|
||||
|
||||
@ -780,7 +781,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
|
||||
return media.getWebsiteLink()
|
||||
}
|
||||
media is FeedMedia -> {
|
||||
return getLinkWithFallback(media.getItem())
|
||||
return getLinkWithFallback(media.item)
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
@ -788,7 +789,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener {
|
||||
|
||||
private fun getFeedItem(playable: Playable?): FeedItem? {
|
||||
return if (playable is FeedMedia) {
|
||||
playable.getItem()
|
||||
playable.item
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ class DownloadLogAdapter(private val context: Activity) : BaseAdapter() {
|
||||
Log.e(TAG, "Could not find feed media for feed id: " + status.feedfileId)
|
||||
return@OnClickListener
|
||||
}
|
||||
if (media.getItem() != null) DownloadActionButton(media.getItem()!!).onClick(context)
|
||||
if (media.item != null) DownloadActionButton(media.item!!).onClick(context)
|
||||
(context as MainActivity).showSnackbarAbovePlayer(
|
||||
R.string.status_downloading_label, Toast.LENGTH_SHORT)
|
||||
})
|
||||
|
@ -70,7 +70,6 @@ open class VariableSpeedDialog : BottomSheetDialogFragment() {
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val binding = SpeedSelectDialogBinding.inflate(inflater)
|
||||
// val root = View.inflate(context, R.layout.speed_select_dialog, null)
|
||||
speedSeekBar = binding.speedSeekBar
|
||||
speedSeekBar.setProgressChangedListener { multiplier: Float ->
|
||||
controller?.setPlaybackSpeed(multiplier)
|
||||
|
@ -461,7 +461,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
|
||||
val isFeedMedia = media is FeedMedia
|
||||
toolbar.menu?.findItem(R.id.open_feed_item)?.setVisible(isFeedMedia)
|
||||
if (media != null && isFeedMedia) {
|
||||
FeedItemMenuHandler.onPrepareMenu(toolbar.menu, (media as FeedMedia).getItem())
|
||||
FeedItemMenuHandler.onPrepareMenu(toolbar.menu, (media as FeedMedia).item)
|
||||
}
|
||||
|
||||
if (controller != null) {
|
||||
@ -474,7 +474,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
val media: Playable = controller?.getMedia() ?: return false
|
||||
|
||||
val feedItem: FeedItem? = if ((media is FeedMedia)) media.getItem() else null
|
||||
val feedItem: FeedItem? = if ((media is FeedMedia)) media.item else null
|
||||
if (feedItem != null && FeedItemMenuHandler.onMenuItemClicked(this, item.itemId, feedItem)) {
|
||||
return true
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ class ChaptersFragment : AppCompatDialogFragment() {
|
||||
}
|
||||
adapter.setMedia(media)
|
||||
(dialog as AlertDialog).getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.INVISIBLE
|
||||
if ((media is FeedMedia) && !media.getItem()?.podcastIndexChapterUrl.isNullOrEmpty()) {
|
||||
if ((media is FeedMedia) && !media.item?.podcastIndexChapterUrl.isNullOrEmpty()) {
|
||||
(dialog as AlertDialog).getButton(DialogInterface.BUTTON_NEUTRAL).visibility = View.VISIBLE
|
||||
}
|
||||
val positionOfCurrentChapter = getCurrentChapter(media)
|
||||
|
@ -102,13 +102,13 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
||||
|
||||
swipeActions = SwipeActions(this, TAG).attachTo(recyclerView)
|
||||
swipeActions.setFilter(FeedItemFilter(FeedItemFilter.DOWNLOADED))
|
||||
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
refreshSwipeTelltale()
|
||||
binding.leftActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
binding.rightActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
|
||||
val animator: RecyclerView.ItemAnimator? = recyclerView.itemAnimator
|
||||
if (animator is SimpleItemAnimator) {
|
||||
@ -299,6 +299,10 @@ class CompletedDownloadsFragment : Fragment(), SelectableAdapter.OnSelectModeLis
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onSwipeActionsChanged(event: SwipeActionsChangedEvent?) {
|
||||
refreshSwipeTelltale()
|
||||
}
|
||||
|
||||
private fun refreshSwipeTelltale() {
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class CoverFragment : Fragment() {
|
||||
+ "\u00A0"
|
||||
+ StringUtils.replace(StringUtils.stripToEmpty(pubDateStr), " ", "\u00A0"))
|
||||
if (media is FeedMedia) {
|
||||
val items = media.getItem()
|
||||
val items = media.item
|
||||
if (items != null) {
|
||||
val openFeed: Intent = MainActivity.getIntentToOpenFeed(requireContext(), items.feedId)
|
||||
viewBinding.txtvPodcastTitle.setOnClickListener { startActivity(openFeed) }
|
||||
@ -189,7 +189,7 @@ class CoverFragment : Fragment() {
|
||||
} else if (media is FeedMedia) {
|
||||
val fm: FeedMedia? = (media as FeedMedia?)
|
||||
// If an item has chapters but they are not loaded yet, still display the button.
|
||||
chapterControlVisible = fm?.getItem() != null && fm.getItem()!!.hasChapters()
|
||||
chapterControlVisible = fm?.item != null && fm.item!!.hasChapters()
|
||||
}
|
||||
val newVisibility = if (chapterControlVisible) View.VISIBLE else View.GONE
|
||||
if (viewBinding.chapterButton.visibility != newVisibility) {
|
||||
|
@ -1,6 +1,27 @@
|
||||
package ac.mdiq.podcini.ui.fragment
|
||||
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.EpisodesListFragmentBinding
|
||||
import ac.mdiq.podcini.databinding.MultiSelectSpeedDialBinding
|
||||
import ac.mdiq.podcini.net.download.FeedUpdateManager
|
||||
import ac.mdiq.podcini.playback.event.PlaybackPositionEvent
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItemFilter
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.adapter.EpisodeItemListAdapter
|
||||
import ac.mdiq.podcini.ui.adapter.SelectableAdapter
|
||||
import ac.mdiq.podcini.ui.dialog.ConfirmationDialog
|
||||
import ac.mdiq.podcini.ui.dialog.SwipeActionsDialog
|
||||
import ac.mdiq.podcini.ui.fragment.actions.EpisodeMultiSelectActionHandler
|
||||
import ac.mdiq.podcini.ui.fragment.swipeactions.SwipeActions
|
||||
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
|
||||
import ac.mdiq.podcini.ui.menuhandler.MenuItemUtils
|
||||
import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
||||
import ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
import ac.mdiq.podcini.ui.view.viewholder.EpisodeItemViewHolder
|
||||
import ac.mdiq.podcini.util.FeedItemUtil
|
||||
import ac.mdiq.podcini.util.event.*
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
@ -18,26 +39,6 @@ import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.leinardi.android.speeddial.SpeedDialActionItem
|
||||
import com.leinardi.android.speeddial.SpeedDialView
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.EpisodesListFragmentBinding
|
||||
import ac.mdiq.podcini.databinding.MultiSelectSpeedDialBinding
|
||||
import ac.mdiq.podcini.ui.adapter.EpisodeItemListAdapter
|
||||
import ac.mdiq.podcini.ui.adapter.SelectableAdapter
|
||||
import ac.mdiq.podcini.ui.dialog.ConfirmationDialog
|
||||
import ac.mdiq.podcini.ui.menuhandler.MenuItemUtils
|
||||
import ac.mdiq.podcini.util.FeedItemUtil
|
||||
import ac.mdiq.podcini.net.download.FeedUpdateManager
|
||||
import ac.mdiq.podcini.util.event.*
|
||||
import ac.mdiq.podcini.playback.event.PlaybackPositionEvent
|
||||
import ac.mdiq.podcini.ui.fragment.actions.EpisodeMultiSelectActionHandler
|
||||
import ac.mdiq.podcini.ui.fragment.swipeactions.SwipeActions
|
||||
import ac.mdiq.podcini.ui.menuhandler.FeedItemMenuHandler
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItemFilter
|
||||
import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
||||
import ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
import ac.mdiq.podcini.ui.view.viewholder.EpisodeItemViewHolder
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -101,13 +102,13 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
|
||||
|
||||
swipeActions = SwipeActions(this, getFragmentTag()).attachTo(recyclerView)
|
||||
swipeActions.setFilter(getFilter())
|
||||
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
refreshSwipeTelltale()
|
||||
binding.leftActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
binding.rightActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
|
||||
val animator: RecyclerView.ItemAnimator? = recyclerView.itemAnimator
|
||||
if (animator is SimpleItemAnimator) {
|
||||
@ -389,6 +390,10 @@ abstract class EpisodesListFragment : Fragment(), SelectableAdapter.OnSelectMode
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onSwipeActionsChanged(event: SwipeActionsChangedEvent?) {
|
||||
refreshSwipeTelltale()
|
||||
}
|
||||
|
||||
private fun refreshSwipeTelltale() {
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
|
@ -117,12 +117,13 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
swipeActions = SwipeActions(this, TAG).attachTo(binding.recyclerView)
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.header.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.header.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
refreshSwipeTelltale()
|
||||
binding.header.leftActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
binding.header.rightActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
|
||||
binding.progressBar.visibility = View.VISIBLE
|
||||
|
||||
@ -409,12 +410,7 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onSwipeActionsChanged(event: SwipeActionsChangedEvent?) {
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.header.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.header.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
refreshSwipeTelltale()
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
|
||||
@ -426,6 +422,15 @@ class FeedItemlistFragment : Fragment(), AdapterView.OnItemClickListener, Toolba
|
||||
binding.swipeRefresh.isRefreshing = event.isFeedUpdateRunning
|
||||
}
|
||||
|
||||
private fun refreshSwipeTelltale() {
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.header.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.header.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
}
|
||||
|
||||
@UnstableApi private fun refreshHeaderView() {
|
||||
setupHeaderView()
|
||||
if (feed == null) {
|
||||
|
@ -93,7 +93,7 @@ class ItemDescriptionFragment : Fragment() {
|
||||
return@create
|
||||
}
|
||||
if (media is FeedMedia) {
|
||||
var item = media.getItem()
|
||||
var item = media.item
|
||||
if (item == null) {
|
||||
item = DBReader.getFeedItem(media.itemId)
|
||||
media.setItem(item)
|
||||
|
@ -45,6 +45,7 @@ import ac.mdiq.podcini.storage.model.feed.FeedItem
|
||||
import ac.mdiq.podcini.storage.model.feed.FeedItemFilter
|
||||
import ac.mdiq.podcini.storage.model.feed.SortOrder
|
||||
import ac.mdiq.podcini.preferences.UserPreferences
|
||||
import ac.mdiq.podcini.ui.dialog.SwipeActionsDialog
|
||||
import ac.mdiq.podcini.ui.view.EmptyViewHandler
|
||||
import ac.mdiq.podcini.ui.view.EpisodeItemListRecyclerView
|
||||
import ac.mdiq.podcini.ui.view.LiftOnScrollListener
|
||||
@ -122,13 +123,13 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
|
||||
swipeActions = QueueSwipeActions()
|
||||
swipeActions.setFilter(FeedItemFilter(FeedItemFilter.QUEUED))
|
||||
swipeActions.attachTo(recyclerView)
|
||||
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
if (swipeActions.actions?.right != null) {
|
||||
binding.rightActionIcon.setImageResource(swipeActions.actions!!.right!!.getActionIcon())
|
||||
}
|
||||
refreshSwipeTelltale()
|
||||
binding.leftActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
binding.rightActionIcon.setOnClickListener({
|
||||
swipeActions.showDialog()
|
||||
})
|
||||
|
||||
recyclerAdapter = object : QueueRecyclerAdapter(activity as MainActivity, swipeActions) {
|
||||
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
|
||||
@ -298,6 +299,10 @@ class QueueFragment : Fragment(), Toolbar.OnMenuItemClickListener, SelectableAda
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onSwipeActionsChanged(event: SwipeActionsChangedEvent?) {
|
||||
refreshSwipeTelltale()
|
||||
}
|
||||
|
||||
private fun refreshSwipeTelltale() {
|
||||
if (swipeActions.actions?.left != null) {
|
||||
binding.leftActionIcon.setImageResource(swipeActions.actions!!.left!!.getActionIcon())
|
||||
}
|
||||
|
@ -99,8 +99,8 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v
|
||||
.setTitle(R.string.playback_speed)
|
||||
.setView(viewBinding.root)
|
||||
.setPositiveButton("OK") { _: DialogInterface?, _: Int ->
|
||||
val newSpeed = if (viewBinding.useGlobalCheckbox.isChecked
|
||||
) FeedPreferences.SPEED_USE_GLOBAL else viewBinding.seekBar.currentSpeed
|
||||
val newSpeed = if (viewBinding.useGlobalCheckbox.isChecked) FeedPreferences.SPEED_USE_GLOBAL
|
||||
else viewBinding.seekBar.currentSpeed
|
||||
saveFeedPreferences { feedPreferences: FeedPreferences ->
|
||||
feedPreferences.feedPlaybackSpeed = newSpeed
|
||||
}
|
||||
|
@ -74,12 +74,13 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
|
||||
@UnstableApi override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
|
||||
if (actions != null && !actions!!.hasActions()) {
|
||||
//open settings dialog if no prefs are set
|
||||
SwipeActionsDialog(fragment.requireContext(), tag).show(object : SwipeActionsDialog.Callback {
|
||||
override fun onCall() {
|
||||
this@SwipeActions.reloadPreference()
|
||||
EventBus.getDefault().post(SwipeActionsChangedEvent())
|
||||
}
|
||||
})
|
||||
showDialog()
|
||||
// SwipeActionsDialog(fragment.requireContext(), tag).show(object : SwipeActionsDialog.Callback {
|
||||
// override fun onCall() {
|
||||
// this@SwipeActions.reloadPreference()
|
||||
// EventBus.getDefault().post(SwipeActionsChangedEvent())
|
||||
// }
|
||||
// })
|
||||
return
|
||||
}
|
||||
|
||||
@ -89,6 +90,15 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
|
||||
(if (swipeDir == ItemTouchHelper.RIGHT) actions!!.right else actions!!.left)?.performAction(item, fragment, filter!!)
|
||||
}
|
||||
|
||||
fun showDialog() {
|
||||
SwipeActionsDialog(fragment.requireContext(), tag).show(object : SwipeActionsDialog.Callback {
|
||||
override fun onCall() {
|
||||
this@SwipeActions.reloadPreference()
|
||||
EventBus.getDefault().post(SwipeActionsChangedEvent())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@UnstableApi override fun onChildDraw(c: Canvas, recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
dx: Float, dy: Float, actionState: Int, isCurrentlyActive: Boolean
|
||||
@ -206,7 +216,7 @@ open class SwipeActions(dragDirs: Int, private val fragment: Fragment, private v
|
||||
}
|
||||
|
||||
fun hasActions(): Boolean {
|
||||
return right != null && left != null && right!!.getId() != SwipeAction.NO_ACTION && left!!.getId() != SwipeAction.NO_ACTION
|
||||
return right != null && left != null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,26 +54,26 @@ class EpisodeItemViewHolder(private val activity: MainActivity, parent: ViewGrou
|
||||
private val placeholder: TextView = binding.txtvPlaceholder
|
||||
private val cover: ImageView = binding.imgvCover
|
||||
private val title: TextView = binding.txtvTitle
|
||||
private val pubDate: TextView
|
||||
private val position: TextView
|
||||
private val duration: TextView
|
||||
private val size: TextView
|
||||
private val pubDate: TextView = binding.txtvPubDate
|
||||
private val position: TextView = binding.txtvPosition
|
||||
private val duration: TextView = binding.txtvDuration
|
||||
private val size: TextView = binding.size
|
||||
@JvmField
|
||||
val isInQueue: ImageView
|
||||
private val isVideo: ImageView
|
||||
val isFavorite: ImageView
|
||||
private val progressBar: ProgressBar
|
||||
val isInQueue: ImageView = binding.ivInPlaylist
|
||||
private val isVideo: ImageView = binding.ivIsVideo
|
||||
private val isFavorite: ImageView = binding.isFavorite
|
||||
private val progressBar: ProgressBar = binding.progressBar
|
||||
@JvmField
|
||||
val secondaryActionButton: View
|
||||
val secondaryActionButton: View = binding.secondaryActionButton.root
|
||||
@JvmField
|
||||
val secondaryActionIcon: ImageView
|
||||
private val secondaryActionProgress: CircularProgressBar
|
||||
private val separatorIcons: TextView
|
||||
private val leftPadding: View
|
||||
val secondaryActionIcon: ImageView = binding.secondaryActionButton.secondaryActionIcon
|
||||
private val secondaryActionProgress: CircularProgressBar = binding.secondaryActionButton.secondaryActionProgress
|
||||
private val separatorIcons: TextView = binding.separatorIcons
|
||||
private val leftPadding: View = binding.leftPadding
|
||||
@JvmField
|
||||
val coverHolder: CardView
|
||||
val coverHolder: CardView = binding.coverHolder
|
||||
@JvmField
|
||||
val infoCard: LinearLayout
|
||||
val infoCard: LinearLayout = binding.infoCard
|
||||
|
||||
private var item: FeedItem? = null
|
||||
|
||||
@ -81,21 +81,6 @@ class EpisodeItemViewHolder(private val activity: MainActivity, parent: ViewGrou
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL)
|
||||
}
|
||||
pubDate = binding.txtvPubDate
|
||||
position = binding.txtvPosition
|
||||
duration = binding.txtvDuration
|
||||
progressBar = binding.progressBar
|
||||
isInQueue = binding.ivInPlaylist
|
||||
isVideo = binding.ivIsVideo
|
||||
isFavorite = binding.isFavorite
|
||||
size = binding.size
|
||||
separatorIcons = binding.separatorIcons
|
||||
secondaryActionProgress = binding.secondaryActionButton.secondaryActionProgress
|
||||
secondaryActionButton = binding.secondaryActionButton.root
|
||||
secondaryActionIcon = binding.secondaryActionButton.secondaryActionIcon
|
||||
coverHolder = binding.coverHolder
|
||||
infoCard = binding.infoCard
|
||||
leftPadding = binding.leftPadding
|
||||
itemView.tag = this
|
||||
}
|
||||
|
||||
@ -103,16 +88,20 @@ class EpisodeItemViewHolder(private val activity: MainActivity, parent: ViewGrou
|
||||
this.item = item
|
||||
placeholder.text = item.feed?.title
|
||||
title.text = item.title
|
||||
container.alpha = if (item.isPlayed()) 0.75f else 1.0f
|
||||
if (item.isPlayed()) {
|
||||
leftPadding.contentDescription = item.title + ". " + activity.getString(R.string.is_played)
|
||||
binding.playedMark.visibility = View.VISIBLE
|
||||
binding.playedMark.alpha = 1.0f
|
||||
} else {
|
||||
leftPadding.contentDescription = item.title
|
||||
binding.playedMark.visibility = View.GONE
|
||||
}
|
||||
pubDate.text = DateFormatter.formatAbbrev(activity, item.getPubDate())
|
||||
pubDate.setContentDescription(DateFormatter.formatForAccessibility(item.getPubDate()))
|
||||
isFavorite.visibility = if (item.isTagged(FeedItem.TAG_FAVORITE)) View.VISIBLE else View.GONE
|
||||
isInQueue.visibility = if (item.isTagged(FeedItem.TAG_QUEUE)) View.VISIBLE else View.GONE
|
||||
container.alpha = if (item.isPlayed()) 0.5f else 1.0f
|
||||
container.alpha = if (item.isPlayed()) 0.75f else 1.0f
|
||||
|
||||
val actionButton: ItemActionButton = ItemActionButton.forItem(item)
|
||||
actionButton.configure(secondaryActionButton, secondaryActionIcon, activity)
|
||||
|
@ -54,10 +54,10 @@ object ChapterUtils {
|
||||
var chaptersFromDatabase: List<Chapter>? = null
|
||||
var chaptersFromPodcastIndex: List<Chapter>? = null
|
||||
if (playable is FeedMedia) {
|
||||
if (playable.getItem() == null) {
|
||||
if (playable.item == null) {
|
||||
playable.setItem(DBReader.getFeedItem(playable.itemId))
|
||||
}
|
||||
val item = playable.getItem()
|
||||
val item = playable.item
|
||||
if (item != null) {
|
||||
if (item.hasChapters()) {
|
||||
chaptersFromDatabase = DBReader.loadChaptersOfFeedItem(item)
|
||||
|
@ -82,6 +82,17 @@
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/played_mark"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@color/background_green"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:contentDescription="@string/is_played"
|
||||
app:srcCompat="@drawable/ic_check"
|
||||
android:importantForAccessibility="yes"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
@ -20,6 +20,7 @@
|
||||
<color name="seek_background_light">#90000000</color>
|
||||
<color name="seek_background_dark">#905B5B5B</color>
|
||||
<color name="navigation_bar_divider_light">#1F000000</color>
|
||||
<color name="background_green">#00EE00</color>
|
||||
|
||||
<color name="accent_light">#0078C2</color>
|
||||
<color name="accent_dark">#3D8BFF</color>
|
||||
|
@ -118,7 +118,7 @@ object CastUtils {
|
||||
return false
|
||||
}
|
||||
val metadata = info.metadata
|
||||
val fi = media.getItem()
|
||||
val fi = media.item
|
||||
if (fi == null || metadata == null || !TextUtils.equals(metadata.getString(KEY_EPISODE_IDENTIFIER), fi.itemIdentifier)) {
|
||||
return false
|
||||
}
|
||||
|
@ -71,8 +71,8 @@ object MediaInfoCreator {
|
||||
return null
|
||||
}
|
||||
val metadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_GENERIC)
|
||||
checkNotNull(media.getItem()) { "item is null" }
|
||||
val feedItem = media.getItem()
|
||||
checkNotNull(media.item) { "item is null" }
|
||||
val feedItem = media.item
|
||||
if (feedItem != null) {
|
||||
metadata.putString(MediaMetadata.KEY_TITLE, media.getEpisodeTitle())
|
||||
val subtitle = media.getFeedTitle()
|
||||
@ -86,7 +86,7 @@ object MediaInfoCreator {
|
||||
metadata.addImage(WebImage(Uri.parse(url)))
|
||||
}
|
||||
val calendar = Calendar.getInstance()
|
||||
if (media.getItem()?.getPubDate() != null) calendar.time = media.getItem()!!.getPubDate()!!
|
||||
if (media.item?.getPubDate() != null) calendar.time = media.item!!.getPubDate()!!
|
||||
metadata.putDate(MediaMetadata.KEY_RELEASE_DATE, calendar)
|
||||
if (feed != null) {
|
||||
if (!feed.author.isNullOrEmpty()) {
|
||||
|
@ -83,7 +83,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
Mockito.`when`(feedMedia.getItem()?.feed?.id).thenReturn(FEED_ID + 1)
|
||||
Mockito.`when`(feedMedia.item?.feed?.id).thenReturn(FEED_ID + 1)
|
||||
|
||||
val playbackVolumeUpdater = PlaybackVolumeUpdater()
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.OFF)
|
||||
@ -100,7 +100,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION)
|
||||
|
||||
@ -119,7 +119,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION)
|
||||
|
||||
@ -138,7 +138,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION)
|
||||
|
||||
@ -157,7 +157,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION)
|
||||
|
||||
@ -176,7 +176,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION)
|
||||
|
||||
@ -195,7 +195,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
|
||||
val feedMedia = mockFeedMedia()
|
||||
Mockito.`when`(mediaPlayer!!.getPlayable()).thenReturn(feedMedia)
|
||||
val feedPreferences: FeedPreferences = feedMedia.getItem()!!.feed!!.preferences!!
|
||||
val feedPreferences: FeedPreferences = feedMedia.item!!.feed!!.preferences!!
|
||||
|
||||
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer!!, FEED_ID, VolumeAdaptionSetting.HEAVY_REDUCTION)
|
||||
|
||||
@ -212,7 +212,7 @@ class PlaybackVolumeUpdaterTest {
|
||||
val feed = Mockito.mock(Feed::class.java)
|
||||
val feedPreferences = Mockito.mock(FeedPreferences::class.java)
|
||||
|
||||
Mockito.`when`(feedMedia.getItem()).thenReturn(feedItem)
|
||||
Mockito.`when`(feedMedia.item).thenReturn(feedItem)
|
||||
Mockito.`when`(feedItem.feed).thenReturn(feed)
|
||||
Mockito.`when`(feed.id).thenReturn(FEED_ID)
|
||||
Mockito.`when`(feed.preferences).thenReturn(feedPreferences)
|
||||
|
@ -451,7 +451,7 @@ class DbReaderTest {
|
||||
val m: FeedMedia = feed.items[i].media!!
|
||||
m.setPlaybackCompletionDate(Date((i + 1).toLong()))
|
||||
adapter.setFeedMediaPlaybackCompletionDate(m)
|
||||
ids[ids.size - 1 - i] = m.getItem()!!.id
|
||||
ids[ids.size - 1 - i] = m.item!!.id
|
||||
}
|
||||
adapter.close()
|
||||
|
||||
|
@ -60,7 +60,7 @@ class DbWriterTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
UserPreferences.init(context!!)
|
||||
UserPreferences.init(context)
|
||||
init(context)
|
||||
|
||||
val app = context as Application?
|
||||
@ -69,14 +69,14 @@ class DbWriterTest {
|
||||
DownloadServiceInterface.setImpl(DownloadServiceInterfaceStub())
|
||||
|
||||
// create new database
|
||||
PodDBAdapter.init(context!!)
|
||||
PodDBAdapter.init(context)
|
||||
deleteDatabase()
|
||||
val adapter = getInstance()
|
||||
adapter.open()
|
||||
adapter.close()
|
||||
|
||||
val prefEdit = PreferenceManager.getDefaultSharedPreferences(
|
||||
context!!.applicationContext).edit()
|
||||
context.applicationContext).edit()
|
||||
prefEdit.putBoolean(UserPreferences.PREF_DELETE_REMOVES_FROM_QUEUE, true).commit()
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class DbWriterTest {
|
||||
PodDBAdapter.tearDownTests()
|
||||
DBWriter.tearDownTests()
|
||||
|
||||
val testDir = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val testDir = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(testDir)
|
||||
for (f in testDir!!.listFiles()) {
|
||||
f.delete()
|
||||
@ -129,7 +129,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeedMediaOfItemFileExists() {
|
||||
val dest = File(context!!.getExternalFilesDir(TEST_FOLDER), "testFile")
|
||||
val dest = File(context.getExternalFilesDir(TEST_FOLDER), "testFile")
|
||||
|
||||
Assert.assertTrue(dest.createNewFile())
|
||||
|
||||
@ -151,7 +151,7 @@ class DbWriterTest {
|
||||
Assert.assertTrue(media!!.id != 0L)
|
||||
Assert.assertTrue(item.id != 0L)
|
||||
|
||||
deleteFeedMediaOfItem(context!!, media.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeedMediaOfItem(context, media.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
media = getFeedMedia(media.id)
|
||||
Assert.assertNotNull(media)
|
||||
Assert.assertFalse(dest.exists())
|
||||
@ -164,7 +164,7 @@ class DbWriterTest {
|
||||
fun testDeleteFeedMediaOfItemRemoveFromQueue() {
|
||||
Assert.assertTrue(shouldDeleteRemoveFromQueue())
|
||||
|
||||
val dest = File(context!!.getExternalFilesDir(TEST_FOLDER), "testFile")
|
||||
val dest = File(context.getExternalFilesDir(TEST_FOLDER), "testFile")
|
||||
|
||||
Assert.assertTrue(dest.createNewFile())
|
||||
|
||||
@ -191,7 +191,7 @@ class DbWriterTest {
|
||||
queue = getQueue().toMutableList()
|
||||
Assert.assertTrue(queue.size != 0)
|
||||
|
||||
deleteFeedMediaOfItem(context!!, media.id)
|
||||
deleteFeedMediaOfItem(context, media.id)
|
||||
Awaitility.await().timeout(2, TimeUnit.SECONDS).until { !dest.exists() }
|
||||
media = getFeedMedia(media.id)
|
||||
Assert.assertNotNull(media)
|
||||
@ -204,7 +204,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeed() {
|
||||
val destFolder = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val destFolder = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(destFolder)
|
||||
|
||||
val feed = Feed("url", null, "title")
|
||||
@ -236,7 +236,7 @@ class DbWriterTest {
|
||||
Assert.assertTrue(item.media!!.id != 0L)
|
||||
}
|
||||
|
||||
deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeed(context, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
|
||||
// check if files still exist
|
||||
for (f in itemFiles) {
|
||||
@ -262,7 +262,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeedNoItems() {
|
||||
val destFolder = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val destFolder = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(destFolder)
|
||||
|
||||
val feed = Feed("url", null, "title")
|
||||
@ -276,7 +276,7 @@ class DbWriterTest {
|
||||
|
||||
Assert.assertTrue(feed.id != 0L)
|
||||
|
||||
deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeed(context, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
|
||||
adapter = getInstance()
|
||||
adapter.open()
|
||||
@ -289,7 +289,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeedNoFeedMedia() {
|
||||
val destFolder = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val destFolder = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(destFolder)
|
||||
|
||||
val feed = Feed("url", null, "title")
|
||||
@ -313,7 +313,7 @@ class DbWriterTest {
|
||||
Assert.assertTrue(item.id != 0L)
|
||||
}
|
||||
|
||||
deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeed(context, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
|
||||
adapter = getInstance()
|
||||
adapter.open()
|
||||
@ -331,7 +331,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeedWithQueueItems() {
|
||||
val destFolder = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val destFolder = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(destFolder)
|
||||
|
||||
val feed = Feed("url", null, "title")
|
||||
@ -369,7 +369,7 @@ class DbWriterTest {
|
||||
queueCursor.close()
|
||||
|
||||
adapter.close()
|
||||
deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeed(context, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
adapter.open()
|
||||
|
||||
var c = adapter.getFeedCursor(feed.id)
|
||||
@ -392,7 +392,7 @@ class DbWriterTest {
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDeleteFeedNoDownloadedFiles() {
|
||||
val destFolder = context!!.getExternalFilesDir(TEST_FOLDER)
|
||||
val destFolder = context.getExternalFilesDir(TEST_FOLDER)
|
||||
Assert.assertNotNull(destFolder)
|
||||
|
||||
val feed = Feed("url", null, "title")
|
||||
@ -421,7 +421,7 @@ class DbWriterTest {
|
||||
Assert.assertTrue(item.media!!.id != 0L)
|
||||
}
|
||||
|
||||
deleteFeed(context!!, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeed(context, feed.id)[TIMEOUT, TimeUnit.SECONDS]
|
||||
|
||||
adapter = getInstance()
|
||||
adapter.open()
|
||||
@ -459,7 +459,7 @@ class DbWriterTest {
|
||||
adapter.close()
|
||||
|
||||
val itemsToDelete: List<FeedItem> = feed.items.subList(0, 2)
|
||||
deleteFeedItems(context!!, itemsToDelete)[TIMEOUT, TimeUnit.SECONDS]
|
||||
deleteFeedItems(context, itemsToDelete)[TIMEOUT, TimeUnit.SECONDS]
|
||||
|
||||
adapter = getInstance()
|
||||
adapter.open()
|
||||
@ -664,7 +664,7 @@ class DbWriterTest {
|
||||
adapter.setQueue(feed.items.toList())
|
||||
adapter.close()
|
||||
|
||||
removeQueueItem(context!!, false, item)[TIMEOUT, TimeUnit.SECONDS]
|
||||
removeQueueItem(context, false, item)[TIMEOUT, TimeUnit.SECONDS]
|
||||
adapter = getInstance()
|
||||
adapter.open()
|
||||
val queue = adapter.queueIDCursor
|
||||
@ -700,21 +700,21 @@ class DbWriterTest {
|
||||
// Use array rather than List to make codes more succinct
|
||||
val itemIds = toItemIds(feed.items).toTypedArray<Long>()
|
||||
|
||||
removeQueueItem(context!!, false,
|
||||
removeQueueItem(context, false,
|
||||
itemIds[1], itemIds[3])[TIMEOUT, TimeUnit.SECONDS]
|
||||
assertQueueByItemIds("Average case - 2 items removed successfully",
|
||||
itemIds[0], itemIds[2])
|
||||
|
||||
removeQueueItem(context!!, false)[TIMEOUT, TimeUnit.SECONDS]
|
||||
removeQueueItem(context, false)[TIMEOUT, TimeUnit.SECONDS]
|
||||
assertQueueByItemIds("Boundary case - no items supplied. queue should see no change",
|
||||
itemIds[0], itemIds[2])
|
||||
|
||||
removeQueueItem(context!!, false,
|
||||
removeQueueItem(context, false,
|
||||
itemIds[0], itemIds[4], -1L)[TIMEOUT, TimeUnit.SECONDS]
|
||||
assertQueueByItemIds("Boundary case - items not in queue ignored",
|
||||
itemIds[2])
|
||||
|
||||
removeQueueItem(context!!, false,
|
||||
removeQueueItem(context, false,
|
||||
itemIds[2], -1L)[TIMEOUT, TimeUnit.SECONDS]
|
||||
assertQueueByItemIds("Boundary case - invalid itemIds ignored") // the queue is empty
|
||||
}
|
||||
|
21
changelog.md
@ -92,9 +92,10 @@
|
||||
* 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
|
||||
|
||||
* https://github.com/XilinJia/Podcini/issues/20
|
||||
* 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
|
||||
|
||||
## 4.3.0
|
||||
|
||||
* added more info about feeds in the online search view
|
||||
@ -104,4 +105,16 @@
|
||||
* added swipe action telltales in all episode lists
|
||||
* added NO_ACTION swipe action
|
||||
* all default swipe actions are set to NO_ACTION
|
||||
* cleaned up swipe preferences ui: statistics removed
|
||||
* cleaned up swipe preferences ui: statistics removed
|
||||
|
||||
## 4.3.1
|
||||
|
||||
* titles of played episodes are made brighter
|
||||
* icons of played episodes are marked with a check
|
||||
* icons of swipe telltales are clickable for setting
|
||||
* Straightened up play speed setting
|
||||
* three places to set the play speed:
|
||||
* global setting at the preference
|
||||
* setting for a feed: either use global or customize
|
||||
* setting at the player: set for current playing and save for global
|
||||
* feed setting takes precedence when playing an episode
|
@ -4,5 +4,6 @@ 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
|
||||
* https://github.com/XilinJia/Podcini/issues/20
|
||||
* 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
|
||||
|
12
fastlane/metadata/android/en-US/changelogs/3020112.txt
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
Version 4.3.1 brings several changes:
|
||||
|
||||
* titles of played episodes are made brighter
|
||||
* icons of played episodes are marked with a check
|
||||
* icons of swipe telltales are clickable for setting
|
||||
* Straightened up play speed setting
|
||||
* three places to set the play speed:
|
||||
* global setting at the preference
|
||||
* setting for a feed: either use global or customize
|
||||
* setting at the player: set for current playing and save for global
|
||||
* feed setting takes precedence when playing an episode
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 148 KiB |