Skip to content

Commit

Permalink
6.0.4 commit
Browse files Browse the repository at this point in the history
  • Loading branch information
XilinJia committed Jun 30, 2024
1 parent 8d8db46 commit a21e99f
Show file tree
Hide file tree
Showing 27 changed files with 326 additions and 280 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ android {
buildConfig true
}
defaultConfig {
versionCode 3020203
versionName "6.0.3"
versionCode 3020204
versionName "6.0.4"

applicationId "ac.mdiq.podcini.R"
def commit = ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,6 @@ object UserPreferences {
/**
* Returns the sort order for the queue keep sorted mode.
* Note: This value is stored independently from the keep sorted state.
*
* @see .isQueueKeepSorted
*/
get() {
Expand All @@ -729,7 +728,6 @@ object UserPreferences {
}
/**
* Sets the sort order for the queue keep sorted mode.
*
* @see .setQueueKeepSorted
*/
set(sortOrder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class UserInterfacePreferencesFragment : PreferenceFragmentCompat() {
findPreference<Preference>(UserPreferences.PREF_SHOW_TIME_LEFT)?.setOnPreferenceChangeListener { _: Preference?, newValue: Any? ->
setShowRemainTimeSetting(newValue as Boolean?)
// TODO: need another event type?
EventFlow.postEvent(FlowEvent.EpisodePlayedEvent())
// EventFlow.postEvent(FlowEvent.EpisodePlayedEvent())
EventFlow.postEvent(FlowEvent.PlayerSettingsEvent())
true
}
Expand Down
23 changes: 13 additions & 10 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/database/Episodes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -249,19 +249,21 @@ object Episodes {
fun addToHistory(episode: Episode, date: Date? = Date()) : Job {
Logd(TAG, "addToHistory called")
return runOnIOScope {
episode.media?.playbackCompletionDate = date
upsert(episode) {}
upsert(episode) {
it.media?.playbackCompletionDate = date
}
EventFlow.postEvent(FlowEvent.HistoryEvent())
}
}

@JvmStatic
fun setFavorite(episode: Episode, stat: Boolean) : Job {
Logd(TAG, "setFavorite called")
Logd(TAG, "setFavorite called $stat")
return runOnIOScope {
episode.isFavorite = stat
upsert(episode) {}
EventFlow.postEvent(FlowEvent.FavoritesEvent(episode))
val result = upsert(episode) {
it.isFavorite = stat
}
EventFlow.postEvent(FlowEvent.FavoritesEvent(result))
}
}

Expand All @@ -276,11 +278,12 @@ object Episodes {
Logd(TAG, "markPlayed called")
return runOnIOScope {
for (episode in episodes) {
episode.playState = played
if (resetMediaPosition) episode.media?.setPosition(0)
upsert(episode) {}
val result = upsert(episode) {
it.playState = played
if (resetMediaPosition) it.media?.setPosition(0)
}
if (played == Episode.PLAYED) removeFromAllQueues(episode)
EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(episode))
EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(result))
}
}
}
Expand Down
73 changes: 44 additions & 29 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/database/Feeds.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ object Feeds {
private val feedMap: MutableMap<Long, Feed> = mutableMapOf()
private val tags: MutableList<String> = mutableListOf()

@Synchronized
fun getFeedList(): List<Feed> {
return feedMap.values.toList()
}
Expand All @@ -44,6 +45,7 @@ object Feeds {
return tags
}

@Synchronized
fun updateFeedMap(feeds: List<Feed> = listOf(), wipe: Boolean = false) {
Logd(TAG, "updateFeedMap called feeds: ${feeds.size} wipe: $wipe")
when {
Expand All @@ -65,13 +67,17 @@ object Feeds {

fun buildTags() {
val tagsSet = mutableSetOf<String>()
val feedsCopy = feedMap.values
val feedsCopy = synchronized(feedMap) { feedMap.values.toList() }
for (feed in feedsCopy) {
if (feed.preferences != null) tagsSet.addAll(feed.preferences!!.tags.filter { it != TAG_ROOT })
}
tags.clear()
tags.addAll(tagsSet)
tags.sort()
val newTags = tagsSet.intersect(tags.toSet())
if (newTags.isNotEmpty()) {
tags.clear()
tags.addAll(tagsSet)
tags.sort()
EventFlow.postEvent(FlowEvent.FeedTagsChangedEvent())
}
}

fun monitorFeeds() {
Expand All @@ -90,8 +96,8 @@ object Feeds {
Logd(TAG, "monitorFeeds inserted feed: ${changes.list[i].title}")
updateFeedMap(listOf(changes.list[i]))
monitorFeed(changes.list[i])
EventFlow.postEvent(FlowEvent.FeedListEvent(FlowEvent.FeedListEvent.Action.ADDED, changes.list[i].id))
}
EventFlow.postEvent(FlowEvent.FeedListEvent(FlowEvent.FeedListEvent.Action.ADDED))
}
// changes.changes.isNotEmpty() -> {
// for (i in changes.changes) {
Expand Down Expand Up @@ -456,12 +462,20 @@ object Feeds {
// remove from queues
removeFromAllQueuesQuiet(eids)
// remove media files
deleteMediaFilesQuiet(context, feed.episodes)
// deleteMediaFilesQuiet(context, feed.episodes)
realm.write {
val feed_ = query(Feed::class).query("id == $0", feedId).first().find()
if (feed_ != null) {
val episodes = feed_.episodes.toList()
if (episodes.isNotEmpty()) episodes.forEach { e -> delete(e) }
if (episodes.isNotEmpty()) episodes.forEach { episode ->
val url = episode.media?.fileUrl
when {
// Local feed
url != null && url.startsWith("content://") -> DocumentFile.fromSingleUri(context, Uri.parse(url))?.delete()
url != null -> File(url).delete()
}
delete(episode)
}
val feedToDelete = findLatest(feed_)
if (feedToDelete != null) {
delete(feedToDelete)
Expand All @@ -475,28 +489,29 @@ object Feeds {
}
}

private fun deleteMediaFilesQuiet(context: Context, episodes: List<Episode>) {
for (episode in episodes) {
val media = episode.media ?: continue
val url = media.fileUrl
when {
url != null && url.startsWith("content://") -> {
// Local feed
val documentFile = DocumentFile.fromSingleUri(context, Uri.parse(media.fileUrl))
documentFile?.delete()
episode.media?.fileUrl = null
}
url != null -> {
// delete downloaded media file
val mediaFile = File(url)
mediaFile.delete()
episode.media?.downloaded = false
episode.media?.fileUrl = null
episode.media?.hasEmbeddedPicture = false
}
}
}
}
// private fun deleteMediaFilesQuiet(context: Context, episodes: List<Episode>) {
// for (episode in episodes) {
// val media = episode.media ?: continue
// val url = media.fileUrl
// when {
// url != null && url.startsWith("content://") -> {
// // Local feed
// val documentFile = DocumentFile.fromSingleUri(context, Uri.parse(media.fileUrl))
// documentFile?.delete()
//// episode.media?.fileUrl = null
// }
// url != null -> {
// // delete downloaded media file
// val mediaFile = File(url)
// mediaFile.delete()
//// since deleting entire feed, these are not necessary
//// episode.media?.downloaded = false
//// episode.media?.fileUrl = null
//// episode.media?.hasEmbeddedPicture = false
// }
// }
// }
// }

@JvmStatic
fun shouldAutoDeleteItemsOnFeed(feed: Feed): Boolean {
Expand Down
13 changes: 8 additions & 5 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/database/RealmDB.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import kotlin.coroutines.ContinuationInterceptor
object RealmDB {
private val TAG: String = RealmDB::class.simpleName ?: "Anonymous"

private const val SCHEMA_VERSION_NUMBER = 4L
private const val SCHEMA_VERSION_NUMBER = 6L

private val ioScope = CoroutineScope(Dispatchers.IO)

Expand Down Expand Up @@ -93,21 +93,24 @@ object RealmDB {
Logd(TAG, "${caller?.className}.${caller?.methodName} upsert: ${entity.javaClass.simpleName}")
}
return realm.write {
var result: T = entity
if (entity.isManaged()) {
findLatest(entity)?.let {
result = findLatest(entity)?.let {
block(it)
}
it
} ?: entity
} else {
try {
copyToRealm(entity, UpdatePolicy.ALL).let {
result = copyToRealm(entity, UpdatePolicy.ALL).let {
block(it)
it
}
} catch (e: Exception) {
Log.e(TAG, "copyToRealm error: ${e.message}")
showStackTrace()
}
}
entity
result
}
}

Expand Down
2 changes: 2 additions & 0 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/model/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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 io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
Expand Down Expand Up @@ -126,6 +127,7 @@ class Feed : RealmObject {

@Ignore
var sortOrder: SortOrder? = null
get() = fromCode(preferences?.sortOrderCode ?: 0)
set(value) {
if (value == null) return
field = value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class EpisodeMultiSelectHandler(private val activity: MainActivity, private val

fun handleAction(items: List<Episode>) {
when (actionId) {
R.id.add_to_favorite_batch -> markFavorite(items)
R.id.add_to_favorite_batch -> markFavorite(items, true)
R.id.remove_favorite_batch -> markFavorite(items, false)
R.id.add_to_queue_batch -> queueChecked(items)
R.id.remove_from_queue_batch -> removeFromQueueChecked(items)
R.id.mark_read_batch -> {
Expand Down Expand Up @@ -68,7 +69,7 @@ class EpisodeMultiSelectHandler(private val activity: MainActivity, private val
// showMessage(R.plurals.marked_unread_batch_label, items.size)
// }

private fun markFavorite(items: List<Episode>) {
private fun markFavorite(items: List<Episode>, stat: Boolean) {
for (item in items) {
Episodes.setFavorite(item, true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ object EpisodeMenuHandler {
/**
* This method should be called in the prepare-methods of menus. It changes
* the visibility of the menu items depending on a FeedItem's attributes.
*
* @param menu An instance of Menu
* @param selectedItem The FeedItem for which the menu is supposed to be prepared
* @return Returns true if selectedItem is not null.
Expand Down Expand Up @@ -101,7 +100,6 @@ object EpisodeMenuHandler {
*/
private fun setItemVisibility(menu: Menu?, menuId: Int, visibility: Boolean) {
if (menu == null) return

val item = menu.findItem(menuId)
item?.setVisible(visibility)
}
Expand All @@ -120,26 +118,21 @@ object EpisodeMenuHandler {
/**
* The same method as [.onPrepareMenu], but lets the
* caller also specify a list of menu items that should not be shown.
*
* @param excludeIds Menu item that should be excluded
* @return true if selectedItem is not null.
*/
@UnstableApi
fun onPrepareMenu(menu: Menu?, selectedItem: Episode?, vararg excludeIds: Int): Boolean {
if (menu == null || selectedItem == null) return false

val rc = onPrepareMenu(menu, selectedItem)
if (rc && excludeIds.isNotEmpty()) {
for (id in excludeIds) {
setItemVisibility(menu, id, false)
}
for (id in excludeIds) setItemVisibility(menu, id, false)
}
return rc
}

/**
* Default menu handling for the given FeedItem.
*
* A Fragment instance, (rather than the more generic Context), is needed as a parameter
* to support some UI operations, e.g., creating a Snackbar.
*/
Expand Down Expand Up @@ -204,22 +197,20 @@ object EpisodeMenuHandler {
return false
}
}

// Refresh menu state
return true
}

/**
* Remove new flag with additional UI logic to allow undo with Snackbar.
*
* Undo is useful for Remove new flag, given there is no UI to undo it otherwise
* ,i.e., there is (context) menu item for add new flag
*/
@JvmStatic
fun markReadWithUndo(fragment: Fragment, item: Episode?, playState: Int, showSnackbar: Boolean) {
if (item == null) return

Logd(TAG, "markReadWithUndo(" + item.id + ")")
Logd(TAG, "markReadWithUndo( ${item.id} )")
// we're marking it as unplayed since the user didn't actually play it
// but they don't want it considered 'NEW' anymore
markPlayed(playState, false, item)
Expand All @@ -228,8 +219,7 @@ object EpisodeMenuHandler {
val r = Runnable {
val media: EpisodeMedia? = item.media
val shouldAutoDelete: Boolean = if (item.feed == null) false else shouldAutoDeleteItemsOnFeed(item.feed!!)
if (media != null && EpisodeUtil.hasAlmostEnded(media) && shouldAutoDelete)
deleteMediaOfEpisode(fragment.requireContext(), item)
if (media != null && EpisodeUtil.hasAlmostEnded(media) && shouldAutoDelete) deleteMediaOfEpisode(fragment.requireContext(), item)
}
val playStateStringRes: Int = when (playState) {
Episode.UNPLAYED -> if (item.playState == Episode.NEW) R.string.removed_inbox_label //was new
Expand All @@ -252,8 +242,4 @@ object EpisodeMenuHandler {

h.postDelayed(r, ceil((duration * 1.05f).toDouble()).toInt().toLong())
}

fun removeNewFlagWithUndo(fragment: Fragment, item: Episode?) {
markReadWithUndo(fragment, item, Episode.UNPLAYED, false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ open class EpisodesAdapter(mainActivity: MainActivity)
* Instead, we tell the adapter to use partial binding by calling [.notifyItemChanged].
* We actually ignore the payload and always do a full bind but calling the partial bind method ensures
* that ViewHolders are always re-used.
*
* @param position Position of the item that has changed
*/
fun notifyItemChangedCompat(position: Int) {
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/kotlin/ac/mdiq/podcini/ui/dialog/ShareDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class ShareDialog : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

ctx = requireContext()
item = requireArguments().getSerializable(ARGUMENT_FEED_ITEM) as Episode?
prefs = requireActivity().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)

_binding = ShareEpisodeDialogBinding.inflate(inflater)
Expand Down Expand Up @@ -93,7 +92,7 @@ class ShareDialog : BottomSheetDialogFragment() {
}

companion object {
private const val ARGUMENT_FEED_ITEM = "feedItem"
// private const val ARGUMENT_FEED_ITEM = "feedItem"
private const val PREF_NAME = "ShareDialog"
private const val PREF_SHARE_EPISODE_START_AT = "prefShareEpisodeStartAt"
private const val PREF_SHARE_EPISODE_TYPE = "prefShareEpisodeType"
Expand Down
Loading

0 comments on commit a21e99f

Please sign in to comment.