mirror of
https://github.com/XilinJia/Podcini.git
synced 2025-01-31 14:14:59 +01:00
6.0.6 commit
This commit is contained in:
parent
27f5f5e95a
commit
09328bf078
@ -125,8 +125,8 @@ android {
|
||||
buildConfig true
|
||||
}
|
||||
defaultConfig {
|
||||
versionCode 3020205
|
||||
versionName "6.0.5"
|
||||
versionCode 3020206
|
||||
versionName "6.0.6"
|
||||
|
||||
applicationId "ac.mdiq.podcini.R"
|
||||
def commit = ""
|
||||
@ -265,7 +265,7 @@ dependencies {
|
||||
testImplementation 'org.awaitility:awaitility:4.2.1'
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
||||
testImplementation 'org.robolectric:robolectric:4.12'
|
||||
testImplementation 'org.robolectric:robolectric:4.13'
|
||||
testImplementation 'javax.inject:javax.inject:1'
|
||||
|
||||
playImplementation 'com.google.android.gms:play-services-base:18.5.0'
|
||||
|
@ -11,8 +11,8 @@ import ac.mdiq.podcini.storage.database.Episodes.getEpisode
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Queues.clearQueue
|
||||
import ac.mdiq.podcini.storage.database.Queues.getInQueueEpisodeIds
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter.Companion.unfiltered
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter.Companion.unfiltered
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.test.podcini.service.playback
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerBase.MediaPlayerInfo
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerCallback
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.test.podcini.service.playback
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerBase.MediaPlayerInfo
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerCallback
|
||||
|
@ -5,7 +5,7 @@ import ac.mdiq.podcini.playback.base.MediaPlayerBase.MediaPlayerInfo
|
||||
import ac.mdiq.podcini.playback.base.PlayerStatus
|
||||
import ac.mdiq.podcini.playback.service.LocalMediaPlayer
|
||||
import ac.mdiq.podcini.storage.model.*
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import androidx.test.annotation.UiThreadTest
|
||||
import androidx.test.filters.MediumTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
|
@ -1,5 +1,8 @@
|
||||
package ac.mdiq.podcini.net.download
|
||||
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction.NEVER
|
||||
|
||||
/** Utility class for Download Errors. */
|
||||
/** Get machine-readable code. */
|
||||
enum class DownloadError(@JvmField val code: Int) {
|
||||
@ -31,10 +34,7 @@ enum class DownloadError(@JvmField val code: Int) {
|
||||
/** Return DownloadError from its associated code. */
|
||||
@JvmStatic
|
||||
fun fromCode(code: Int): DownloadError {
|
||||
for (reason in entries) {
|
||||
if (reason.code == code) return reason
|
||||
}
|
||||
throw IllegalArgumentException("unknown code: $code")
|
||||
return enumValues<DownloadError>().firstOrNull { it.code == code } ?: throw IllegalArgumentException("unknown code: $code")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import ac.mdiq.podcini.storage.database.LogsAndStats
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
||||
import ac.mdiq.podcini.storage.model.DownloadResult
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.ui.utils.NotificationUtils
|
||||
import ac.mdiq.podcini.util.config.ClientConfigurator
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
|
@ -15,7 +15,7 @@ import ac.mdiq.podcini.storage.model.DownloadResult
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.utils.FastDocumentFile
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.net.feed.parser
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding
|
||||
import ac.mdiq.podcini.storage.model.FeedFunding
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.net.feed.parser.element.SyndElement
|
||||
import ac.mdiq.podcini.net.feed.parser.namespace.Namespace
|
||||
|
@ -2,7 +2,7 @@ package ac.mdiq.podcini.net.feed.parser.media.id3
|
||||
|
||||
import android.util.Log
|
||||
import ac.mdiq.podcini.storage.model.Chapter
|
||||
import ac.mdiq.podcini.storage.utils.EmbeddedChapterImage.Companion.makeUrl
|
||||
import ac.mdiq.podcini.storage.model.EmbeddedChapterImage.Companion.makeUrl
|
||||
import ac.mdiq.podcini.net.feed.parser.media.id3.model.FrameHeader
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import org.apache.commons.io.input.CountingInputStream
|
||||
|
@ -8,7 +8,7 @@ import ac.mdiq.podcini.net.feed.parser.utils.MimeTypeUtils.getMimeType
|
||||
import ac.mdiq.podcini.net.feed.parser.utils.MimeTypeUtils.isMediaFile
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding
|
||||
import ac.mdiq.podcini.storage.model.FeedFunding
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import org.xml.sax.Attributes
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.net.feed.parser.namespace
|
||||
|
||||
import ac.mdiq.podcini.net.feed.parser.HandlerState
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding
|
||||
import ac.mdiq.podcini.storage.model.FeedFunding
|
||||
import ac.mdiq.podcini.net.feed.parser.element.SyndElement
|
||||
import org.xml.sax.Attributes
|
||||
|
||||
|
@ -28,9 +28,9 @@ import ac.mdiq.podcini.storage.database.Feeds.updateFeed
|
||||
import ac.mdiq.podcini.storage.database.Queues.removeFromQueue
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.utils.NotificationUtils
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.*
|
||||
|
@ -29,6 +29,8 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
*/
|
||||
val position: Int
|
||||
|
||||
var playedDuration: Int
|
||||
|
||||
/**
|
||||
* Returns the total length of the file in seconds.
|
||||
*
|
||||
@ -46,6 +48,7 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
this.timestamp = builder.timestamp
|
||||
this.started = builder.started
|
||||
this.position = builder.position
|
||||
this.playedDuration = builder.playedDuration
|
||||
this.playState = builder.playState
|
||||
this.isFavorite = builder.isFavorite
|
||||
this.total = builder.total
|
||||
@ -60,7 +63,7 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
if (o !is EpisodeAction) return false
|
||||
|
||||
val that = o
|
||||
return started == that.started && position == that.position && total == that.total && playState == that.playState && isFavorite == that.isFavorite && action != that.action && podcast == that.podcast && episode == that.episode && timestamp == that.timestamp && guid == that.guid
|
||||
return started == that.started && position == that.position && playedDuration == that.playedDuration && total == that.total && playState == that.playState && isFavorite == that.isFavorite && action != that.action && podcast == that.podcast && episode == that.episode && timestamp == that.timestamp && guid == that.guid
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@ -71,6 +74,7 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
result = 31 * result + (timestamp?.hashCode() ?: 0)
|
||||
result = 31 * result + started
|
||||
result = 31 * result + position
|
||||
result = 31 * result + playedDuration
|
||||
result = 31 * result + playState
|
||||
result = 31 * result + total
|
||||
return result
|
||||
@ -94,6 +98,7 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
if (this.action == Action.PLAY) {
|
||||
obj.put("started", this.started)
|
||||
obj.put("position", this.position)
|
||||
obj.put("playedDuration", this.playedDuration)
|
||||
obj.put("playState", this.playState)
|
||||
obj.put("total", this.total)
|
||||
obj.put("isFavorite", this.isFavorite)
|
||||
@ -119,6 +124,7 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
var timestamp: Date? = null
|
||||
var started: Int = -1
|
||||
var position: Int = -1
|
||||
var playedDuration: Int = -1
|
||||
var total: Int = -1
|
||||
var playState: Int = 0
|
||||
var isFavorite: Boolean = false
|
||||
@ -152,6 +158,11 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
return this
|
||||
}
|
||||
|
||||
fun playedDuration(seconds: Int): Builder {
|
||||
if (action == Action.PLAY) this.playedDuration = seconds
|
||||
return this
|
||||
}
|
||||
|
||||
fun total(seconds: Int): Builder {
|
||||
if (action == Action.PLAY) this.total = seconds
|
||||
return this
|
||||
@ -217,11 +228,12 @@ class EpisodeAction private constructor(builder: Builder) {
|
||||
if (action == Action.PLAY) {
|
||||
val started = `object`.optInt("started", -1)
|
||||
val position = `object`.optInt("position", -1)
|
||||
val playedDuration = `object`.optInt("playedDuration", -1)
|
||||
val total = `object`.optInt("total", -1)
|
||||
val playState = `object`.optInt("playState", 0)
|
||||
val isFavorite = `object`.optBoolean("isFavorite", false)
|
||||
builder.playState(playState).isFavorite(isFavorite)
|
||||
if (started >= 0 && position > 0 && total > 0) builder.started(started).position(position).total(total)
|
||||
if (started >= 0 && position >= 0 && playedDuration >= 0 && total > 0) builder.started(started).position(position).playedDuration(playedDuration).total(total)
|
||||
}
|
||||
return builder.build()
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ import ac.mdiq.podcini.storage.database.Episodes.getEpisodeByGuidOrUrl
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Episodes.persistEpisode
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
@ -256,8 +256,9 @@ import kotlin.math.min
|
||||
val media = item.media ?: continue
|
||||
val played = EpisodeAction.Builder(item, EpisodeAction.PLAY)
|
||||
.timestamp(Date(media.getLastPlayedTime()))
|
||||
.started(media.getPosition() / 1000)
|
||||
.started(media.startPosition / 1000)
|
||||
.position(media.getPosition() / 1000)
|
||||
.playedDuration(media.playedDuration / 1000)
|
||||
.total(media.getDuration() / 1000)
|
||||
.isFavorite(item.isFavorite)
|
||||
.playState(item.playState)
|
||||
@ -327,7 +328,9 @@ import kotlin.math.min
|
||||
var idRemove: Long? = null
|
||||
Logd(TAG, "processEpisodeAction ${feedItem.media!!.getLastPlayedTime()} ${(action.timestamp?.time?:0L)} ${action.position} ${feedItem.title}")
|
||||
if (feedItem.media!!.getLastPlayedTime() < (action.timestamp?.time?:0L)) {
|
||||
feedItem.media!!.startPosition = action.started * 1000
|
||||
feedItem.media!!.setPosition(action.position * 1000)
|
||||
feedItem.media!!.playedDuration = action.playedDuration * 1000
|
||||
feedItem.media!!.setLastPlayedTime(action.timestamp!!.time)
|
||||
feedItem.isFavorite = action.isFavorite
|
||||
feedItem.playState = action.playState
|
||||
|
@ -13,7 +13,7 @@ import ac.mdiq.podcini.playback.service.PlaybackService.Companion.isRunning
|
||||
import ac.mdiq.podcini.playback.service.PlaybackService.LocalBinder
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.isSkipSilence
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.ui.activity.starter.MainActivityStarter
|
||||
import ac.mdiq.podcini.ui.activity.starter.VideoPlayerActivityStarter
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
|
@ -6,7 +6,7 @@ import ac.mdiq.podcini.preferences.UserPreferences
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.media.AudioManager
|
||||
|
@ -2,7 +2,7 @@ package ac.mdiq.podcini.playback.base
|
||||
|
||||
import ac.mdiq.podcini.playback.base.MediaPlayerBase.MediaPlayerInfo
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
|
||||
interface MediaPlayerCallback {
|
||||
fun statusChanged(newInfo: MediaPlayerInfo?)
|
||||
|
@ -13,7 +13,7 @@ import ac.mdiq.podcini.preferences.UserPreferences
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.config.ClientConfig
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
|
@ -57,8 +57,8 @@ import ac.mdiq.podcini.storage.model.FeedPreferences
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.ui.utils.NotificationUtils
|
||||
import ac.mdiq.podcini.ui.widget.WidgetUpdater.WidgetState
|
||||
import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast
|
||||
@ -318,7 +318,7 @@ class PlaybackService : MediaSessionService() {
|
||||
Logd(TAG, "onPostPlayback ended: $ended smartMarkAsPlayed: $smartMarkAsPlayed autoSkipped: $autoSkipped skipped: $skipped")
|
||||
// only mark the item as played if we're not keeping it anyways
|
||||
item = setPlayStateSync(Episode.PLAYED, ended || (skipped && smartMarkAsPlayed), item!!)
|
||||
val action = item?.feed?.preferences?.currentAutoDelete
|
||||
val action = item?.feed?.preferences?.autoDeleteAction
|
||||
val shouldAutoDelete = (action == AutoDeleteAction.ALWAYS ||
|
||||
(action == AutoDeleteAction.GLOBAL && item?.feed != null && shouldAutoDeleteItem(item!!.feed!!)))
|
||||
if (playable is EpisodeMedia && shouldAutoDelete && (item?.isFavorite != true || !shouldFavoriteKeepEpisode())) {
|
||||
|
@ -2,8 +2,8 @@ package ac.mdiq.podcini.preferences
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.ProxyConfig
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
@ -17,9 +17,9 @@ import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.preferences.OpmlTransporter.*
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.activity.OpmlImportActivity
|
||||
import ac.mdiq.podcini.ui.activity.PreferenceActivity
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
@ -34,7 +34,6 @@ import android.os.Bundle
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.text.format.Formatter
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@ -281,7 +280,7 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||
builder.setNegativeButton(R.string.no, null)
|
||||
builder.setPositiveButton(R.string.confirm_label) { _: DialogInterface?, _: Int ->
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||
intent.setType("application/octet-stream")
|
||||
intent.setType("*/*")
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
restoreProgressLauncher.launch(intent)
|
||||
}
|
||||
@ -711,7 +710,9 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||
return null
|
||||
}
|
||||
var idRemove = 0L
|
||||
feedItem.media!!.startPosition = action.started * 1000
|
||||
feedItem.media!!.setPosition(action.position * 1000)
|
||||
feedItem.media!!.playedDuration = action.playedDuration * 1000
|
||||
feedItem.media!!.setLastPlayedTime(action.timestamp!!.time)
|
||||
feedItem.isFavorite = action.isFavorite
|
||||
feedItem.playState = action.playState
|
||||
@ -743,8 +744,9 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||
val media = item.media ?: continue
|
||||
val played = EpisodeAction.Builder(item, EpisodeAction.PLAY)
|
||||
.timestamp(Date(media.getLastPlayedTime()))
|
||||
.started(media.getPosition() / 1000)
|
||||
.started(media.startPosition / 1000)
|
||||
.position(media.getPosition() / 1000)
|
||||
.playedDuration(media.playedDuration / 1000)
|
||||
.total(media.getDuration() / 1000)
|
||||
.isFavorite(item.isFavorite)
|
||||
.playState(item.playState)
|
||||
|
@ -9,8 +9,8 @@ import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodesCount
|
||||
import ac.mdiq.podcini.storage.database.Queues.getInQueueEpisodeIds
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.annotation.OptIn
|
||||
|
@ -11,8 +11,8 @@ import ac.mdiq.podcini.preferences.UserPreferences.isEnableAutodownloadOnBattery
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodesCount
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@ -86,7 +86,7 @@ object AutoDownloads {
|
||||
candidates.addAll(queue)
|
||||
for (newItem in newItems) {
|
||||
val feedPrefs = newItem.feed!!.preferences
|
||||
if (feedPrefs!!.autoDownload && !candidates.contains(newItem) && feedPrefs.filter.shouldAutoDownload(newItem)) candidates.add(newItem)
|
||||
if (feedPrefs!!.autoDownload && !candidates.contains(newItem) && feedPrefs.autoDownloadFilter.shouldAutoDownload(newItem)) candidates.add(newItem)
|
||||
}
|
||||
// filter items that are not auto downloadable
|
||||
val it = candidates.iterator()
|
||||
|
@ -19,8 +19,8 @@ import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.util.IntentUtils.sendLocalBroadcast
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ac.mdiq.podcini.storage.database
|
||||
|
||||
import ac.mdiq.podcini.BuildConfig
|
||||
import ac.mdiq.podcini.net.download.DownloadError
|
||||
import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
||||
import ac.mdiq.podcini.net.sync.queue.SynchronizationQueueSink
|
||||
@ -13,7 +14,7 @@ import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||
import ac.mdiq.podcini.storage.model.*
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.Companion.TAG_ROOT
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
@ -164,7 +165,11 @@ object Feeds {
|
||||
}
|
||||
|
||||
fun getFeed(feedId: Long, copy: Boolean = false, fromDB: Boolean = true): Feed? {
|
||||
Logd(TAG, "getFeed called fromDB: $fromDB")
|
||||
if (BuildConfig.DEBUG) {
|
||||
val stackTrace = Thread.currentThread().stackTrace
|
||||
val caller = if (stackTrace.size > 3) stackTrace[3] else null
|
||||
Logd(TAG, "${caller?.className}.${caller?.methodName} getFeed called fromDB: $fromDB")
|
||||
}
|
||||
val f = if (fromDB) realm.query(Feed::class, "id == $feedId").first().find() else feedMap[feedId]
|
||||
return if (f != null) {
|
||||
if (copy) realm.copyFromRealm(f)
|
||||
|
@ -17,7 +17,7 @@ import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.PlayQueue
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
|
@ -18,7 +18,7 @@ import kotlin.coroutines.ContinuationInterceptor
|
||||
object RealmDB {
|
||||
private val TAG: String = RealmDB::class.simpleName ?: "Anonymous"
|
||||
|
||||
private const val SCHEMA_VERSION_NUMBER = 6L
|
||||
private const val SCHEMA_VERSION_NUMBER = 7L
|
||||
|
||||
private val ioScope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class EmbeddedChapterImage(@JvmField val media: Playable, private val imageUrl: String) {
|
@ -241,10 +241,10 @@ class Episode : RealmObject {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
}
|
||||
|
||||
override fun equals(o: Any?): Boolean {
|
||||
if (this === o) return true
|
||||
if (o !is Episode) return false
|
||||
return id == o.id
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Episode) return false
|
||||
return id == other.id
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.curQueue
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import java.io.Serializable
|
||||
|
||||
class EpisodeFilter(vararg properties: String) : Serializable {
|
@ -2,7 +2,6 @@ package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||
import ac.mdiq.podcini.storage.utils.MediaMetadataRetrieverCompat
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
@ -64,7 +63,6 @@ class EpisodeMedia: EmbeddedRealmObject, Playable {
|
||||
}
|
||||
|
||||
var startPosition: Int = -1
|
||||
private set
|
||||
|
||||
var playedDurationWhenStarted: Int = 0
|
||||
private set
|
||||
@ -343,10 +341,10 @@ class EpisodeMedia: EmbeddedRealmObject, Playable {
|
||||
upsertBlk(episode!!) {}
|
||||
}
|
||||
|
||||
override fun equals(o: Any?): Boolean {
|
||||
if (o == null) return false
|
||||
if (o is RemoteMedia) return o == this
|
||||
return super.equals(o)
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (other is RemoteMedia) return other == this
|
||||
return super.equals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
|
@ -1,11 +1,7 @@
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding.Companion.extractPaymentLinks
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder.Companion.fromCode
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.FeedFunding.Companion.extractPaymentLinks
|
||||
import ac.mdiq.podcini.storage.model.SortOrder.Companion.fromCode
|
||||
import io.realm.kotlin.ext.realmListOf
|
||||
import io.realm.kotlin.types.RealmList
|
||||
import io.realm.kotlin.types.RealmObject
|
||||
@ -178,11 +174,9 @@ class Feed : RealmObject {
|
||||
this.identifier = feedIdentifier
|
||||
this.imageUrl = imageUrl
|
||||
this.isPaged = false
|
||||
this.nextPageLink = nextPageLink
|
||||
this.preferences?.filterString = ""
|
||||
this.sortOrder = sortOrder
|
||||
this.preferences?.sortOrderCode = sortOrder?.code ?: 0
|
||||
this.lastUpdateFailed = lastUpdateFailed
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
@ -10,7 +9,7 @@ import java.util.regex.Pattern
|
||||
// (we don't have to recreate it)
|
||||
// 2. We don't know if we'll actually be asked to parse anything anyways.
|
||||
|
||||
class FeedEpisodesFilter(val includeFilterRaw: String? = "", val excludeFilterRaw: String? = "", val minimalDurationFilter: Int = -1) : Serializable {
|
||||
class FeedAutoDownloadFilter(val includeFilterRaw: String? = "", val excludeFilterRaw: String? = "", val minimalDurationFilter: Int = -1) : Serializable {
|
||||
|
||||
/**
|
||||
* Parses the text in to a list of single words or quoted strings.
|
@ -1,4 +1,4 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
@ -11,9 +11,9 @@ class FeedFunding(@JvmField var url: String?, @JvmField var content: String?) {
|
||||
this.url = url
|
||||
}
|
||||
|
||||
override fun equals(obj: Any?): Boolean {
|
||||
if (obj == null || obj.javaClass != this.javaClass) return false
|
||||
val funding = obj as FeedFunding
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != this.javaClass) return false
|
||||
val funding = other as FeedFunding
|
||||
if (url == null && funding.url == null && content == null && funding.content == null) return true
|
||||
if (url != null && url == funding.url && content != null && content == funding.content) return true
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.FeedEpisodesFilter
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting.Companion.fromInteger
|
||||
import io.realm.kotlin.ext.realmSetOf
|
||||
import io.realm.kotlin.types.EmbeddedRealmObject
|
||||
import io.realm.kotlin.types.RealmSet
|
||||
@ -11,24 +10,42 @@ import io.realm.kotlin.types.annotations.Index
|
||||
/**
|
||||
* Contains preferences for a single feed.
|
||||
*/
|
||||
class FeedPreferences(@Index var feedID: Long,
|
||||
var autoDownload: Boolean,
|
||||
class FeedPreferences : EmbeddedRealmObject {
|
||||
|
||||
@Index var feedID: Long = 0L
|
||||
|
||||
var autoDownload: Boolean = false
|
||||
|
||||
/**
|
||||
* @return true if this feed should be refreshed when everything else is being refreshed
|
||||
* if false the feed should only be refreshed if requested directly.
|
||||
*/
|
||||
var keepUpdated: Boolean,
|
||||
@Ignore var currentAutoDelete: AutoDeleteAction,
|
||||
@Ignore @JvmField var volumeAdaptionSetting: VolumeAdaptionSetting?,
|
||||
var username: String?,
|
||||
var password: String?,
|
||||
@Ignore @JvmField var filter: FeedEpisodesFilter,
|
||||
var playSpeed: Float,
|
||||
var introSkip: Int,
|
||||
var endingSkip: Int,
|
||||
tags: RealmSet<String>) : EmbeddedRealmObject {
|
||||
var keepUpdated: Boolean = true
|
||||
|
||||
var username: String? = null
|
||||
var password: String? = null
|
||||
|
||||
var playSpeed: Float = SPEED_USE_GLOBAL
|
||||
|
||||
var introSkip: Int = 0
|
||||
var endingSkip: Int = 0
|
||||
|
||||
@Ignore
|
||||
var autoDeleteAction: AutoDeleteAction = AutoDeleteAction.GLOBAL
|
||||
get() = AutoDeleteAction.fromCode(autoDelete)
|
||||
set(value) {
|
||||
field = value
|
||||
autoDelete = field.code
|
||||
}
|
||||
var autoDelete: Int = 0
|
||||
|
||||
@Ignore
|
||||
var volumeAdaptionSetting: VolumeAdaptionSetting = VolumeAdaptionSetting.OFF
|
||||
get() = fromInteger(volumeAdaption)
|
||||
set(value) {
|
||||
field = value
|
||||
volumeAdaption = field.toInteger()
|
||||
}
|
||||
var volumeAdaption: Int = 0
|
||||
|
||||
var tags: RealmSet<String> = realmSetOf()
|
||||
@ -37,9 +54,19 @@ class FeedPreferences(@Index var feedID: Long,
|
||||
val tagsAsString: String
|
||||
get() = tags.joinToString(TAG_SEPARATOR)
|
||||
|
||||
/**
|
||||
* Contains property strings. If such a property applies to a feed item, it is not shown in the feed list
|
||||
*/
|
||||
@Ignore
|
||||
var autoDownloadFilter: FeedAutoDownloadFilter = FeedAutoDownloadFilter()
|
||||
get() = FeedAutoDownloadFilter(autoDLInclude, autoDLExclude, autoDLMinDuration)
|
||||
set(value) {
|
||||
field = value
|
||||
autoDLInclude = field.includeFilterRaw
|
||||
autoDLExclude = field.excludeFilterRaw
|
||||
autoDLMinDuration = field.minimalDurationFilter
|
||||
}
|
||||
var autoDLInclude: String? = ""
|
||||
var autoDLExclude: String? = ""
|
||||
var autoDLMinDuration: Int = -1
|
||||
|
||||
var filterString: String = ""
|
||||
|
||||
var sortOrderCode: Int = 0
|
||||
@ -52,41 +79,34 @@ class FeedPreferences(@Index var feedID: Long,
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun fromCode(code: Int): AutoDeleteAction {
|
||||
for (action in entries) {
|
||||
if (code == action.code) return action
|
||||
}
|
||||
return NEVER
|
||||
return enumValues<AutoDeleteAction>().firstOrNull { it.code == code } ?: NEVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() : this(0L, false, true, AutoDeleteAction.GLOBAL, VolumeAdaptionSetting.OFF, null, null,
|
||||
FeedEpisodesFilter(), SPEED_USE_GLOBAL, 0, 0, realmSetOf())
|
||||
constructor() {}
|
||||
|
||||
constructor(feedID: Long, autoDownload: Boolean, autoDeleteAction: AutoDeleteAction,
|
||||
volumeAdaptionSetting: VolumeAdaptionSetting?, username: String?, password: String?)
|
||||
: this(feedID, autoDownload, true, autoDeleteAction, volumeAdaptionSetting, username, password,
|
||||
FeedEpisodesFilter(), SPEED_USE_GLOBAL, 0, 0, realmSetOf()) {
|
||||
|
||||
volumeAdaptionSetting: VolumeAdaptionSetting?, username: String?, password: String?) {
|
||||
this.feedID = feedID
|
||||
this.autoDownload = autoDownload
|
||||
this.autoDeleteAction = autoDeleteAction
|
||||
if (volumeAdaptionSetting != null) this.volumeAdaptionSetting = volumeAdaptionSetting
|
||||
this.username = username
|
||||
this.password = password
|
||||
this.autoDelete = autoDeleteAction.code
|
||||
this.volumeAdaption = volumeAdaptionSetting?.toInteger() ?: 0
|
||||
}
|
||||
|
||||
init {
|
||||
this.tags.addAll(tags!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the
|
||||
* comparison.
|
||||
*
|
||||
* @return True if the two objects are different.
|
||||
*/
|
||||
fun compareWithOther(other: FeedPreferences?): Boolean {
|
||||
if (other == null) return true
|
||||
if (username != other.username) return true
|
||||
if (password != other.password) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -100,10 +120,6 @@ class FeedPreferences(@Index var feedID: Long,
|
||||
this.password = other.password
|
||||
}
|
||||
|
||||
fun getTags(): MutableSet<String> {
|
||||
return tags
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SPEED_USE_GLOBAL: Float = -1f
|
||||
const val TAG_ROOT: String = "#root"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
enum class MediaType {
|
||||
AUDIO, VIDEO, FLASH, UNKNOWN;
|
@ -1,6 +1,5 @@
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import android.content.Context
|
||||
import android.os.Parcelable
|
||||
import java.io.Serializable
|
||||
@ -65,9 +64,6 @@ interface Playable : Parcelable, Serializable {
|
||||
* Returns last time (in ms) when this playable was played or 0
|
||||
* if last played time is unknown.
|
||||
*/
|
||||
/**
|
||||
* @param lastPlayedTime timestamp in ms
|
||||
*/
|
||||
fun getLastPlayedTime(): Long
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
@ -1,4 +1,4 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
/**
|
||||
* Provides sort orders to sort a list of episodes.
|
||||
@ -56,11 +56,7 @@ enum class SortOrder(@JvmField val code: Int, @JvmField val scope: Scope) {
|
||||
|
||||
@JvmStatic
|
||||
fun fromCode(code: Int): SortOrder? {
|
||||
for (sortOrder in entries) {
|
||||
if (sortOrder.code == code) return sortOrder
|
||||
}
|
||||
return null
|
||||
// throw IllegalArgumentException("Unsupported code: $code")
|
||||
return enumValues<SortOrder>().firstOrNull { it.code == code }
|
||||
}
|
||||
|
||||
@JvmStatic
|
@ -1,4 +1,4 @@
|
||||
package ac.mdiq.podcini.storage.utils
|
||||
package ac.mdiq.podcini.storage.model
|
||||
|
||||
enum class VolumeAdaptionSetting(private val value: Int, @JvmField val adaptionFactor: Float) {
|
||||
OFF(0, 1.0f),
|
||||
@ -15,10 +15,7 @@ enum class VolumeAdaptionSetting(private val value: Int, @JvmField val adaptionF
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun fromInteger(value: Int): VolumeAdaptionSetting {
|
||||
for (setting in entries) {
|
||||
if (setting.value == value) return setting
|
||||
}
|
||||
throw IllegalArgumentException("Cannot map value to VolumeAdaptionSetting: $value")
|
||||
return enumValues<VolumeAdaptionSetting>().firstOrNull { it.value == value } ?: throw IllegalArgumentException("Cannot map value to VolumeAdaptionSetting: $value")
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import android.provider.DocumentsContract
|
||||
* This queries the ContentResolver a single time with all the information.
|
||||
*/
|
||||
class FastDocumentFile(val name: String, val type: String, val uri: Uri, val length: Long, val lastModified: Long) {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun list(context: Context, folderUri: Uri?): List<FastDocumentFile> {
|
||||
|
@ -7,11 +7,11 @@ import ac.mdiq.podcini.preferences.UserPreferences
|
||||
* Utility functions for handling storage errors
|
||||
*/
|
||||
object StorageUtils {
|
||||
@JvmStatic
|
||||
val freeSpaceAvailable: Long
|
||||
/**
|
||||
* Get the number of free bytes that are available on the external storage.
|
||||
*/
|
||||
@JvmStatic
|
||||
val freeSpaceAvailable: Long
|
||||
get() {
|
||||
val dataFolder = UserPreferences.getDataFolder(null)
|
||||
return if (dataFolder != null) getFreeSpaceAvailable(dataFolder.absolutePath) else 0
|
||||
|
@ -3,11 +3,8 @@ package ac.mdiq.podcini.ui.actions.actionbutton
|
||||
import ac.mdiq.podcini.net.download.serviceinterface.DownloadServiceInterface
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.isStreamOverDownload
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.isCurrentlyPlaying
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.curMedia
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
|
@ -8,7 +8,7 @@ import ac.mdiq.podcini.playback.base.InTheatre
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
|
@ -6,7 +6,7 @@ import ac.mdiq.podcini.playback.PlaybackController.Companion.playbackService
|
||||
import ac.mdiq.podcini.playback.PlaybackServiceStarter
|
||||
import ac.mdiq.podcini.playback.base.InTheatre
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
|
@ -6,7 +6,7 @@ import ac.mdiq.podcini.preferences.UsageStatistics
|
||||
import ac.mdiq.podcini.preferences.UsageStatistics.logAction
|
||||
import ac.mdiq.podcini.preferences.UserPreferences.isAllowMobileStreaming
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.model.RemoteMedia
|
||||
import ac.mdiq.podcini.net.utils.NetworkUtils.isStreamingAllowed
|
||||
|
@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.database.Queues.addToQueue
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
|
||||
|
@ -6,7 +6,7 @@ import androidx.media3.common.util.UnstableApi
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.database.Episodes.deleteMediaOfEpisode
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.ui.utils.LocalDeleteModal.showLocalFeedDeleteWarningIfNecessary
|
||||
|
||||
class DeleteSwipeAction : SwipeAction {
|
||||
|
@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.database.Episodes.setFavorite
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
|
||||
|
@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
|
||||
class NoActionSwipeAction : SwipeAction {
|
||||
override fun getId(): String {
|
||||
|
@ -3,7 +3,7 @@ package ac.mdiq.podcini.ui.actions.swipeactions
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.database.Episodes.addToHistory
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import android.content.Context
|
||||
import androidx.annotation.OptIn
|
||||
|
@ -7,7 +7,7 @@ import ac.mdiq.podcini.storage.database.Queues.removeFromQueue
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.util.event.EventFlow
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
|
@ -4,7 +4,7 @@ import android.content.Context
|
||||
import androidx.fragment.app.Fragment
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
|
||||
class ShowFirstSwipeDialogAction : SwipeAction {
|
||||
override fun getId(): String {
|
||||
|
@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.ui.actions.actionbutton.DownloadActionButton
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
|
||||
class StartDownloadSwipeAction : SwipeAction {
|
||||
override fun getId(): String {
|
||||
|
@ -5,7 +5,7 @@ import androidx.annotation.AttrRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
|
||||
|
||||
interface SwipeAction {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.ui.actions.swipeactions
|
||||
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.ui.actions.swipeactions.SwipeAction.Companion.NO_ACTION
|
||||
import ac.mdiq.podcini.ui.dialog.SwipeActionsDialog
|
||||
import ac.mdiq.podcini.ui.fragment.AllEpisodesFragment
|
||||
|
@ -11,7 +11,7 @@ import ac.mdiq.podcini.storage.database.Episodes.setPlayStateSync
|
||||
import ac.mdiq.podcini.storage.database.Queues.removeFromQueueSync
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
|
@ -89,6 +89,7 @@ abstract class DatesFilterDialog(private val context: Context, oldestDate: Long)
|
||||
builder.setPositiveButton(android.R.string.ok) { dialog: DialogInterface?, which: Int ->
|
||||
includeMarkedAsPlayed = binding.includeMarkedCheckbox.isChecked
|
||||
if (includeMarkedAsPlayed) {
|
||||
// TODO: what can be done with this?
|
||||
// We do not know the date at which something was marked as played, so filtering does not make sense
|
||||
timeFilterFrom = 0
|
||||
timeFilterTo = Long.MAX_VALUE
|
||||
|
@ -3,7 +3,7 @@ package ac.mdiq.podcini.ui.dialog
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.FilterDialogBinding
|
||||
import ac.mdiq.podcini.databinding.FilterDialogRowBinding
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
|
@ -4,7 +4,7 @@ import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.SortDialogBinding
|
||||
import ac.mdiq.podcini.databinding.SortDialogItemActiveBinding
|
||||
import ac.mdiq.podcini.databinding.SortDialogItemBinding
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
|
@ -15,7 +15,7 @@ import ac.mdiq.podcini.preferences.UserPreferences.videoPlaybackSpeed
|
||||
import ac.mdiq.podcini.storage.database.Feeds.persistFeedPreferences
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.ui.utils.ItemOffsetDecoration
|
||||
import ac.mdiq.podcini.ui.view.PlaybackSpeedSeekBar
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
|
@ -7,7 +7,7 @@ import ac.mdiq.podcini.net.feed.discovery.*
|
||||
import ac.mdiq.podcini.net.feed.FeedUpdateManager
|
||||
import ac.mdiq.podcini.storage.database.Feeds.updateFeed
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.activity.OpmlImportActivity
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
|
@ -6,8 +6,8 @@ import ac.mdiq.podcini.preferences.UserPreferences.prefFilterAllEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodesCount
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.dialog.EpisodeFilterDialog
|
||||
import ac.mdiq.podcini.ui.dialog.EpisodeSortDialog
|
||||
|
@ -28,7 +28,7 @@ import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.ChapterUtils
|
||||
import ac.mdiq.podcini.storage.utils.ImageResourceUtils
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.activity.VideoplayerActivity.Companion.videoMode
|
||||
|
@ -7,7 +7,7 @@ import ac.mdiq.podcini.net.feed.FeedUpdateManager
|
||||
import ac.mdiq.podcini.playback.base.InTheatre.isCurMedia
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.ui.actions.EpisodeMultiSelectHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.MenuItemUtils
|
||||
|
@ -14,7 +14,7 @@ import ac.mdiq.podcini.playback.base.InTheatre.curMedia
|
||||
import ac.mdiq.podcini.playback.PlaybackController.Companion.curPosition
|
||||
import ac.mdiq.podcini.playback.PlaybackController.Companion.seekTo
|
||||
import ac.mdiq.podcini.storage.model.Chapter
|
||||
import ac.mdiq.podcini.storage.utils.EmbeddedChapterImage
|
||||
import ac.mdiq.podcini.storage.model.EmbeddedChapterImage
|
||||
import ac.mdiq.podcini.ui.view.CircularProgressBar
|
||||
import ac.mdiq.podcini.util.Converter.getDurationStringLocalized
|
||||
import ac.mdiq.podcini.util.Converter.getDurationStringLong
|
||||
|
@ -11,9 +11,9 @@ import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.actions.EpisodeMultiSelectHandler
|
||||
import ac.mdiq.podcini.ui.actions.actionbutton.DeleteActionButton
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
|
@ -15,7 +15,7 @@ import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.ui.actions.actionbutton.*
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
|
@ -18,10 +18,10 @@ import ac.mdiq.podcini.storage.model.DownloadResult
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder.Companion.fromCode
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder.Companion.fromCode
|
||||
import ac.mdiq.podcini.ui.actions.EpisodeMultiSelectHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.MenuItemUtils
|
||||
|
@ -9,7 +9,7 @@ import ac.mdiq.podcini.net.utils.HtmlToPlainText
|
||||
import ac.mdiq.podcini.storage.database.Feeds.updateFeed
|
||||
import ac.mdiq.podcini.storage.database.Feeds.updateFeedDownloadURL
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.FeedFunding
|
||||
import ac.mdiq.podcini.storage.model.FeedFunding
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.statistics.FeedStatisticsFragment
|
||||
import ac.mdiq.podcini.ui.statistics.StatisticsFragment
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.ui.fragment
|
||||
|
||||
import ac.mdiq.podcini.R
|
||||
import ac.mdiq.podcini.databinding.EpisodeFilterDialogBinding
|
||||
import ac.mdiq.podcini.databinding.AutodownloadFilterDialogBinding
|
||||
import ac.mdiq.podcini.databinding.FeedPrefSkipDialogBinding
|
||||
import ac.mdiq.podcini.databinding.FeedsettingsBinding
|
||||
import ac.mdiq.podcini.databinding.PlaybackSpeedFeedSettingDialogBinding
|
||||
@ -12,8 +12,8 @@ import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences.AutoDeleteAction
|
||||
import ac.mdiq.podcini.storage.utils.FeedEpisodesFilter
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.FeedAutoDownloadFilter
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.ui.adapter.SimpleChipAdapter
|
||||
import ac.mdiq.podcini.ui.dialog.AuthenticationDialog
|
||||
import ac.mdiq.podcini.ui.dialog.TagSettingsDialog
|
||||
@ -72,7 +72,6 @@ class FeedSettingsFragment : Fragment() {
|
||||
class FeedSettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
private var feed: Feed? = null
|
||||
private var feedPrefs: FeedPreferences? = null
|
||||
|
||||
private var notificationPermissionDenied: Boolean = false
|
||||
private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
|
||||
if (isGranted) return@registerForActivityResult
|
||||
@ -95,34 +94,29 @@ class FeedSettingsFragment : Fragment() {
|
||||
view.layoutAnimation = null
|
||||
return view
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class) override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.feed_settings)
|
||||
// To prevent displaying partially loaded data
|
||||
findPreference<Preference>(PREF_SCREEN)!!.isVisible = false
|
||||
|
||||
if (feed != null) {
|
||||
if (feed!!.preferences == null) {
|
||||
feed!!.preferences = FeedPreferences(feed!!.id, false, AutoDeleteAction.GLOBAL, VolumeAdaptionSetting.OFF, "", "")
|
||||
persistFeedPreferences(feed!!)
|
||||
}
|
||||
feedPrefs = feed!!.preferences
|
||||
|
||||
setupAutoDownloadGlobalPreference()
|
||||
setupAutoDownloadPreference()
|
||||
setupKeepUpdatedPreference()
|
||||
setupAutoDeletePreference()
|
||||
setupVolumeAdaptationPreferences()
|
||||
setupAuthentificationPreference()
|
||||
setupEpisodeFilterPreference()
|
||||
setupAutoDownloadFilterPreference()
|
||||
setupPlaybackSpeedPreference()
|
||||
setupFeedAutoSkipPreference()
|
||||
setupTags()
|
||||
|
||||
updateAutoDeleteSummary()
|
||||
updateVolumeAdaptationValue()
|
||||
updateAutoDownloadEnabled()
|
||||
|
||||
if (feed!!.isLocalFeed) {
|
||||
findPreference<Preference>(PREF_AUTHENTICATION)!!.isVisible = false
|
||||
findPreference<Preference>(PREF_CATEGORY_AUTO_DOWNLOAD)!!.isVisible = false
|
||||
@ -130,23 +124,21 @@ class FeedSettingsFragment : Fragment() {
|
||||
findPreference<Preference>(PREF_SCREEN)!!.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFeedAutoSkipPreference() {
|
||||
if (feedPrefs == null) return
|
||||
findPreference<Preference>(PREF_AUTO_SKIP)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (feedPrefs != null) {
|
||||
object : FeedPreferenceSkipDialog(requireContext(), feedPrefs!!.introSkip, feedPrefs!!.endingSkip) {
|
||||
@UnstableApi override fun onConfirmed(skipIntro: Int, skipEnding: Int) {
|
||||
@UnstableApi
|
||||
override fun onConfirmed(skipIntro: Int, skipEnding: Int) {
|
||||
feedPrefs!!.introSkip = skipIntro
|
||||
feedPrefs!!.endingSkip = skipEnding
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
// EventFlow.postEvent(FlowEvent.SkipIntroEndingChangedEvent(feedPrefs!!.introSkip, feedPrefs!!.endingSkip, feed!!.id))
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@UnstableApi private fun setupPlaybackSpeedPreference() {
|
||||
val feedPlaybackSpeedPreference = findPreference<Preference>(PREF_FEED_PLAYBACK_SPEED)
|
||||
feedPlaybackSpeedPreference!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
@ -173,8 +165,6 @@ class FeedSettingsFragment : Fragment() {
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.playSpeed = newSpeed
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
// EventFlow.postEvent(FlowEvent.FeedPrefsChangeEvent(feedPrefs!!))
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.cancel_label, null)
|
||||
@ -182,64 +172,59 @@ class FeedSettingsFragment : Fragment() {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEpisodeFilterPreference() {
|
||||
if (feedPrefs == null) return
|
||||
private fun setupAutoDownloadFilterPreference() {
|
||||
findPreference<Preference>(PREF_EPISODE_FILTER)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
object : EpisodeFilterPrefDialog(requireContext(), feedPrefs!!.filter) {
|
||||
@UnstableApi override fun onConfirmed(filter: FeedEpisodesFilter) {
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.filter = filter
|
||||
object : AutoDownloadFilterPrefDialog(requireContext(), feedPrefs!!.autoDownloadFilter) {
|
||||
@UnstableApi
|
||||
override fun onConfirmed(filter: FeedAutoDownloadFilter) {
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.autoDownloadFilter = filter
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAuthentificationPreference() {
|
||||
if (feedPrefs == null) return
|
||||
findPreference<Preference>(PREF_AUTHENTICATION)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (feedPrefs != null) {
|
||||
object : AuthenticationDialog(requireContext(), R.string.authentication_label, true, feedPrefs!!.username, feedPrefs!!.password) {
|
||||
@UnstableApi override fun onConfirmed(username: String, password: String) {
|
||||
@UnstableApi
|
||||
override fun onConfirmed(username: String, password: String) {
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.username = username
|
||||
feedPrefs!!.password = password
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
Thread({ runOnce(context, feed) }, "RefreshAfterCredentialChange").start()
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@UnstableApi private fun setupAutoDeletePreference() {
|
||||
if (feedPrefs == null) return
|
||||
findPreference<Preference>(PREF_AUTO_DELETE)!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||
if (feedPrefs != null) {
|
||||
when (newValue as String?) {
|
||||
"global" -> feedPrefs!!.currentAutoDelete = AutoDeleteAction.GLOBAL
|
||||
"always" -> feedPrefs!!.currentAutoDelete = AutoDeleteAction.ALWAYS
|
||||
"never" -> feedPrefs!!.currentAutoDelete = AutoDeleteAction.NEVER
|
||||
when (newValue as? String) {
|
||||
"global" -> feedPrefs!!.autoDeleteAction = AutoDeleteAction.GLOBAL
|
||||
"always" -> feedPrefs!!.autoDeleteAction = AutoDeleteAction.ALWAYS
|
||||
"never" -> feedPrefs!!.autoDeleteAction = AutoDeleteAction.NEVER
|
||||
else -> {}
|
||||
}
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
updateAutoDeleteSummary()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAutoDeleteSummary() {
|
||||
if (feedPrefs == null) return
|
||||
val autoDeletePreference = findPreference<ListPreference>(PREF_AUTO_DELETE)
|
||||
|
||||
when (feedPrefs!!.currentAutoDelete) {
|
||||
when (feedPrefs!!.autoDeleteAction) {
|
||||
AutoDeleteAction.GLOBAL -> {
|
||||
autoDeletePreference!!.setSummary(R.string.global_default)
|
||||
autoDeletePreference.value = "global"
|
||||
@ -254,11 +239,9 @@ class FeedSettingsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UnstableApi private fun setupVolumeAdaptationPreferences() {
|
||||
if (feedPrefs == null) return
|
||||
val volumeAdaptationPreference = findPreference<ListPreference>("volumeReduction")
|
||||
volumeAdaptationPreference!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||
val volumeAdaptationPreference = findPreference<ListPreference>("volumeReduction") ?: return
|
||||
volumeAdaptationPreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||
if (feedPrefs != null) {
|
||||
when (newValue as String?) {
|
||||
"off" -> feedPrefs!!.volumeAdaptionSetting = VolumeAdaptionSetting.OFF
|
||||
@ -270,48 +253,37 @@ class FeedSettingsFragment : Fragment() {
|
||||
else -> {}
|
||||
}
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
updateVolumeAdaptationValue()
|
||||
// if (feed != null && feedPrefs!!.volumeAdaptionSetting != null)
|
||||
// EventFlow.postEvent(FlowEvent.VolumeAdaptionChangedEvent(feedPrefs!!.volumeAdaptionSetting!!, feed!!.id))
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateVolumeAdaptationValue() {
|
||||
if (feedPrefs == null) return
|
||||
|
||||
val volumeAdaptationPreference = findPreference<ListPreference>("volumeReduction")
|
||||
|
||||
when (feedPrefs!!.volumeAdaptionSetting) {
|
||||
VolumeAdaptionSetting.OFF -> volumeAdaptationPreference!!.value = "off"
|
||||
VolumeAdaptionSetting.LIGHT_REDUCTION -> volumeAdaptationPreference!!.value = "light"
|
||||
VolumeAdaptionSetting.HEAVY_REDUCTION -> volumeAdaptationPreference!!.value = "heavy"
|
||||
VolumeAdaptionSetting.LIGHT_BOOST -> volumeAdaptationPreference!!.value = "light_boost"
|
||||
VolumeAdaptionSetting.MEDIUM_BOOST -> volumeAdaptationPreference!!.value = "medium_boost"
|
||||
VolumeAdaptionSetting.HEAVY_BOOST -> volumeAdaptationPreference!!.value = "heavy_boost"
|
||||
val volumeAdaptationPreference = findPreference<ListPreference>("volumeReduction") ?: return
|
||||
when (feedPrefs?.volumeAdaptionSetting) {
|
||||
VolumeAdaptionSetting.OFF -> volumeAdaptationPreference.value = "off"
|
||||
VolumeAdaptionSetting.LIGHT_REDUCTION -> volumeAdaptationPreference.value = "light"
|
||||
VolumeAdaptionSetting.HEAVY_REDUCTION -> volumeAdaptationPreference.value = "heavy"
|
||||
VolumeAdaptionSetting.LIGHT_BOOST -> volumeAdaptationPreference.value = "light_boost"
|
||||
VolumeAdaptionSetting.MEDIUM_BOOST -> volumeAdaptationPreference.value = "medium_boost"
|
||||
VolumeAdaptionSetting.HEAVY_BOOST -> volumeAdaptationPreference.value = "heavy_boost"
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class) private fun setupKeepUpdatedPreference() {
|
||||
if (feedPrefs == null) return
|
||||
val pref = findPreference<SwitchPreferenceCompat>("keepUpdated")
|
||||
|
||||
pref!!.isChecked = feedPrefs!!.keepUpdated
|
||||
pref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||
val checked = newValue == true
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.keepUpdated = checked
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
pref.isChecked = checked
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAutoDownloadGlobalPreference() {
|
||||
if (!isEnableAutodownload) {
|
||||
val autodl = findPreference<SwitchPreferenceCompat>("autoDownload")
|
||||
@ -321,47 +293,38 @@ class FeedSettingsFragment : Fragment() {
|
||||
findPreference<Preference>(PREF_EPISODE_FILTER)!!.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class) private fun setupAutoDownloadPreference() {
|
||||
if (feedPrefs == null) return
|
||||
val pref = findPreference<SwitchPreferenceCompat>("autoDownload")
|
||||
|
||||
pref!!.isEnabled = isEnableAutodownload
|
||||
if (isEnableAutodownload) {
|
||||
pref.isChecked = feedPrefs!!.autoDownload
|
||||
} else {
|
||||
if (isEnableAutodownload) pref.isChecked = feedPrefs!!.autoDownload
|
||||
else {
|
||||
pref.isChecked = false
|
||||
pref.setSummary(R.string.auto_download_disabled_globally)
|
||||
}
|
||||
|
||||
pref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||
val checked = newValue == true
|
||||
if (feedPrefs != null) {
|
||||
feedPrefs!!.autoDownload = checked
|
||||
persistFeedPreferences(feed!!)
|
||||
// EventFlow.postEvent(FlowEvent.FeedListUpdateEvent(feedPrefs!!.feedID))
|
||||
}
|
||||
updateAutoDownloadEnabled()
|
||||
pref.isChecked = checked
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAutoDownloadEnabled() {
|
||||
if (feed != null && feed!!.preferences != null) {
|
||||
if (feed?.preferences != null) {
|
||||
val enabled = feed!!.preferences!!.autoDownload && isEnableAutodownload
|
||||
findPreference<Preference>(PREF_EPISODE_FILTER)!!.isEnabled = enabled
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTags() {
|
||||
findPreference<Preference>(PREF_TAGS)!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (feedPrefs != null) TagSettingsDialog.newInstance(listOf(feed!!))
|
||||
.show(childFragmentManager, TagSettingsDialog.TAG)
|
||||
if (feedPrefs != null) TagSettingsDialog.newInstance(listOf(feed!!)).show(childFragmentManager, TagSettingsDialog.TAG)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun setFeed(feed_: Feed) {
|
||||
feed = feed_
|
||||
}
|
||||
@ -372,7 +335,6 @@ class FeedSettingsFragment : Fragment() {
|
||||
private val PREF_AUTHENTICATION: CharSequence = "authentication"
|
||||
private val PREF_AUTO_DELETE: CharSequence = "autoDelete"
|
||||
private val PREF_CATEGORY_AUTO_DOWNLOAD: CharSequence = "autoDownloadCategory"
|
||||
// private val PREF_NEW_EPISODES_ACTION: CharSequence = "feedNewEpisodesAction"
|
||||
private const val PREF_FEED_PLAYBACK_SPEED = "feedPlaybackSpeed"
|
||||
private const val PREF_AUTO_SKIP = "feedAutoSkip"
|
||||
private const val PREF_TAGS = "tags"
|
||||
@ -388,52 +350,35 @@ class FeedSettingsFragment : Fragment() {
|
||||
/**
|
||||
* Displays a dialog with a username and password text field and an optional checkbox to save username and preferences.
|
||||
*/
|
||||
abstract class FeedPreferenceSkipDialog(context: Context, skipIntroInitialValue: Int, skipEndInitialValue: Int)
|
||||
: MaterialAlertDialogBuilder(context) {
|
||||
|
||||
abstract class FeedPreferenceSkipDialog(context: Context, skipIntroInitialValue: Int, skipEndInitialValue: Int) : MaterialAlertDialogBuilder(context) {
|
||||
init {
|
||||
setTitle(R.string.pref_feed_skip)
|
||||
val binding = FeedPrefSkipDialogBinding.bind(View.inflate(context, R.layout.feed_pref_skip_dialog, null))
|
||||
setView(binding.root)
|
||||
|
||||
val etxtSkipIntro = binding.etxtSkipIntro
|
||||
val etxtSkipEnd = binding.etxtSkipEnd
|
||||
|
||||
etxtSkipIntro.setText(skipIntroInitialValue.toString())
|
||||
etxtSkipEnd.setText(skipEndInitialValue.toString())
|
||||
|
||||
setNegativeButton(R.string.cancel_label, null)
|
||||
setPositiveButton(R.string.confirm_label) { _: DialogInterface?, _: Int ->
|
||||
val skipIntro = try {
|
||||
etxtSkipIntro.text.toString().toInt()
|
||||
} catch (e: NumberFormatException) {
|
||||
0
|
||||
}
|
||||
val skipEnding = try {
|
||||
etxtSkipEnd.text.toString().toInt()
|
||||
} catch (e: NumberFormatException) {
|
||||
0
|
||||
}
|
||||
val skipIntro = try { etxtSkipIntro.text.toString().toInt() } catch (e: NumberFormatException) { 0 }
|
||||
val skipEnding = try { etxtSkipEnd.text.toString().toInt() } catch (e: NumberFormatException) { 0 }
|
||||
onConfirmed(skipIntro, skipEnding)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onConfirmed(skipIntro: Int, skipEndig: Int)
|
||||
protected abstract fun onConfirmed(skipIntro: Int, skipEnding: Int)
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a dialog with a text box for filtering episodes and two radio buttons for exclusion/inclusion
|
||||
*/
|
||||
abstract class EpisodeFilterPrefDialog(context: Context, filter: FeedEpisodesFilter) :
|
||||
MaterialAlertDialogBuilder(context) {
|
||||
|
||||
private val binding = EpisodeFilterDialogBinding.inflate(LayoutInflater.from(context))
|
||||
abstract class AutoDownloadFilterPrefDialog(context: Context, filter: FeedAutoDownloadFilter) : MaterialAlertDialogBuilder(context) {
|
||||
private val binding = AutodownloadFilterDialogBinding.inflate(LayoutInflater.from(context))
|
||||
private val termList: MutableList<String>
|
||||
|
||||
init {
|
||||
setTitle(R.string.episode_filters_label)
|
||||
setView(binding.root)
|
||||
|
||||
binding.durationCheckBox.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
binding.episodeFilterDurationText.isEnabled = isChecked
|
||||
}
|
||||
@ -442,7 +387,6 @@ class FeedSettingsFragment : Fragment() {
|
||||
// Store minimal duration in seconds, show in minutes
|
||||
binding.episodeFilterDurationText.setText((filter.minimalDurationFilter / 60).toString())
|
||||
} else binding.episodeFilterDurationText.isEnabled = false
|
||||
|
||||
if (filter.excludeOnly()) {
|
||||
termList = filter.getExcludeFilter().toMutableList()
|
||||
binding.excludeRadio.isChecked = true
|
||||
@ -451,13 +395,11 @@ class FeedSettingsFragment : Fragment() {
|
||||
binding.includeRadio.isChecked = true
|
||||
}
|
||||
setupWordsList()
|
||||
|
||||
setNegativeButton(R.string.cancel_label, null)
|
||||
setPositiveButton(R.string.confirm_label) { dialog: DialogInterface, which: Int ->
|
||||
this.onConfirmClick(dialog, which)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWordsList() {
|
||||
binding.termsRecycler.layoutManager = GridLayoutManager(context, 2)
|
||||
binding.termsRecycler.addItemDecoration(ItemOffsetDecoration(context, 4))
|
||||
@ -465,7 +407,6 @@ class FeedSettingsFragment : Fragment() {
|
||||
override fun getChips(): List<String> {
|
||||
return termList
|
||||
}
|
||||
|
||||
override fun onRemoveClicked(position: Int) {
|
||||
termList.removeAt(position)
|
||||
notifyDataSetChanged()
|
||||
@ -475,15 +416,12 @@ class FeedSettingsFragment : Fragment() {
|
||||
binding.termsTextInput.setEndIconOnClickListener {
|
||||
val newWord = binding.termsTextInput.editText!!.text.toString().replace("\"", "").trim { it <= ' ' }
|
||||
if (newWord.isEmpty() || termList.contains(newWord)) return@setEndIconOnClickListener
|
||||
|
||||
termList.add(newWord)
|
||||
binding.termsTextInput.editText!!.setText("")
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun onConfirmed(filter: FeedEpisodesFilter)
|
||||
|
||||
protected abstract fun onConfirmed(filter: FeedAutoDownloadFilter)
|
||||
private fun onConfirmClick(dialog: DialogInterface, which: Int) {
|
||||
var minimalDuration = -1
|
||||
if (binding.durationCheckBox.isChecked) {
|
||||
@ -498,10 +436,8 @@ class FeedSettingsFragment : Fragment() {
|
||||
var includeFilter = ""
|
||||
if (binding.includeRadio.isChecked) includeFilter = toFilterString(termList)
|
||||
else excludeFilter = toFilterString(termList)
|
||||
|
||||
onConfirmed(FeedEpisodesFilter(includeFilter, excludeFilter, minimalDuration))
|
||||
onConfirmed(FeedAutoDownloadFilter(includeFilter, excludeFilter, minimalDuration))
|
||||
}
|
||||
|
||||
private fun toFilterString(words: List<String>?): String {
|
||||
val result = StringBuilder()
|
||||
for (word in words!!) {
|
||||
|
@ -5,7 +5,7 @@ import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.MenuItemUtils
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.adapter.EpisodesAdapter
|
||||
|
@ -13,8 +13,8 @@ import ac.mdiq.podcini.storage.algorithms.AutoCleanups
|
||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodesCount
|
||||
import ac.mdiq.podcini.storage.database.Feeds.getFeedList
|
||||
import ac.mdiq.podcini.storage.model.DatasetStats
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter.Companion.unfiltered
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter.Companion.unfiltered
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.activity.PreferenceActivity
|
||||
import ac.mdiq.podcini.ui.activity.starter.MainActivityStarter
|
||||
|
@ -19,7 +19,7 @@ import ac.mdiq.podcini.storage.model.DownloadResult
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.FeedPreferences
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.dialog.AuthenticationDialog
|
||||
import ac.mdiq.podcini.ui.utils.ThemeUtils.getColorFromAttr
|
||||
|
@ -15,7 +15,7 @@ import ac.mdiq.podcini.storage.model.Chapter
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.EmbeddedChapterImage
|
||||
import ac.mdiq.podcini.storage.model.EmbeddedChapterImage
|
||||
import ac.mdiq.podcini.ui.activity.MainActivity
|
||||
import ac.mdiq.podcini.ui.utils.ShownotesCleaner
|
||||
import ac.mdiq.podcini.ui.view.ShownotesWebView
|
||||
|
@ -17,9 +17,9 @@ import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
|
||||
import ac.mdiq.podcini.storage.database.RealmDB.upsert
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.actions.EpisodeMultiSelectHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.EpisodeMenuHandler
|
||||
import ac.mdiq.podcini.ui.actions.menuhandler.MenuItemUtils
|
||||
|
@ -56,7 +56,6 @@ import io.realm.kotlin.query.Sort
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.text.NumberFormat
|
||||
@ -223,13 +222,13 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||
when (tagFilterIndex) {
|
||||
1 -> feedListFiltered = feedList // All feeds
|
||||
0 -> feedListFiltered = feedList.filter { // feeds without tag
|
||||
val tags = it.preferences?.getTags()
|
||||
val tags = it.preferences?.tags
|
||||
tags.isNullOrEmpty() || (tags.size == 1 && tags.toList()[0] == "#root")
|
||||
}
|
||||
else -> { // feeds with the chosen tag
|
||||
val tag = tags[tagFilterIndex]
|
||||
feedListFiltered = feedList.filter {
|
||||
it.preferences?.getTags()?.contains(tag) ?: false
|
||||
it.preferences?.tags?.contains(tag) ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,6 +259,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||
is FlowEvent.FeedListEvent, is FlowEvent.FeedsSortedEvent -> loadSubscriptions()
|
||||
is FlowEvent.EpisodePlayedEvent -> loadSubscriptions()
|
||||
is FlowEvent.FeedTagsChangedEvent -> loadSubscriptions()
|
||||
// is FlowEvent.FeedPrefsChangeEvent -> onFeedPrefsChangeEvent(event)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@ -280,6 +280,10 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||
}
|
||||
}
|
||||
|
||||
// private fun onFeedPrefsChangeEvent(event: FlowEvent.FeedPrefsChangeEvent) {
|
||||
// val feed = getFeed(event.feed.id)
|
||||
// }
|
||||
|
||||
@UnstableApi override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
val itemId = item.itemId
|
||||
when (itemId) {
|
||||
@ -494,7 +498,7 @@ class SubscriptionsFragment : Fragment(), Toolbar.OnMenuItemClickListener, Selec
|
||||
@UnstableApi override fun preferenceChanged(pos: Int) {
|
||||
val autoDeleteAction: FeedPreferences.AutoDeleteAction = FeedPreferences.AutoDeleteAction.fromCode(pos)
|
||||
saveFeedPreferences { feedPreferences: FeedPreferences ->
|
||||
feedPreferences.currentAutoDelete = autoDeleteAction
|
||||
feedPreferences.autoDeleteAction = autoDeleteAction
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -187,9 +187,6 @@ class StatisticsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the 'playback statistics' screen
|
||||
*/
|
||||
class SubscriptionStatisticsFragment : Fragment() {
|
||||
private var _binding: StatisticsFragmentBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
@ -11,7 +11,7 @@ import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.Episode.Companion.BUILDING
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.model.Feed.Companion.PREFIX_GENERATIVE_COVER
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.ui.actions.actionbutton.EpisodeActionButton
|
||||
import ac.mdiq.podcini.ui.actions.actionbutton.TTSActionButton
|
||||
@ -22,7 +22,6 @@ import ac.mdiq.podcini.ui.view.CircularProgressBar
|
||||
import ac.mdiq.podcini.util.Converter
|
||||
import ac.mdiq.podcini.util.DateFormatter
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import ac.mdiq.podcini.util.event.FlowEvent
|
||||
import android.text.Layout
|
||||
import android.text.format.Formatter
|
||||
import android.util.Log
|
||||
|
@ -8,7 +8,7 @@ import ac.mdiq.podcini.receiver.MediaButtonReceiver.Companion.createPendingInten
|
||||
import ac.mdiq.podcini.receiver.PlayerWidget
|
||||
import ac.mdiq.podcini.receiver.PlayerWidget.Companion.isEnabled
|
||||
import ac.mdiq.podcini.receiver.PlayerWidget.Companion.prefs
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.ui.activity.starter.MainActivityStarter
|
||||
import ac.mdiq.podcini.ui.activity.starter.PlaybackSpeedActivityStarter
|
||||
|
@ -5,7 +5,7 @@ import ac.mdiq.podcini.net.download.DownloadStatus
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.util.Logd
|
||||
import android.content.Context
|
||||
import android.view.KeyEvent
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.util.sorting
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/autodownload_filter_dialog"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
@ -91,9 +92,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/time_minutes" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
@ -8,14 +8,6 @@
|
||||
android:summary="@string/keep_updated_summary"
|
||||
android:title="@string/keep_updated" />
|
||||
|
||||
<!-- <SwitchPreferenceCompat-->
|
||||
<!-- android:defaultValue="false"-->
|
||||
<!-- android:dependency="keepUpdated"-->
|
||||
<!-- android:icon="@drawable/ic_notifications"-->
|
||||
<!-- android:key="episodeNotification"-->
|
||||
<!-- android:summary="@string/episode_notification_summary"-->
|
||||
<!-- android:title="@string/episode_notification" />-->
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_key"
|
||||
android:key="authentication"
|
||||
|
@ -1,10 +1,6 @@
|
||||
package ac.mdiq.podcini.playback.cast
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.Playable
|
||||
import ac.mdiq.podcini.storage.model.RemoteMedia
|
||||
import ac.mdiq.podcini.storage.model.*
|
||||
import android.content.ContentResolver
|
||||
import android.util.Log
|
||||
import com.google.android.gms.cast.CastDevice
|
||||
|
@ -1,15 +1,15 @@
|
||||
package ac.mdiq.podcini.feed
|
||||
|
||||
import ac.mdiq.podcini.util.Converter.durationStringShortToMs
|
||||
import ac.mdiq.podcini.storage.utils.FeedEpisodesFilter
|
||||
import ac.mdiq.podcini.storage.model.FeedAutoDownloadFilter
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
class FeedEpisodesFilterTest {
|
||||
class FeedAutoDownloadFilterTest {
|
||||
@Test
|
||||
fun testNullFilter() {
|
||||
val filter = FeedEpisodesFilter()
|
||||
val filter = FeedAutoDownloadFilter()
|
||||
val item = Episode()
|
||||
item.title = ("Hello world")
|
||||
|
||||
@ -23,7 +23,7 @@ class FeedEpisodesFilterTest {
|
||||
@Test
|
||||
fun testBasicIncludeFilter() {
|
||||
val includeFilter = "Hello"
|
||||
val filter = FeedEpisodesFilter(includeFilter, "")
|
||||
val filter = FeedAutoDownloadFilter(includeFilter, "")
|
||||
val item = Episode()
|
||||
item.title = ("Hello world")
|
||||
|
||||
@ -41,7 +41,7 @@ class FeedEpisodesFilterTest {
|
||||
@Test
|
||||
fun testBasicExcludeFilter() {
|
||||
val excludeFilter = "Hello"
|
||||
val filter = FeedEpisodesFilter("", excludeFilter)
|
||||
val filter = FeedAutoDownloadFilter("", excludeFilter)
|
||||
val item = Episode()
|
||||
item.title = ("Hello world")
|
||||
|
||||
@ -59,7 +59,7 @@ class FeedEpisodesFilterTest {
|
||||
@Test
|
||||
fun testComplexIncludeFilter() {
|
||||
val includeFilter = "Hello \n\"Two words\""
|
||||
val filter = FeedEpisodesFilter(includeFilter, "")
|
||||
val filter = FeedAutoDownloadFilter(includeFilter, "")
|
||||
val item = Episode()
|
||||
item.title = ("hello world")
|
||||
|
||||
@ -81,7 +81,7 @@ class FeedEpisodesFilterTest {
|
||||
@Test
|
||||
fun testComplexExcludeFilter() {
|
||||
val excludeFilter = "Hello \"Two words\""
|
||||
val filter = FeedEpisodesFilter("", excludeFilter)
|
||||
val filter = FeedAutoDownloadFilter("", excludeFilter)
|
||||
val item = Episode()
|
||||
item.title = ("hello world")
|
||||
|
||||
@ -104,7 +104,7 @@ class FeedEpisodesFilterTest {
|
||||
fun testComboFilter() {
|
||||
val includeFilter = "Hello world"
|
||||
val excludeFilter = "dislike"
|
||||
val filter = FeedEpisodesFilter(includeFilter, excludeFilter)
|
||||
val filter = FeedAutoDownloadFilter(includeFilter, excludeFilter)
|
||||
|
||||
val download = Episode()
|
||||
download.title = ("Hello everyone!")
|
||||
@ -142,7 +142,7 @@ class FeedEpisodesFilterTest {
|
||||
doNotDownload.setMedia(doNotDownloadMedia)
|
||||
|
||||
val minimalDurationFilter = 3 * 60
|
||||
val filter = FeedEpisodesFilter("", "", minimalDurationFilter)
|
||||
val filter = FeedAutoDownloadFilter("", "", minimalDurationFilter)
|
||||
|
||||
Assert.assertTrue(filter.hasMinimalDurationFilter())
|
||||
Assert.assertTrue(filter.shouldAutoDownload(download))
|
@ -2,7 +2,7 @@ package ac.mdiq.podcini.feed
|
||||
|
||||
import ac.mdiq.podcini.feed.FeedMother.anyFeed
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.feed
|
||||
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting.Companion.fromInteger
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting.Companion.fromInteger
|
||||
import org.hamcrest.MatcherAssert
|
||||
import org.hamcrest.Matchers
|
||||
import org.junit.Assert
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ac.mdiq.podcini.feed.parser.element.namespace
|
||||
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.utils.MediaType
|
||||
import ac.mdiq.podcini.storage.model.MediaType
|
||||
import ac.mdiq.podcini.feed.parser.element.namespace.FeedParserTestHelper.getFeedFile
|
||||
import ac.mdiq.podcini.feed.parser.element.namespace.FeedParserTestHelper.runFeedParser
|
||||
import junit.framework.TestCase.assertEquals
|
||||
|
@ -4,7 +4,7 @@ import ac.mdiq.podcini.net.feed.parser.media.id3.ChapterReader
|
||||
import ac.mdiq.podcini.net.feed.parser.media.id3.ID3Reader
|
||||
import ac.mdiq.podcini.net.feed.parser.media.id3.ID3ReaderException
|
||||
import ac.mdiq.podcini.storage.model.Chapter
|
||||
import ac.mdiq.podcini.storage.utils.EmbeddedChapterImage.Companion.makeUrl
|
||||
import ac.mdiq.podcini.storage.model.EmbeddedChapterImage.Companion.makeUrl
|
||||
import ac.mdiq.podcini.net.feed.parser.media.id3.model.FrameHeader
|
||||
import org.apache.commons.io.input.CountingInputStream
|
||||
import org.junit.Assert
|
||||
|
@ -5,7 +5,7 @@ import ac.mdiq.podcini.playback.base.MediaPlayerBase
|
||||
import ac.mdiq.podcini.playback.base.PlayerStatus
|
||||
import ac.mdiq.podcini.playback.service.PlaybackService
|
||||
import ac.mdiq.podcini.storage.model.*
|
||||
import ac.mdiq.podcini.storage.utils.VolumeAdaptionSetting
|
||||
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers
|
||||
|
@ -9,8 +9,8 @@ import ac.mdiq.podcini.storage.database.Feeds.getFeedList
|
||||
import ac.mdiq.podcini.storage.database.Feeds.getFeedListDownloadUrls
|
||||
import ac.mdiq.podcini.storage.database.Queues.getInQueueEpisodeIds
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.utils.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import ac.mdiq.podcini.ui.fragment.HistoryFragment.Companion.getHistory
|
||||
import ac.mdiq.podcini.ui.fragment.HistoryFragment.Companion.getNumberOfCompleted
|
||||
import ac.mdiq.podcini.ui.fragment.NavDrawerFragment.Companion.getDatasetStats
|
||||
|
@ -4,7 +4,7 @@ import ac.mdiq.podcini.util.sorting.EpisodesPermutors.getPermutor
|
||||
import ac.mdiq.podcini.storage.model.Feed
|
||||
import ac.mdiq.podcini.storage.model.Episode
|
||||
import ac.mdiq.podcini.storage.model.EpisodeMedia
|
||||
import ac.mdiq.podcini.storage.utils.SortOrder
|
||||
import ac.mdiq.podcini.storage.model.SortOrder
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
@ -1,3 +1,11 @@
|
||||
## 6.0.6
|
||||
|
||||
* minor class re-structuring
|
||||
* adjusted FeedPreferences to incoporate some previously ignored properties
|
||||
* enabled selection of .json files when importing progress
|
||||
* in wifi sync and episode progress export/import, changed start position and added played duration for episodes (available from 5.5.3),
|
||||
this helps for the statistics view at the importer to correctly show imported progress without having to do "include marked played"
|
||||
|
||||
## 6.0.5
|
||||
|
||||
* fixed threading issue of downloading multiple episodes
|
||||
|
8
fastlane/metadata/android/en-US/changelogs/3020206.txt
Normal file
8
fastlane/metadata/android/en-US/changelogs/3020206.txt
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
Version 6.0.6 brings several changes:
|
||||
|
||||
* minor class re-structuring
|
||||
* adjusted FeedPreferences to incoporate some previously ignored properties
|
||||
* enabled selection of .json files when importing progress
|
||||
* in wifi sync and episode progress export/import, changed start position and added played duration for episodes (available from 5.5.3),
|
||||
this helps for the statistics view at the importer to correctly show imported progress without having to do "include marked played"
|
Loading…
x
Reference in New Issue
Block a user