diff --git a/app/build.gradle b/app/build.gradle index 4772c734..f09c6907 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -149,8 +149,8 @@ android { // Version code schema (not used): // "1.2.3-beta4" -> 1020304 // "1.2.3" -> 1020395 - versionCode 3020128 - versionName "4.7.0" + versionCode 3020129 + versionName "4.7.1" def commit = "" try { diff --git a/app/src/main/java/ac/mdiq/podcini/net/download/service/FeedUpdateWorker.kt b/app/src/main/java/ac/mdiq/podcini/net/download/service/FeedUpdateWorker.kt index 1a098584..a2300d66 100644 --- a/app/src/main/java/ac/mdiq/podcini/net/download/service/FeedUpdateWorker.kt +++ b/app/src/main/java/ac/mdiq/podcini/net/download/service/FeedUpdateWorker.kt @@ -32,12 +32,12 @@ import android.os.Build import java.util.* class FeedUpdateWorker(context: Context, params: WorkerParameters) : Worker(context, params) { - private val newEpisodesNotification = NewEpisodesNotification() +// private val newEpisodesNotification = NewEpisodesNotification() private val notificationManager = NotificationManagerCompat.from(context) @UnstableApi override fun doWork(): Result { ClientConfigurator.initialize(applicationContext) - newEpisodesNotification.loadCountersBeforeRefresh() +// newEpisodesNotification.loadCountersBeforeRefresh() val toUpdate: MutableList val feedId = inputData.getLong(FeedUpdateManager.EXTRA_FEED_ID, -1) @@ -110,6 +110,7 @@ class FeedUpdateWorker(context: Context, params: WorkerParameters) : Worker(cont Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions +// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) @@ -186,7 +187,7 @@ class FeedUpdateWorker(context: Context, params: WorkerParameters) : Worker(cont if (log.isNotEmpty() && !log[0].isSuccessful) { DBWriter.addDownloadStatus(feedSyncTask.downloadStatus) } - newEpisodesNotification.showIfNeeded(applicationContext, feedSyncTask.savedFeed!!) +// newEpisodesNotification.showIfNeeded(applicationContext, feedSyncTask.savedFeed!!) if (!request.source.isNullOrEmpty()) { when { !downloader.permanentRedirectUrl.isNullOrEmpty() -> { diff --git a/app/src/main/java/ac/mdiq/podcini/net/download/service/NewEpisodesNotification.kt b/app/src/main/java/ac/mdiq/podcini/net/download/service/NewEpisodesNotification.kt deleted file mode 100644 index 085f9716..00000000 --- a/app/src/main/java/ac/mdiq/podcini/net/download/service/NewEpisodesNotification.kt +++ /dev/null @@ -1,161 +0,0 @@ -package ac.mdiq.podcini.net.download.service - -import ac.mdiq.podcini.R -import ac.mdiq.podcini.storage.database.PodDBAdapter -import ac.mdiq.podcini.storage.model.feed.Feed -import ac.mdiq.podcini.storage.model.feed.FeedCounter -import ac.mdiq.podcini.ui.utils.NotificationUtils -import android.Manifest -import android.app.PendingIntent -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.graphics.Bitmap -import android.os.Build -import android.util.Log -import android.widget.Toast -import androidx.core.app.ActivityCompat -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import com.bumptech.glide.Glide -import com.bumptech.glide.request.RequestOptions - -class NewEpisodesNotification { - private var countersBefore: Map? = null - - fun loadCountersBeforeRefresh() { - val adapter = PodDBAdapter.getInstance() - adapter.open() - countersBefore = adapter.getFeedCounters(FeedCounter.SHOW_NEW) - adapter.close() - } - - fun showIfNeeded(context: Context, feed: Feed) { - val prefs = feed.preferences - if (prefs == null || !prefs.keepUpdated || !prefs.showEpisodeNotification) { - return - } - - val newEpisodesBefore = if (countersBefore!!.containsKey(feed.id)) countersBefore!![feed.id]!! else 0 - val newEpisodesAfter = getNewEpisodeCount(feed.id) - - Log.d(TAG, "New episodes before: $newEpisodesBefore, after: $newEpisodesAfter") - if (newEpisodesAfter > newEpisodesBefore) { - val notificationManager = NotificationManagerCompat.from(context) - showNotification(newEpisodesAfter, feed, context, notificationManager) - } - } - - companion object { - private const val TAG = "NewEpisodesNotification" - private const val GROUP_KEY = "ac.mdiq.podcini.EPISODES" - - private fun showNotification(newEpisodes: Int, feed: Feed, context: Context, - notificationManager: NotificationManagerCompat - ) { - val res = context.resources - val text = res.getQuantityString( - R.plurals.new_episode_notification_message, newEpisodes, newEpisodes, feed.title - ) - val title = res.getQuantityString(R.plurals.new_episode_notification_title, newEpisodes) - - val intent = Intent() - intent.setAction("NewEpisodes" + feed.id) - intent.setComponent(ComponentName(context, "ac.mdiq.podcini.activity.MainActivity")) - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - intent.putExtra("fragment_feed_id", feed.id) - val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) - - val notification = NotificationCompat.Builder( - context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS) - .setSmallIcon(R.drawable.ic_notification_new) - .setContentTitle(title) - .setLargeIcon(loadIcon(context, feed)) - .setContentText(text) - .setContentIntent(pendingIntent) - .setGroup(GROUP_KEY) - .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) - .setOnlyAlertOnce(true) - .setAutoCancel(true) - .build() - - if (Build.VERSION.SDK_INT >= 33 && ActivityCompat.checkSelfPermission(context, - Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. - Log.e(TAG, "showNotification: require POST_NOTIFICATIONS permission") - Toast.makeText(context, R.string.notification_permission_text, Toast.LENGTH_LONG).show() - return - } - notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, - feed.hashCode(), - notification) - showGroupSummaryNotification(context, notificationManager) - } - - private fun showGroupSummaryNotification(context: Context, notificationManager: NotificationManagerCompat) { - val intent = Intent() - intent.setAction("NewEpisodes") - intent.setComponent(ComponentName(context, "ac.mdiq.podcini.activity.MainActivity")) - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - intent.putExtra("fragment_tag", "NewEpisodesFragment") - val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE) - - val notificationGroupSummary = NotificationCompat.Builder( - context, NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS) - .setSmallIcon(R.drawable.ic_notification_new) - .setContentTitle(context.getString(R.string.new_episode_notification_group_text)) - .setContentIntent(pendingIntent) - .setGroup(GROUP_KEY) - .setGroupSummary(true) - .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) - .setOnlyAlertOnce(true) - .setAutoCancel(true) - .build() - if (Build.VERSION.SDK_INT >= 33 && ActivityCompat.checkSelfPermission(context, - Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. - Log.e(TAG, "showGroupSummaryNotification: require POST_NOTIFICATIONS permission") - Toast.makeText(context, R.string.notification_permission_text, Toast.LENGTH_LONG).show() - return - } - notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, 0, notificationGroupSummary) - } - - private fun loadIcon(context: Context, feed: Feed): Bitmap? { - val iconSize = (128 * context.resources.displayMetrics.density).toInt() - return try { - if (!feed.imageUrl.isNullOrBlank()) Glide.with(context) - .asBitmap() - .load(feed.imageUrl) - .apply(RequestOptions().centerCrop()) - .submit(iconSize, iconSize) - .get() - else null - } catch (tr: Throwable) { - null - } - } - - private fun getNewEpisodeCount(feedId: Long): Int { - val adapter = PodDBAdapter.getInstance() - adapter.open() - val counters = adapter.getFeedCounters(FeedCounter.SHOW_NEW, feedId) - val episodeCount = if (counters.containsKey(feedId)) counters[feedId]!! else 0 - adapter.close() - return episodeCount - } - } -} diff --git a/app/src/main/java/ac/mdiq/podcini/playback/service/PlaybackService.kt b/app/src/main/java/ac/mdiq/podcini/playback/service/PlaybackService.kt index 31cf57e1..2d036bf6 100644 --- a/app/src/main/java/ac/mdiq/podcini/playback/service/PlaybackService.kt +++ b/app/src/main/java/ac/mdiq/podcini/playback/service/PlaybackService.kt @@ -253,6 +253,7 @@ class PlaybackService : MediaBrowserServiceCompat() { Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions +// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) @@ -590,6 +591,7 @@ class PlaybackService : MediaBrowserServiceCompat() { Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions +// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) @@ -1334,6 +1336,7 @@ class PlaybackService : MediaBrowserServiceCompat() { Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling // ActivityCompat#requestPermissions +// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) // here to request the missing permissions, and then overriding // public void onRequestPermissionsResult(int requestCode, String[] permissions, // int[] grantResults) diff --git a/app/src/main/java/ac/mdiq/podcini/preferences/UserPreferences.kt b/app/src/main/java/ac/mdiq/podcini/preferences/UserPreferences.kt index c6c28744..af830e41 100644 --- a/app/src/main/java/ac/mdiq/podcini/preferences/UserPreferences.kt +++ b/app/src/main/java/ac/mdiq/podcini/preferences/UserPreferences.kt @@ -251,7 +251,7 @@ object UserPreferences { @JvmStatic val feedCounterSetting: FeedCounter get() { - val value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FeedCounter.SHOW_NEW.id) + val value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FeedCounter.SHOW_UNPLAYED.id) return FeedCounter.fromOrdinal(value!!.toInt()) } diff --git a/app/src/main/java/ac/mdiq/podcini/preferences/fragments/NotificationPreferencesFragment.kt b/app/src/main/java/ac/mdiq/podcini/preferences/fragments/NotificationPreferencesFragment.kt index 6e8b10c1..8649be93 100644 --- a/app/src/main/java/ac/mdiq/podcini/preferences/fragments/NotificationPreferencesFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/preferences/fragments/NotificationPreferencesFragment.kt @@ -19,8 +19,7 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat() { } private fun setUpScreen() { - findPreference(ac.mdiq.podcini.preferences.fragments.NotificationPreferencesFragment.Companion.PREF_GPODNET_NOTIFICATIONS)!!.isEnabled = - SynchronizationSettings.isProviderConnected + findPreference(PREF_GPODNET_NOTIFICATIONS)!!.isEnabled = SynchronizationSettings.isProviderConnected } companion object { diff --git a/app/src/main/java/ac/mdiq/podcini/storage/DBReader.kt b/app/src/main/java/ac/mdiq/podcini/storage/DBReader.kt index 3640b16d..ac237872 100644 --- a/app/src/main/java/ac/mdiq/podcini/storage/DBReader.kt +++ b/app/src/main/java/ac/mdiq/podcini/storage/DBReader.kt @@ -141,6 +141,7 @@ object DBReader { * @param items The FeedItems whose Feed-objects should be loaded. */ private fun loadFeedDataOfFeedItemList(items: List) { + Log.d(TAG, "loadFeedDataOfFeedItemList called") val feedIndex: MutableMap = ArrayMap(feeds.size) val feedsCopy = ArrayList(feeds) for (feed in feedsCopy) { @@ -235,7 +236,7 @@ object DBReader { @JvmStatic fun getQueue(adapter: PodDBAdapter?): List { -// Log.d(TAG, "getQueue()") + Log.d(TAG, "getQueue(adapter)") adapter?.queueCursor.use { cursor -> val items = extractItemlistFromCursor(adapter, cursor) loadAdditionalFeedItemListData(items) @@ -323,6 +324,7 @@ object DBReader { @JvmStatic fun getTotalEpisodeCount(filter: FeedItemFilter?): Int { + Log.d(TAG, "getTotalEpisodeCount called") val adapter = getInstance() adapter.open() try { @@ -506,7 +508,7 @@ object DBReader { } return item } - return item + return null } /** @@ -582,19 +584,16 @@ object DBReader { * Does NOT load additional attributes like feed or queue state. */ private fun getFeedItemByGuidOrEpisodeUrl(guid: String?, episodeUrl: String, - adapter: PodDBAdapter? - ): FeedItem? { - if (adapter != null) { - adapter.getFeedItemCursor(guid, episodeUrl).use { cursor -> - if (!cursor.moveToNext()) { - return null - } - val list = extractItemlistFromCursor(adapter, cursor) - if (list.isNotEmpty()) { - return list[0] - } + adapter: PodDBAdapter?): FeedItem? { + adapter?.getFeedItemCursor(guid, episodeUrl)?.use { cursor -> + if (!cursor.moveToNext()) { return null } + val list = extractItemlistFromCursor(adapter, cursor) + if (list.isNotEmpty()) { + return list[0] + } + return null } return null } @@ -618,20 +617,18 @@ object DBReader { } private fun getImageAuthentication(imageUrl: String, adapter: PodDBAdapter?): String { - var credentials: String = "" - if (adapter != null) { - adapter.getImageAuthenticationCursor(imageUrl).use { cursor -> - if (cursor.moveToFirst()) { - val username = cursor.getString(0) - val password = cursor.getString(1) - credentials = if (!username.isNullOrEmpty() && password != null) { - "$username:$password" - } else { - "" - } + var credentials = "" + adapter?.getImageAuthenticationCursor(imageUrl)?.use { cursor -> + if (cursor.moveToFirst()) { + val username = cursor.getString(0) + val password = cursor.getString(1) + credentials = if (!username.isNullOrEmpty() && password != null) { + "$username:$password" } else { - credentials = "" + "" } + } else { + credentials = "" } } return credentials @@ -647,6 +644,7 @@ object DBReader { */ @JvmStatic fun getFeedItemByGuidOrEpisodeUrl(guid: String?, episodeUrl: String): FeedItem? { + Log.d(TAG, "getFeedItemByGuidOrEpisodeUrl called") val adapter = getInstance() adapter.open() try { @@ -705,19 +703,17 @@ object DBReader { } private fun loadChaptersOfFeedItem(adapter: PodDBAdapter?, item: FeedItem): List? { - if (adapter != null) { - adapter.getSimpleChaptersOfFeedItemCursor(item).use { cursor -> - val chaptersCount = cursor.count - if (chaptersCount == 0) { - item.chapters = null - return null - } - val chapters = ArrayList() - while (cursor.moveToNext()) { - chapters.add(ChapterCursorMapper.convert(cursor)) - } - return chapters + adapter?.getSimpleChaptersOfFeedItemCursor(item)?.use { cursor -> + val chaptersCount = cursor.count + if (chaptersCount == 0) { + item.chapters = null + return null } + val chapters = ArrayList() + while (cursor.moveToNext()) { + chapters.add(ChapterCursorMapper.convert(cursor)) + } + return chapters } return null } @@ -730,9 +726,9 @@ object DBReader { */ @JvmStatic fun getFeedMedia(mediaId: Long): FeedMedia? { + Log.d(TAG, "getFeedMedia called") val adapter = getInstance() adapter.open() - try { adapter.getSingleFeedMediaCursor(mediaId).use { mediaCursor -> if (!mediaCursor.moveToFirst()) { @@ -798,8 +794,7 @@ object DBReader { * @return The list of statistics objects */ fun getStatistics(includeMarkedAsPlayed: Boolean, - timeFilterFrom: Long, timeFilterTo: Long - ): StatisticsResult { + timeFilterFrom: Long, timeFilterTo: Long): StatisticsResult { val adapter = getInstance() adapter.open() diff --git a/app/src/main/java/ac/mdiq/podcini/storage/DBTasks.kt b/app/src/main/java/ac/mdiq/podcini/storage/DBTasks.kt index a7c9e54b..45b38fad 100644 --- a/app/src/main/java/ac/mdiq/podcini/storage/DBTasks.kt +++ b/app/src/main/java/ac/mdiq/podcini/storage/DBTasks.kt @@ -196,6 +196,7 @@ import java.util.concurrent.* @JvmStatic @Synchronized fun updateFeed(context: Context, newFeed: Feed, removeUnlistedItems: Boolean): Feed? { + Log.d(TAG, "updateFeed called") var resultFeed: Feed? val unlistedItems: MutableList = ArrayList() @@ -227,14 +228,6 @@ import java.util.concurrent.* savedFeed.preferences!!.updateFromOther(newFeed.preferences) } - // get the most recent date now, before we start changing the list -// only used to add to IN_Box??? -// val priorMostRecent = savedFeed.mostRecentItem -// var priorMostRecentDate: Date? = Date() -// if (priorMostRecent != null) { -// priorMostRecentDate = priorMostRecent.getPubDate() -// } - // Look for new or updated Items for (idx in newFeed.items.indices) { val item = newFeed.items[idx] @@ -298,18 +291,6 @@ import java.util.concurrent.* } else { savedFeed.items.add(idx, item) } - -// var action = savedFeed.preferences!!.newEpisodesAction -// if (action == NewEpisodesAction.GLOBAL) { -// action = newEpisodesAction -// } -// if (action == NewEpisodesAction.ADD_TO_INBOX -// && (item.getPubDate() == null || priorMostRecentDate == null || priorMostRecentDate.before( -// item.getPubDate()) || priorMostRecentDate == item.getPubDate())) { -// Log.d(TAG, "Marking item published on " + item.getPubDate() -// + " new, prior most recent date = " + priorMostRecentDate) -// item.setNew() -// } } } @@ -383,6 +364,7 @@ import java.util.concurrent.* */ @JvmStatic fun searchFeedItems(feedID: Long, query: String): FutureTask> { + Log.d(TAG, "searchFeedItems called") return FutureTask(object : QueryTask>() { override fun execute(adapter: PodDBAdapter?) { val searchResult = adapter?.searchItems(feedID, query) diff --git a/app/src/main/java/ac/mdiq/podcini/storage/DBWriter.kt b/app/src/main/java/ac/mdiq/podcini/storage/DBWriter.kt index 5b7344fa..42f6f27b 100644 --- a/app/src/main/java/ac/mdiq/podcini/storage/DBWriter.kt +++ b/app/src/main/java/ac/mdiq/podcini/storage/DBWriter.kt @@ -88,6 +88,7 @@ import java.util.concurrent.TimeUnit */ @JvmStatic fun deleteFeedMediaOfItem(context: Context, mediaId: Long): Future<*> { + Log.d(TAG, "deleteFeedMediaOfItem called") return runOnDbThread { val media = getFeedMedia(mediaId) if (media != null) { @@ -194,6 +195,7 @@ import java.util.concurrent.TimeUnit * Deleting media also removes the download log entries. */ fun deleteFeedItems(context: Context, items: List): Future<*> { + Log.d(TAG, "deleteFeedItems called") return runOnDbThread { deleteFeedItemsSynchronous(context, items) } } @@ -282,13 +284,6 @@ import java.util.concurrent.TimeUnit * @param media FeedMedia that should be added to the playback history. * @param date PlaybackCompletionDate for `media` */ - /** - * Adds a FeedMedia object to the playback history. A FeedMedia object is in the playback history if - * its playback completion date is set to a non-null value. This method will set the playback completion date to the - * current date regardless of the current value. - * - * @param media FeedMedia that should be added to the playback history. - */ @JvmOverloads fun addItemToPlaybackHistory(media: FeedMedia?, date: Date? = Date()): Future<*> { return runOnDbThread { @@ -311,6 +306,7 @@ import java.util.concurrent.TimeUnit * @param status The DownloadStatus object. */ fun addDownloadStatus(status: DownloadResult?): Future<*> { + Log.d(TAG, "addDownloadStatus called") return runOnDbThread { if (status != null) { val adapter = getInstance() @@ -335,6 +331,7 @@ import java.util.concurrent.TimeUnit @UnstableApi fun addQueueItemAt(context: Context, itemId: Long, index: Int, performAutoDownload: Boolean ): Future<*> { + Log.d(TAG, "addQueueItemAt called") return runOnDbThread { val adapter = getInstance() adapter.open() @@ -368,6 +365,7 @@ import java.util.concurrent.TimeUnit } fun addQueueItem(context: Context, markAsUnplayed: Boolean, vararg items: FeedItem): Future<*> { + Log.d(TAG, "addQueueItem called") val itemIds = LongList(items.size) for (item in items) { if (!item.hasMedia()) { @@ -403,8 +401,8 @@ import java.util.concurrent.TimeUnit * @param itemIds IDs of the FeedItem objects that should be added to the queue. */ @UnstableApi fun addQueueItem(context: Context, performAutoDownload: Boolean, - markAsUnplayed: Boolean, vararg itemIds: Long - ): Future<*> { + markAsUnplayed: Boolean, vararg itemIds: Long): Future<*> { + Log.d(TAG, "addQueueItem(context ...) called") return runOnDbThread { if (itemIds.isEmpty()) { return@runOnDbThread @@ -506,26 +504,20 @@ import java.util.concurrent.TimeUnit * @param item FeedItem that should be removed. */ @JvmStatic - fun removeQueueItem(context: Context, - performAutoDownload: Boolean, item: FeedItem - ): Future<*> { + fun removeQueueItem(context: Context, performAutoDownload: Boolean, item: FeedItem): Future<*> { return runOnDbThread { removeQueueItemSynchronous(context, performAutoDownload, item.id) } } @JvmStatic - fun removeQueueItem(context: Context, performAutoDownload: Boolean, - vararg itemIds: Long - ): Future<*> { + fun removeQueueItem(context: Context, performAutoDownload: Boolean, vararg itemIds: Long): Future<*> { return runOnDbThread { removeQueueItemSynchronous(context, performAutoDownload, *itemIds) } } @UnstableApi private fun removeQueueItemSynchronous(context: Context, - performAutoDownload: Boolean, - vararg itemIds: Long - ) { - if (itemIds.isEmpty()) { - return - } + performAutoDownload: Boolean, vararg itemIds: Long) { + Log.d(TAG, "removeQueueItemSynchronous called") + if (itemIds.isEmpty()) return + val adapter = getInstance() adapter.open() val queue = getQueue(adapter).toMutableList() @@ -643,9 +635,7 @@ import java.util.concurrent.TimeUnit * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size()) */ @JvmStatic - fun moveQueueItem(from: Int, - to: Int, broadcastUpdate: Boolean - ): Future<*> { + fun moveQueueItem(from: Int, to: Int, broadcastUpdate: Boolean): Future<*> { return runOnDbThread { moveQueueItemHelper(from, to, broadcastUpdate) } } @@ -661,9 +651,7 @@ import java.util.concurrent.TimeUnit * false if the caller wants to avoid unexpected updates of the GUI. * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size()) */ - private fun moveQueueItemHelper(from: Int, - to: Int, broadcastUpdate: Boolean - ) { + private fun moveQueueItemHelper(from: Int, to: Int, broadcastUpdate: Boolean) { val adapter = getInstance() adapter.open() val queue = getQueue(adapter).toMutableList() @@ -743,13 +731,11 @@ import java.util.concurrent.TimeUnit private fun markItemPlayed(itemId: Long, played: Int, mediaId: Long, - resetMediaPosition: Boolean - ): Future<*> { + resetMediaPosition: Boolean): Future<*> { return runOnDbThread { val adapter = getInstance() adapter.open() - adapter.setFeedItemRead(played, itemId, mediaId, - resetMediaPosition) + adapter.setFeedItemRead(played, itemId, mediaId, resetMediaPosition) adapter.close() EventBus.getDefault().post(UnreadItemsUpdateEvent()) } @@ -828,6 +814,7 @@ import java.util.concurrent.TimeUnit * @param media The FeedMedia object. */ fun setFeedMedia(media: FeedMedia?): Future<*> { + Log.d(TAG, "setFeedMedia called") return runOnDbThread { val adapter = getInstance() adapter.open() @@ -843,6 +830,7 @@ import java.util.concurrent.TimeUnit */ @JvmStatic fun setFeedMediaPlaybackInformation(media: FeedMedia?): Future<*> { + Log.d(TAG, "setFeedMediaPlaybackInformation called") return runOnDbThread { if (media != null) { val adapter = getInstance() @@ -861,6 +849,7 @@ import java.util.concurrent.TimeUnit */ @JvmStatic fun setFeedItem(item: FeedItem?): Future<*> { + Log.d(TAG, "setFeedItem called") return runOnDbThread { if (item != null) { val adapter = getInstance() @@ -905,6 +894,7 @@ import java.util.concurrent.TimeUnit } private fun indexInItemList(items: List, itemId: Long): Int { + Log.d(TAG, "indexInItemList called") for (i in items.indices) { val item = items[i] if (item?.id == itemId) { @@ -919,9 +909,7 @@ import java.util.concurrent.TimeUnit * * @param lastUpdateFailed true if last update failed */ - fun setFeedLastUpdateFailed(feedId: Long, - lastUpdateFailed: Boolean - ): Future<*> { + fun setFeedLastUpdateFailed(feedId: Long, lastUpdateFailed: Boolean): Future<*> { return runOnDbThread { val adapter = getInstance() adapter.open() @@ -974,9 +962,7 @@ import java.util.concurrent.TimeUnit * @param feedId The feed's ID * @param filterValues Values that represent properties to filter by */ - fun setFeedItemsFilter(feedId: Long, - filterValues: Set - ): Future<*> { + fun setFeedItemsFilter(feedId: Long, filterValues: Set): Future<*> { Log.d(TAG, "setFeedItemsFilter() called with: feedId = [$feedId], filterValues = [$filterValues]") return runOnDbThread { val adapter = getInstance() diff --git a/app/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt b/app/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt index 7b8e1874..f598a910 100644 --- a/app/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt +++ b/app/src/main/java/ac/mdiq/podcini/storage/database/PodDBAdapter.kt @@ -917,7 +917,7 @@ class PodDBAdapter private constructor() { fun getFeedCounters(setting: FeedCounter?, vararg feedIds: Long): Map { val whereRead = when (setting) { - FeedCounter.SHOW_NEW -> KEY_READ + "=" + FeedItem.NEW +// FeedCounter.SHOW_NEW -> KEY_READ + "=" + FeedItem.NEW FeedCounter.SHOW_UNPLAYED -> ("(" + KEY_READ + "=" + FeedItem.NEW + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")") FeedCounter.SHOW_DOWNLOADED -> "$KEY_DOWNLOADED=1" diff --git a/app/src/main/java/ac/mdiq/podcini/storage/model/feed/FeedCounter.kt b/app/src/main/java/ac/mdiq/podcini/storage/model/feed/FeedCounter.kt index 6ec22930..642a1564 100644 --- a/app/src/main/java/ac/mdiq/podcini/storage/model/feed/FeedCounter.kt +++ b/app/src/main/java/ac/mdiq/podcini/storage/model/feed/FeedCounter.kt @@ -1,7 +1,7 @@ package ac.mdiq.podcini.storage.model.feed enum class FeedCounter(val id: Int) { - SHOW_NEW(1), +// SHOW_NEW(1), SHOW_UNPLAYED(2), SHOW_NONE(3), SHOW_DOWNLOADED(4), diff --git a/app/src/main/java/ac/mdiq/podcini/ui/actions/FeedMultiSelectActionHandler.kt b/app/src/main/java/ac/mdiq/podcini/ui/actions/FeedMultiSelectActionHandler.kt index 285f0a8d..057f660b 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/actions/FeedMultiSelectActionHandler.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/actions/FeedMultiSelectActionHandler.kt @@ -28,9 +28,9 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v R.id.remove_feed -> { RemoveFeedDialog.show(activity, selectedItems) } - R.id.notify_new_episodes -> { - notifyNewEpisodesPrefHandler() - } +// R.id.notify_new_episodes -> { +// notifyNewEpisodesPrefHandler() +// } R.id.keep_updated -> { keepUpdatedPrefHandler() } @@ -52,20 +52,20 @@ class FeedMultiSelectActionHandler(private val activity: MainActivity, private v } } - private fun notifyNewEpisodesPrefHandler() { - val preferenceSwitchDialog = PreferenceSwitchDialog(activity, - activity.getString(R.string.episode_notification), - activity.getString(R.string.episode_notification_summary)) - - preferenceSwitchDialog.setOnPreferenceChangedListener(object: PreferenceSwitchDialog.OnPreferenceChangedListener { - @UnstableApi override fun preferenceChanged(enabled: Boolean) { - saveFeedPreferences { feedPreferences: FeedPreferences -> - feedPreferences.showEpisodeNotification = enabled - } - } - }) - preferenceSwitchDialog.openDialog() - } +// private fun notifyNewEpisodesPrefHandler() { +// val preferenceSwitchDialog = PreferenceSwitchDialog(activity, +// activity.getString(R.string.episode_notification), +// activity.getString(R.string.episode_notification_summary)) +// +// preferenceSwitchDialog.setOnPreferenceChangedListener(object: PreferenceSwitchDialog.OnPreferenceChangedListener { +// @UnstableApi override fun preferenceChanged(enabled: Boolean) { +// saveFeedPreferences { feedPreferences: FeedPreferences -> +// feedPreferences.showEpisodeNotification = enabled +// } +// } +// }) +// preferenceSwitchDialog.openDialog() +// } private fun autoDownloadPrefHandler() { val preferenceSwitchDialog = PreferenceSwitchDialog(activity, diff --git a/app/src/main/java/ac/mdiq/podcini/ui/activity/PreferenceActivity.kt b/app/src/main/java/ac/mdiq/podcini/ui/activity/PreferenceActivity.kt index 303839a1..20176bf7 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/activity/PreferenceActivity.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/activity/PreferenceActivity.kt @@ -78,7 +78,7 @@ class PreferenceActivity : AppCompatActivity(), SearchPreferenceResultListener { prefFragment = PlaybackPreferencesFragment() } R.xml.preferences_notifications -> { - prefFragment = ac.mdiq.podcini.preferences.fragments.NotificationPreferencesFragment() + prefFragment = NotificationPreferencesFragment() } R.xml.preferences_swipe -> { prefFragment = SwipePreferencesFragment() diff --git a/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt b/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt index 4a78a87a..959aa21e 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/activity/VideoplayerActivity.kt @@ -288,8 +288,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener { binding.videoView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION setupVideoControlsToggler() - window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN) + window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN) binding.videoPlayerContainer.setOnTouchListener(onVideoviewTouched) binding.videoPlayerContainer.viewTreeObserver.addOnGlobalLayoutListener { @@ -308,12 +307,10 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener { } private val onVideoviewTouched = OnTouchListener { v: View, event: MotionEvent -> - if (event.action != MotionEvent.ACTION_DOWN) { - return@OnTouchListener false - } - if (PictureInPictureUtil.isInPictureInPictureMode(this)) { - return@OnTouchListener true - } + if (event.action != MotionEvent.ACTION_DOWN) return@OnTouchListener false + + if (PictureInPictureUtil.isInPictureInPictureMode(this)) return@OnTouchListener true + videoControlsHider.removeCallbacks(hideVideoControls) if (System.currentTimeMillis() - lastScreenTap < 300) { @@ -333,9 +330,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener { } toggleVideoControlsVisibility() - if (videoControlsShowing) { - setupVideoControlsToggler() - } + if (videoControlsShowing) setupVideoControlsToggler() lastScreenTap = System.currentTimeMillis() true @@ -609,7 +604,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener { shareDialog.show(supportFragmentManager, "ShareEpisodeDialog") } item.itemId == R.id.playback_speed -> { - VariableSpeedDialog.newInstance(booleanArrayOf(true, false, true))?.show(supportFragmentManager, null) + VariableSpeedDialog.newInstance(booleanArrayOf(true, true, true))?.show(supportFragmentManager, null) } else -> { return false @@ -714,9 +709,7 @@ class VideoplayerActivity : CastEnabledActivity(), OnSeekBarChangeListener { //Hardware keyboard support override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { val currentFocus = currentFocus - if (currentFocus is EditText) { - return super.onKeyUp(keyCode, event) - } + if (currentFocus is EditText) return super.onKeyUp(keyCode, event) val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt index 7f725048..f4061f25 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/AudioPlayerFragment.kt @@ -137,7 +137,6 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar playerView2.setBackgroundColor( SurfaceColors.getColorForElevation(requireContext(), 8 * resources.displayMetrics.density)) -// itemDesrView = binding.itemDescription cardViewSeek = binding.cardViewSeek txtvSeek = binding.txtvSeek @@ -146,11 +145,7 @@ class AudioPlayerFragment : Fragment(), SeekBar.OnSeekBarChangeListener, Toolbar itemDescFrag = PlayerDetailsFragment() transaction.replace(R.id.itemDescription, itemDescFrag).commit() -// controller = externalPlayerFragment1.controller -// loadMediaInfo(false) EventBus.getDefault().register(this) - -// updateUi(controller?.getMedia()) return binding.root } diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt index afd70df0..47c79018 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/FeedSettingsFragment.kt @@ -11,7 +11,6 @@ import ac.mdiq.podcini.storage.model.feed.Feed import ac.mdiq.podcini.storage.model.feed.FeedFilter import ac.mdiq.podcini.storage.model.feed.FeedPreferences import ac.mdiq.podcini.storage.model.feed.FeedPreferences.AutoDeleteAction -import ac.mdiq.podcini.storage.model.feed.FeedPreferences.NewEpisodesAction import ac.mdiq.podcini.storage.model.feed.VolumeAdaptionSetting import ac.mdiq.podcini.ui.dialog.AuthenticationDialog import ac.mdiq.podcini.ui.dialog.EpisodeFilterDialog @@ -20,12 +19,9 @@ import ac.mdiq.podcini.ui.dialog.TagSettingsDialog import ac.mdiq.podcini.util.event.settings.SkipIntroEndingChangedEvent import ac.mdiq.podcini.util.event.settings.SpeedPresetChangedEvent import ac.mdiq.podcini.util.event.settings.VolumeAdaptionChangedEvent -import android.Manifest import android.content.DialogInterface import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri -import android.os.Build import android.os.Bundle import android.provider.Settings import android.util.Log @@ -36,7 +32,6 @@ import android.widget.CompoundButton import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.OptIn -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.media3.common.util.UnstableApi import androidx.preference.ListPreference @@ -159,7 +154,7 @@ class FeedSettingsFragment : Fragment() { setupEpisodeFilterPreference() setupPlaybackSpeedPreference() setupFeedAutoSkipPreference() - setupEpisodeNotificationPreference() +// setupEpisodeNotificationPreference() setupTags() updateAutoDeleteSummary() @@ -440,25 +435,25 @@ class FeedSettingsFragment : Fragment() { } } - @OptIn(UnstableApi::class) private fun setupEpisodeNotificationPreference() { - val pref = findPreference("episodeNotification") - - pref!!.isChecked = feedPreferences!!.showEpisodeNotification - pref.onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> - if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission( - requireContext(), - Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) - return@OnPreferenceChangeListener false - } - val checked = newValue == true - feedPreferences!!.showEpisodeNotification = checked - if (feedPreferences != null) DBWriter.setFeedPreferences(feedPreferences!!) - pref.isChecked = checked - false - } - } +// @OptIn(UnstableApi::class) private fun setupEpisodeNotificationPreference() { +// val pref = findPreference("episodeNotification") +// +// pref!!.isChecked = feedPreferences!!.showEpisodeNotification +// pref.onPreferenceChangeListener = +// Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> +// if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission( +// requireContext(), +// Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { +// requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) +// return@OnPreferenceChangeListener false +// } +// val checked = newValue == true +// feedPreferences!!.showEpisodeNotification = checked +// if (feedPreferences != null) DBWriter.setFeedPreferences(feedPreferences!!) +// pref.isChecked = checked +// false +// } +// } companion object { private val PREF_EPISODE_FILTER: CharSequence = "episodeFilter" diff --git a/app/src/main/java/ac/mdiq/podcini/ui/fragment/SubscriptionFragment.kt b/app/src/main/java/ac/mdiq/podcini/ui/fragment/SubscriptionFragment.kt index 9c6f0ca7..0c61a326 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/fragment/SubscriptionFragment.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/fragment/SubscriptionFragment.kt @@ -135,7 +135,7 @@ class SubscriptionFragment : Fragment(), Toolbar.OnMenuItemClickListener, Select catSpinner.setAdapter(catAdapter) catSpinner.setSelection(catAdapter.getPosition("All")) catSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { tagFilterIndex = position filterOnTag() } diff --git a/app/src/main/java/ac/mdiq/podcini/ui/utils/NotificationUtils.kt b/app/src/main/java/ac/mdiq/podcini/ui/utils/NotificationUtils.kt index a9e1d50b..afcb9aec 100644 --- a/app/src/main/java/ac/mdiq/podcini/ui/utils/NotificationUtils.kt +++ b/app/src/main/java/ac/mdiq/podcini/ui/utils/NotificationUtils.kt @@ -23,8 +23,9 @@ object NotificationUtils { val mNotificationManager = NotificationManagerCompat.from(context) val channelGroups = listOf( - createGroupErrors(context), - createGroupNews(context)) + createGroupErrors(context) +// createGroupNews(context) + ) mNotificationManager.createNotificationChannelGroupsCompat(channelGroups) val channels = listOf( @@ -32,10 +33,13 @@ object NotificationUtils { createChannelDownloading(context), createChannelPlaying(context), createChannelError(context), - createChannelSyncError(context), - createChannelEpisodeNotification(context)) - + createChannelSyncError(context) +// createChannelEpisodeNotification(context) + ) mNotificationManager.createNotificationChannelsCompat(channels) + + mNotificationManager.deleteNotificationChannelGroup(GROUP_ID_NEWS) + mNotificationManager.deleteNotificationChannel(CHANNEL_ID_EPISODE_NOTIFICATIONS) } private fun createChannelUserAction(c: Context): NotificationChannelCompat { @@ -93,14 +97,14 @@ object NotificationUtils { return notificationChannel.build() } - private fun createChannelEpisodeNotification(c: Context): NotificationChannelCompat { - return NotificationChannelCompat.Builder( - CHANNEL_ID_EPISODE_NOTIFICATIONS, NotificationManagerCompat.IMPORTANCE_DEFAULT) - .setName(c.getString(R.string.notification_channel_new_episode)) - .setDescription(c.getString(R.string.notification_channel_new_episode_description)) - .setGroup(GROUP_ID_NEWS) - .build() - } +// private fun createChannelEpisodeNotification(c: Context): NotificationChannelCompat { +// return NotificationChannelCompat.Builder( +// CHANNEL_ID_EPISODE_NOTIFICATIONS, NotificationManagerCompat.IMPORTANCE_DEFAULT) +// .setName(c.getString(R.string.notification_channel_new_episode)) +// .setDescription(c.getString(R.string.notification_channel_new_episode_description)) +// .setGroup(GROUP_ID_NEWS) +// .build() +// } private fun createGroupErrors(c: Context): NotificationChannelGroupCompat { return NotificationChannelGroupCompat.Builder(GROUP_ID_ERRORS) @@ -108,9 +112,9 @@ object NotificationUtils { .build() } - private fun createGroupNews(c: Context): NotificationChannelGroupCompat { - return NotificationChannelGroupCompat.Builder(GROUP_ID_NEWS) - .setName(c.getString(R.string.notification_group_news)) - .build() - } +// private fun createGroupNews(c: Context): NotificationChannelGroupCompat { +// return NotificationChannelGroupCompat.Builder(GROUP_ID_NEWS) +// .setName(c.getString(R.string.notification_group_news)) +// .build() +// } } diff --git a/app/src/main/res/layout/speed_select_dialog.xml b/app/src/main/res/layout/speed_select_dialog.xml index d32ba457..442e02c9 100644 --- a/app/src/main/res/layout/speed_select_dialog.xml +++ b/app/src/main/res/layout/speed_select_dialog.xml @@ -20,6 +20,7 @@ diff --git a/app/src/main/res/menu/nav_feed_action_speeddial.xml b/app/src/main/res/menu/nav_feed_action_speeddial.xml index 250d12bc..e10389f7 100644 --- a/app/src/main/res/menu/nav_feed_action_speeddial.xml +++ b/app/src/main/res/menu/nav_feed_action_speeddial.xml @@ -10,11 +10,11 @@ android:menuCategory="container" android:title="@string/keep_updated" android:icon="@drawable/ic_refresh"/> - + + + + + - + + + + + + +